Skip to content

Commit 4814874

Browse files
authored
Merge branch 'develop' into 1213-fix-chat-stuck-loop-bug
2 parents f066107 + aac570b commit 4814874

File tree

7 files changed

+112
-10
lines changed

7 files changed

+112
-10
lines changed

.vscode/settings.json

+11
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,16 @@
4343
},
4444
"[shellscript]": {
4545
"editor.defaultFormatter": "foxundermoon.shell-format"
46+
},
47+
"explorer.fileNesting.enabled": true,
48+
"explorer.fileNesting.patterns": {
49+
"*.ts": "${capture}.js",
50+
"*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts",
51+
"*.jsx": "${capture}.js",
52+
"*.tsx": "${capture}.ts",
53+
"tsconfig.json": "tsconfig.*.json",
54+
"package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb,pnpm-workspace.yaml",
55+
"README.md": "*.md",
56+
"Dockerfile": "docker-compose-docs.yaml,docker-compose.yaml,Dockerfile.docs"
4657
}
4758
}

agent/src/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,11 @@ export function getTokenForProvider(
449449
character.settings?.secrets?.INFERA_API_KEY ||
450450
settings.INFERA_API_KEY
451451
);
452+
case ModelProviderName.DEEPSEEK:
453+
return (
454+
character.settings?.secrets?.DEEPSEEK_API_KEY ||
455+
settings.DEEPSEEK_API_KEY
456+
);
452457
default:
453458
const errorMessage = `Failed to get token - unsupported model provider: ${provider}`;
454459
elizaLogger.error(errorMessage);

packages/client-direct/src/api.ts

+54-7
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,46 @@ import {
66
AgentRuntime,
77
elizaLogger,
88
getEnvVariable,
9+
UUID,
910
validateCharacterConfig,
1011
ServiceType,
1112
} from "@elizaos/core";
1213

1314
import { TeeLogQuery, TeeLogService } from "@elizaos/plugin-tee-log";
1415
import { REST, Routes } from "discord.js";
1516
import { DirectClient } from ".";
16-
import { stringToUuid } from "@elizaos/core";
17+
import { validateUuid } from "@elizaos/core";
18+
19+
interface UUIDParams {
20+
agentId: UUID;
21+
roomId?: UUID;
22+
}
23+
24+
function validateUUIDParams(
25+
params: { agentId: string; roomId?: string },
26+
res: express.Response
27+
): UUIDParams | null {
28+
const agentId = validateUuid(params.agentId);
29+
if (!agentId) {
30+
res.status(400).json({
31+
error: "Invalid AgentId format. Expected to be a UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
32+
});
33+
return null;
34+
}
35+
36+
if (params.roomId) {
37+
const roomId = validateUuid(params.roomId);
38+
if (!roomId) {
39+
res.status(400).json({
40+
error: "Invalid RoomId format. Expected to be a UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
41+
});
42+
return null;
43+
}
44+
return { agentId, roomId };
45+
}
46+
47+
return { agentId };
48+
}
1749

1850
export function createApiRouter(
1951
agents: Map<string, AgentRuntime>,
@@ -48,7 +80,11 @@ export function createApiRouter(
4880
});
4981

