@saleso.innovations/bridge 0.1.17 → 0.1.19
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/activeConversation.d.ts +3 -1
- package/dist/activeConversation.d.ts.map +1 -1
- package/dist/activeConversation.js +2 -2
- package/dist/cli.js +15 -0
- package/dist/client.d.ts +2 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +39 -5
- package/dist/cronWatcher.d.ts.map +1 -1
- package/dist/cronWatcher.js +53 -25
- package/dist/hermesForwarder.d.ts.map +1 -1
- package/dist/hermesForwarder.js +3 -2
- package/package.json +1 -1
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.19
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
## Manual usage
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type SavedAgentCredentials } from "./credentials.js";
|
|
2
|
-
export declare function resolveActiveConversationId(credentials?: SavedAgentCredentials
|
|
2
|
+
export declare function resolveActiveConversationId(credentials?: SavedAgentCredentials, options?: {
|
|
3
|
+
forceRefresh?: boolean;
|
|
4
|
+
}): Promise<string>;
|
|
3
5
|
export declare function rememberConversationId(conversationId: string): void;
|
|
4
6
|
//# sourceMappingURL=activeConversation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activeConversation.d.ts","sourceRoot":"","sources":["../src/activeConversation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqC,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEjG,wBAAsB,2BAA2B,CAC/C,WAAW,CAAC,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"activeConversation.d.ts","sourceRoot":"","sources":["../src/activeConversation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqC,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEjG,wBAAsB,2BAA2B,CAC/C,WAAW,CAAC,EAAE,qBAAqB,EACnC,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,OAAO,CAAC,MAAM,CAAC,CA+BjB;AAED,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAEnE"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { convexSiteUrlFromEnv } from "./resolve.js";
|
|
2
2
|
import { hashToken } from "./token.js";
|
|
3
3
|
import { loadCredentials, patchCredentials } from "./credentials.js";
|
|
4
|
-
export async function resolveActiveConversationId(credentials) {
|
|
4
|
+
export async function resolveActiveConversationId(credentials, options = {}) {
|
|
5
5
|
const resolved = credentials ?? loadCredentials();
|
|
6
6
|
if (!resolved) {
|
|
7
7
|
throw new Error("No saved Cleos agent credentials");
|
|
8
8
|
}
|
|
9
|
-
if (resolved.conversationId) {
|
|
9
|
+
if (resolved.conversationId && !options.forceRefresh) {
|
|
10
10
|
return resolved.conversationId;
|
|
11
11
|
}
|
|
12
12
|
const convexSiteUrl = resolved.convexSiteUrl ?? convexSiteUrlFromEnv();
|
package/dist/cli.js
CHANGED
|
@@ -81,6 +81,21 @@ async function main() {
|
|
|
81
81
|
}
|
|
82
82
|
const session = await reconnectHermesAgent({ onUserMessage });
|
|
83
83
|
try {
|
|
84
|
+
if (process.platform !== "win32") {
|
|
85
|
+
try {
|
|
86
|
+
const { execSync } = await import("node:child_process");
|
|
87
|
+
const active = execSync("systemctl is-active cleos-bridge.service", {
|
|
88
|
+
encoding: "utf8",
|
|
89
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
90
|
+
}).trim();
|
|
91
|
+
if (active === "active") {
|
|
92
|
+
console.error("Warning: cleos-bridge.service is running. Stop it first to avoid relay disconnects:\n systemctl stop cleos-bridge.service");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// systemctl unavailable or service not installed.
|
|
97
|
+
}
|
|
98
|
+
}
|
|
84
99
|
const summary = await backfillCronDeliveries(session, { reset });
|
|
85
100
|
console.log(JSON.stringify({ event: "cleos-bridge.cron-backfill.complete", ...summary }, null, 2));
|
|
86
101
|
if (summary.remainingCount > 0) {
|
package/dist/client.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export type AgentFailedPayload = {
|
|
|
37
37
|
export type AgentReply = {
|
|
38
38
|
delta: (text: string, sequence: number) => void;
|
|
39
39
|
activity: (activity: AgentActivityPayload) => void;
|
|
40
|
-
complete: (text: string, sequence: number, attachments?: UserMessageAttachment[]) => void;
|
|
40
|
+
complete: (text: string, sequence: number, attachments?: UserMessageAttachment[], hermesAssistantMessageId?: string) => void;
|
|
41
41
|
failed: (failure: AgentFailedPayload) => void;
|
|
42
42
|
};
|
|
43
43
|
export type CronDeliveryMeta = {
|
|
@@ -51,7 +51,7 @@ export type ConnectResult = {
|
|
|
51
51
|
agentToken: string;
|
|
52
52
|
close: () => void;
|
|
53
53
|
closed: Promise<void>;
|
|
54
|
-
deliverCronResult: (content: string, meta: CronDeliveryMeta) => void
|
|
54
|
+
deliverCronResult: (content: string, meta: CronDeliveryMeta) => Promise<void>;
|
|
55
55
|
};
|
|
56
56
|
export declare function pairCleosAgent(options: Omit<ConnectOptions, "onUserMessage">): Promise<{
|
|
57
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,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,YAAY,EAAE,cAAc,GAAG,gBAAgB,CAAC;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,QAAQ,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,
|
|
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, attachments) {
|
|
76
|
+
complete(text, sequence, attachments, hermesAssistantMessageId) {
|
|
76
77
|
ws.send(JSON.stringify({
|
|
77
78
|
type: "agent.message",
|
|
78
79
|
agentId,
|
|
@@ -82,6 +83,9 @@ function createReplySender(ws, agentId, conversationId, messageId) {
|
|
|
82
83
|
sequence,
|
|
83
84
|
final: true,
|
|
84
85
|
...(attachments && attachments.length > 0 ? { attachments } : {}),
|
|
86
|
+
...(hermesAssistantMessageId
|
|
87
|
+
? { metadata: { hermes: { assistantMessageId: hermesAssistantMessageId } } }
|
|
88
|
+
: {}),
|
|
85
89
|
}));
|
|
86
90
|
},
|
|
87
91
|
failed(failure) {
|
|
@@ -166,6 +170,7 @@ function userSafeHermesError(error) {
|
|
|
166
170
|
}
|
|
167
171
|
async function openAgentConnection(options) {
|
|
168
172
|
const ws = new WebSocket(options.relayWsUrl);
|
|
173
|
+
const pendingAcks = new Map();
|
|
169
174
|
let closedResolve = null;
|
|
170
175
|
const closed = new Promise((resolve) => {
|
|
171
176
|
closedResolve = resolve;
|
|
@@ -183,6 +188,16 @@ async function openAgentConnection(options) {
|
|
|
183
188
|
ws.on("message", (raw) => {
|
|
184
189
|
void (async () => {
|
|
185
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
|
+
const message = typeof envelope.message === "string" ? envelope.message : undefined;
|
|
197
|
+
resolveAck(envelope.ok === true, message);
|
|
198
|
+
}
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
186
201
|
if (envelope.type === "hermes.command") {
|
|
187
202
|
await handleHermesCommandEnvelope(ws, envelope, options.agentId);
|
|
188
203
|
return;
|
|
@@ -224,6 +239,10 @@ async function openAgentConnection(options) {
|
|
|
224
239
|
}, 30_000);
|
|
225
240
|
ws.on("close", () => {
|
|
226
241
|
clearInterval(heartbeat);
|
|
242
|
+
for (const [requestId, resolveAck] of pendingAcks.entries()) {
|
|
243
|
+
pendingAcks.delete(requestId);
|
|
244
|
+
resolveAck(false);
|
|
245
|
+
}
|
|
227
246
|
closedResolve?.();
|
|
228
247
|
});
|
|
229
248
|
return {
|
|
@@ -234,11 +253,26 @@ async function openAgentConnection(options) {
|
|
|
234
253
|
ws.close();
|
|
235
254
|
},
|
|
236
255
|
closed,
|
|
237
|
-
deliverCronResult(content, meta) {
|
|
256
|
+
async deliverCronResult(content, meta) {
|
|
238
257
|
if (ws.readyState !== WebSocket.OPEN) {
|
|
239
258
|
throw new Error("Cleos relay connection is not open");
|
|
240
259
|
}
|
|
241
|
-
|
|
260
|
+
const messageId = randomUUID();
|
|
261
|
+
await new Promise((resolve, reject) => {
|
|
262
|
+
const timer = setTimeout(() => {
|
|
263
|
+
pendingAcks.delete(messageId);
|
|
264
|
+
reject(new Error("Cron delivery ack timed out"));
|
|
265
|
+
}, CRON_DELIVERY_TIMEOUT_MS);
|
|
266
|
+
pendingAcks.set(messageId, (ok, failureMessage) => {
|
|
267
|
+
clearTimeout(timer);
|
|
268
|
+
if (ok) {
|
|
269
|
+
resolve();
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
reject(new Error(failureMessage ?? "Cron delivery persist failed"));
|
|
273
|
+
});
|
|
274
|
+
sendCronResult(ws, options.agentId, messageId, content, meta);
|
|
275
|
+
});
|
|
242
276
|
},
|
|
243
277
|
};
|
|
244
278
|
}
|
|
@@ -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;AA+JD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,IAAI,CA4BxE;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,CAmBD"}
|
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;
|
|
@@ -114,7 +121,7 @@ function sleep(ms) {
|
|
|
114
121
|
function isRelayNotOpenError(error) {
|
|
115
122
|
return error instanceof Error && error.message === "Cleos relay connection is not open";
|
|
116
123
|
}
|
|
117
|
-
async function deliverPendingFiles(session, delivered,
|
|
124
|
+
async function deliverPendingFiles(session, delivered, conversationRef, options) {
|
|
118
125
|
const jobNames = loadHermesCronJobs();
|
|
119
126
|
for (const filePath of listCronOutputFiles()) {
|
|
120
127
|
const key = relativeOutputKey(filePath);
|
|
@@ -129,24 +136,50 @@ async function deliverPendingFiles(session, delivered, conversationId, options)
|
|
|
129
136
|
writeDeliveredIndex(delivered);
|
|
130
137
|
continue;
|
|
131
138
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
let retriedAfterConversationRefresh = false;
|
|
140
|
+
let deliveredSuccessfully = false;
|
|
141
|
+
while (true) {
|
|
142
|
+
try {
|
|
143
|
+
await session.deliverCronResult(content, {
|
|
144
|
+
conversationId: conversationRef.value,
|
|
145
|
+
jobId,
|
|
146
|
+
jobName,
|
|
147
|
+
runAt: parseRunAtFromFileName(filePath),
|
|
148
|
+
});
|
|
149
|
+
deliveredSuccessfully = true;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
if (isRelayNotOpenError(error)) {
|
|
154
|
+
console.log(JSON.stringify({
|
|
155
|
+
event: "cleos-bridge.cron-deferred",
|
|
156
|
+
file: key,
|
|
157
|
+
reason: "relay_not_open",
|
|
158
|
+
}));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
162
|
+
const shouldRefreshConversation = !retriedAfterConversationRefresh
|
|
163
|
+
&& (message.includes("Invalid relay message target")
|
|
164
|
+
|| message.includes("Active conversation")
|
|
165
|
+
|| message.includes("Cron delivery persist failed"));
|
|
166
|
+
if (shouldRefreshConversation) {
|
|
167
|
+
conversationRef.value = await resolveActiveConversationId(undefined, { forceRefresh: true });
|
|
168
|
+
retriedAfterConversationRefresh = true;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
options.onError?.(message);
|
|
172
|
+
console.error(JSON.stringify({
|
|
173
|
+
event: "cleos-bridge.cron-delivery-failed",
|
|
144
174
|
file: key,
|
|
145
|
-
|
|
175
|
+
message,
|
|
176
|
+
conversationId: conversationRef.value,
|
|
146
177
|
}));
|
|
147
|
-
|
|
178
|
+
break;
|
|
148
179
|
}
|
|
149
|
-
|
|
180
|
+
}
|
|
181
|
+
if (!deliveredSuccessfully) {
|
|
182
|
+
continue;
|
|
150
183
|
}
|
|
151
184
|
delivered.add(key);
|
|
152
185
|
writeDeliveredIndex(delivered);
|
|
@@ -168,10 +201,8 @@ export function startCronWatcher(options) {
|
|
|
168
201
|
if (stopped)
|
|
169
202
|
return;
|
|
170
203
|
try {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
await deliverPendingFiles(options.session, delivered, conversationId, options);
|
|
204
|
+
conversationId = await resolveActiveConversationId(undefined, { forceRefresh: !conversationId });
|
|
205
|
+
await deliverPendingFiles(options.session, delivered, { value: conversationId }, options);
|
|
175
206
|
}
|
|
176
207
|
catch (error) {
|
|
177
208
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -192,12 +223,9 @@ export async function runCronBackfill(session, resetIndex) {
|
|
|
192
223
|
const clearedEntries = resetIndex ? clearDeliveredIndex() : 0;
|
|
193
224
|
const delivered = readDeliveredIndex();
|
|
194
225
|
const pendingAfterReset = listPendingCronFiles(delivered).length;
|
|
195
|
-
let conversationId =
|
|
196
|
-
if (!conversationId) {
|
|
197
|
-
conversationId = await resolveActiveConversationId();
|
|
198
|
-
}
|
|
226
|
+
let conversationId = await resolveActiveConversationId(undefined, { forceRefresh: true });
|
|
199
227
|
const deliveredBefore = delivered.size;
|
|
200
|
-
await deliverPendingFiles(session, delivered, conversationId, {});
|
|
228
|
+
await deliverPendingFiles(session, delivered, { value: conversationId }, {});
|
|
201
229
|
const deliveredCount = delivered.size - deliveredBefore;
|
|
202
230
|
const remainingCount = listPendingCronFiles(delivered).length;
|
|
203
231
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hermesForwarder.d.ts","sourceRoot":"","sources":["../src/hermesForwarder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAyB,eAAe,EAAE,MAAM,aAAa,CAAC;AAWtF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAkBF,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,sBAA2B,GAAG;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf,CAUA;AA+MD,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"hermesForwarder.d.ts","sourceRoot":"","sources":["../src/hermesForwarder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAyB,eAAe,EAAE,MAAM,aAAa,CAAC;AAWtF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAkBF,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,sBAA2B,GAAG;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf,CAUA;AA+MD,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,CA6E9B;AAED,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,sBAA2B,IAC/D,SAAS,MAAM,EAAE,MAAM,eAAe,EAAE,OAAO,UAAU,KAAG,OAAO,CAAC,IAAI,CAAC,CAMxF"}
|
package/dist/hermesForwarder.js
CHANGED
|
@@ -102,7 +102,7 @@ function processSseEventBlock(eventBlock, reply, counters, onTextDelta) {
|
|
|
102
102
|
try {
|
|
103
103
|
const payload = JSON.parse(data);
|
|
104
104
|
const delta = extractDeltaFromChunk(payload);
|
|
105
|
-
if (delta) {
|
|
105
|
+
if (delta && delta.trim()) {
|
|
106
106
|
onTextDelta(delta);
|
|
107
107
|
reply.delta(delta, counters.textSequence);
|
|
108
108
|
counters.textSequence += 1;
|
|
@@ -262,7 +262,8 @@ export async function forwardToHermes(content, meta, reply, options = {}) {
|
|
|
262
262
|
const mediaRefs = parseMediaReferences(fullText);
|
|
263
263
|
const attachments = mediaRefs.length > 0 ? await uploadMediaAttachments(meta.agentId, mediaRefs) : [];
|
|
264
264
|
const displayText = attachments.length > 0 ? stripMediaReferences(fullText, mediaRefs) : fullText.trim() || fullText;
|
|
265
|
-
|
|
265
|
+
const { assistantMessageId } = getLatestTurnMessageIds(resolvedSessionId);
|
|
266
|
+
reply.complete(displayText, counters.textSequence, attachments.length > 0 ? attachments : undefined, assistantMessageId !== undefined ? String(assistantMessageId) : undefined);
|
|
266
267
|
await linkTurnToConvex(meta, resolvedSessionId);
|
|
267
268
|
return { sessionId: resolvedSessionId };
|
|
268
269
|
}
|