5082
router.get("/agents/:agentId", (req, res) => {
51-
const agentId = req.params.agentId;
83+
const { agentId } = validateUUIDParams(req.params, res) ?? {
84+
agentId: null,
85+
};
86+
if (!agentId) return;
87+
5288
const agent = agents.get(agentId);
5389

5490
if (!agent) {
@@ -68,8 +104,11 @@ export function createApiRouter(
68104
});
69105

70106
router.post("/agents/:agentId/set", async (req, res) => {
71-
const agentId = req.params.agentId;
72-
console.log("agentId", agentId);
107+
const { agentId } = validateUUIDParams(req.params, res) ?? {
108+
agentId: null,
109+
};
110+
if (!agentId) return;
111+
73112
let agent: AgentRuntime = agents.get(agentId);
74113

75114
// update character
@@ -104,7 +143,11 @@ export function createApiRouter(
104143
});
105144

106145
router.get("/agents/:agentId/channels", async (req, res) => {
107-
const agentId = req.params.agentId;
146+
const { agentId } = validateUUIDParams(req.params, res) ?? {
147+
agentId: null,
148+
};
149+
if (!agentId) return;
150+
108151
const runtime = agents.get(agentId);
109152

110153
if (!runtime) {
@@ -130,8 +173,12 @@ export function createApiRouter(
130173
});
131174

132175
router.get("/agents/:agentId/:roomId/memories", async (req, res) => {
133-
const agentId = req.params.agentId;
134-
const roomId = stringToUuid(req.params.roomId);
176+
const { agentId, roomId } = validateUUIDParams(req.params, res) ?? {
177+
agentId: null,
178+
roomId: null,
179+
};
180+
if (!agentId || !roomId) return;
181+
135182
let runtime = agents.get(agentId);
136183

137184
// if runtime is null, look for runtime with the same name

packages/client-twitter/src/utils.ts

+32-2
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,18 @@ export async function sendTweet(
212212
})
213213
);
214214
}
215+
216+
const cleanChunk = deduplicateMentions(chunk.trim())
217+
215218
const result = await client.requestQueue.add(async () =>
216219
isLongTweet
217220
? client.twitterClient.sendLongTweet(
218-
chunk.trim(),
221+
cleanChunk,
219222
previousTweetId,
220223
mediaData
221224
)
222225
: client.twitterClient.sendTweet(
223-
chunk.trim(),
226+
cleanChunk,
224227
previousTweetId,
225228
mediaData
226229
)
@@ -397,6 +400,33 @@ function splitSentencesAndWords(text: string, maxLength: number): string[] {
397400
return chunks;
398401
}
399402

403+
function deduplicateMentions(paragraph: string) {
404+
// Regex to match mentions at the beginning of the string
405+
const mentionRegex = /^@(\w+)(?:\s+@(\w+))*(\s+|$)/;
406+
407+
// Find all matches
408+
const matches = paragraph.match(mentionRegex);
409+
410+
if (!matches) {
411+
return paragraph; // If no matches, return the original string
412+
}
413+
414+
// Extract mentions from the match groups
415+
let mentions = matches.slice(1).filter(Boolean) as string[];
416+
417+
// Deduplicate mentions
418+
mentions = [...new Set(mentions)];
419+
420+
// Reconstruct the string with deduplicated mentions
421+
const uniqueMentionsString = `@${mentions.join(' ')}`;
422+
423+
// Find where the mentions end in the original string
424+
const endOfMentions = paragraph.indexOf(matches[0]) + matches[0].length;
425+
426+
// Construct the result by combining unique mentions with the rest of the string
427+
return uniqueMentionsString + paragraph.slice(endOfMentions);
428+
}
429+
400430
function restoreUrls(
401431
chunks: string[],
402432
placeholderMap: Map<string, string>

packages/core/src/uuid.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { sha1 } from "js-sha1";
22
import { UUID } from "./types.ts";
3+
import { z } from "zod";
4+
5+
export const uuidSchema = z.string().uuid() as z.ZodType<UUID>;
6+
7+
export function validateUuid(value: unknown): UUID | null {
8+
const result = uuidSchema.safeParse(value);
9+
return result.success ? result.data : null;
10+
}
311

412
export function stringToUuid(target: string | number): UUID {
513
if (typeof target === "number") {

packages/plugin-tts/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"dependencies": {
2222
"@elizaos/core": "workspace:*",
2323
"tsup": "8.3.5",
24+
"langdetect": "0.2.1",
2425
"whatwg-url": "7.1.0"
2526
},
2627
"scripts": {

pnpm-lock.yaml

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)