appback-remoteagent 0.13.14 → 0.13.16
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/dist/bot.js +23 -11
- package/dist/services/agent-memory-service.js +0 -68
- package/package.json +1 -1
package/dist/bot.js
CHANGED
|
@@ -886,14 +886,6 @@ ${bridge.formatStatus(mapping)}`);
|
|
|
886
886
|
if (!text) {
|
|
887
887
|
return;
|
|
888
888
|
}
|
|
889
|
-
if (mapping) {
|
|
890
|
-
const localStatus = await memoryService.formatLocalStatusQuestion(mapping.session, text);
|
|
891
|
-
if (localStatus) {
|
|
892
|
-
await bridge.logSystem(botId, chatId, "Answered local session status without provider execution.");
|
|
893
|
-
await reply(ctx, localStatus);
|
|
894
|
-
return;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
889
|
if (isRemoteShellMessage(text)) {
|
|
898
890
|
const shellRequest = parseRemoteShellRequest(text);
|
|
899
891
|
if (!shellRequest) {
|
|
@@ -1383,7 +1375,7 @@ function renderTelegramHtml(text) {
|
|
|
1383
1375
|
for (const line of lines) {
|
|
1384
1376
|
if (/^```\w*\s*$/.test(line.trim())) {
|
|
1385
1377
|
if (codeFence) {
|
|
1386
|
-
rendered.push(
|
|
1378
|
+
rendered.push(renderTelegramCodeFenceHtml(codeFence.join("\n")));
|
|
1387
1379
|
codeFence = undefined;
|
|
1388
1380
|
}
|
|
1389
1381
|
else {
|
|
@@ -1398,25 +1390,45 @@ function renderTelegramHtml(text) {
|
|
|
1398
1390
|
rendered.push(renderTelegramInlineHtml(line));
|
|
1399
1391
|
}
|
|
1400
1392
|
if (codeFence) {
|
|
1401
|
-
rendered.push(
|
|
1393
|
+
rendered.push(renderTelegramCodeFenceHtml(codeFence.join("\n")));
|
|
1402
1394
|
}
|
|
1403
1395
|
return rendered.join("\n");
|
|
1404
1396
|
}
|
|
1397
|
+
function renderTelegramCodeFenceHtml(content) {
|
|
1398
|
+
if (containsUrl(content)) {
|
|
1399
|
+
return content.split(/\r?\n/).map((line) => renderTelegramInlineHtml(line)).join("\n");
|
|
1400
|
+
}
|
|
1401
|
+
return `<pre>${escapeTelegramHtml(content)}</pre>`;
|
|
1402
|
+
}
|
|
1405
1403
|
function renderTelegramInlineHtml(line) {
|
|
1406
1404
|
const parts = line.split(/(`[^`\n]+`)/g);
|
|
1407
1405
|
return parts.map((part) => {
|
|
1408
1406
|
if (part.startsWith("`") && part.endsWith("`") && part.length >= 2) {
|
|
1409
1407
|
return `<code>${escapeTelegramHtml(part.slice(1, -1))}</code>`;
|
|
1410
1408
|
}
|
|
1411
|
-
return
|
|
1409
|
+
return renderTelegramTextLinks(part);
|
|
1412
1410
|
}).join("");
|
|
1413
1411
|
}
|
|
1412
|
+
function renderTelegramTextLinks(value) {
|
|
1413
|
+
return value.replace(/https?:\/\/[^\s<>"']+/g, (url) => {
|
|
1414
|
+
const trailingMatch = /[),.;!?]+$/.exec(url);
|
|
1415
|
+
const trailing = trailingMatch?.[0] ?? "";
|
|
1416
|
+
const cleanUrl = trailing ? url.slice(0, -trailing.length) : url;
|
|
1417
|
+
return `<a href="${escapeTelegramHtmlAttribute(cleanUrl)}">${escapeTelegramHtml(cleanUrl)}</a>${escapeTelegramHtml(trailing)}`;
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
function containsUrl(value) {
|
|
1421
|
+
return /https?:\/\/[^\s<>"']+/.test(value);
|
|
1422
|
+
}
|
|
1414
1423
|
function escapeTelegramHtml(value) {
|
|
1415
1424
|
return value
|
|
1416
1425
|
.replace(/&/g, "&")
|
|
1417
1426
|
.replace(/</g, "<")
|
|
1418
1427
|
.replace(/>/g, ">");
|
|
1419
1428
|
}
|
|
1429
|
+
function escapeTelegramHtmlAttribute(value) {
|
|
1430
|
+
return escapeTelegramHtml(value).replace(/"/g, """);
|
|
1431
|
+
}
|
|
1420
1432
|
function looksLikeUntaggedIntentOnlyResponse(text) {
|
|
1421
1433
|
const normalized = text.trim();
|
|
1422
1434
|
if (!normalized) {
|
|
@@ -71,53 +71,6 @@ export class AgentMemoryService {
|
|
|
71
71
|
history.length > 0 ? ["Recent history:", ...history.map((entry) => `- ${entry}`)].join("\n") : undefined,
|
|
72
72
|
].filter(Boolean).join("\n");
|
|
73
73
|
}
|
|
74
|
-
async formatLocalStatusQuestion(session, question) {
|
|
75
|
-
if (!this.looksLikeLocalStatusQuestion(question)) {
|
|
76
|
-
return undefined;
|
|
77
|
-
}
|
|
78
|
-
const current = await this.currentTaskText(session);
|
|
79
|
-
const todo = await this.readTodo(session);
|
|
80
|
-
const active = this.activeTodoItems(todo);
|
|
81
|
-
const history = await this.readRecentHistory(session, 8);
|
|
82
|
-
const workHistory = await this.readRecentWorkHistory(session, 6);
|
|
83
|
-
const latestInstruction = this.extractLatestInstructionFromCurrent(current);
|
|
84
|
-
const currentIsStatusOnly = latestInstruction ? this.looksLikeLocalStatusQuestion(latestInstruction) : false;
|
|
85
|
-
const hasCurrentWork = Boolean(current.trim()) && !currentIsStatusOnly;
|
|
86
|
-
const lines = [
|
|
87
|
-
`Session ${session.publicId} local state`,
|
|
88
|
-
"",
|
|
89
|
-
`workspace: ${session.workspace}`,
|
|
90
|
-
`memory: ${this.sessionDir(session)}`,
|
|
91
|
-
"",
|
|
92
|
-
];
|
|
93
|
-
if (!hasCurrentWork && active.length === 0 && workHistory.length === 0) {
|
|
94
|
-
lines.push("현재 하네스 기준으로 진행 중이거나 완료된 작업 기록이 없습니다.", "이 세션은 깨끗한 상태로 보입니다.");
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
if (hasCurrentWork) {
|
|
98
|
-
lines.push("Current note:", this.summarizeCurrentTask(current), "");
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
lines.push("Current note: none", "");
|
|
102
|
-
}
|
|
103
|
-
if (active.length > 0) {
|
|
104
|
-
lines.push("Active TODO:", this.formatTodoSummary(todo, false), "");
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
lines.push("Active TODO: none", "");
|
|
108
|
-
}
|
|
109
|
-
if (workHistory.length > 0) {
|
|
110
|
-
lines.push("Recent work history:", ...workHistory.map((entry) => `- ${entry}`));
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
lines.push("Recent work history: none");
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (history.length > 0) {
|
|
117
|
-
lines.push("", "Recent raw history:", ...history.map((entry) => `- ${entry}`));
|
|
118
|
-
}
|
|
119
|
-
return lines.join("\n");
|
|
120
|
-
}
|
|
121
74
|
async clearSessionState(session, summary) {
|
|
122
75
|
const dir = this.sessionDir(session);
|
|
123
76
|
const currentPath = path.join(dir, "current.md");
|
|
@@ -627,27 +580,6 @@ export class AgentMemoryService {
|
|
|
627
580
|
const match = /## Latest User Instruction\s*\n([\s\S]*?)(?:\n## |\s*$)/.exec(current);
|
|
628
581
|
return match?.[1]?.trim() || undefined;
|
|
629
582
|
}
|
|
630
|
-
looksLikeLocalStatusQuestion(text) {
|
|
631
|
-
const normalized = text.trim();
|
|
632
|
-
if (!normalized) {
|
|
633
|
-
return false;
|
|
634
|
-
}
|
|
635
|
-
if (normalized.length > 80 || /[\r\n]/.test(normalized)) {
|
|
636
|
-
return false;
|
|
637
|
-
}
|
|
638
|
-
if (/(진행|정리|구현|수정|제거|삭제|추가|작성|테스트|검증|커밋|푸시|배포|문서로|완료되면|필수|전담|담당|작업\s*폴더)/.test(normalized)) {
|
|
639
|
-
return false;
|
|
640
|
-
}
|
|
641
|
-
return [
|
|
642
|
-
/최근\s*(작업|진행|히스토리|기록)/,
|
|
643
|
-
/현재\s*(작업|진행|상태|세션)/,
|
|
644
|
-
/(뭐|무엇)\s*(하고|하는)\s*(있어|중|거야)?/,
|
|
645
|
-
/작업\s*(상태|히스토리|기록|있어|없어)/,
|
|
646
|
-
/세션\s*(상태|히스토리|기록)/,
|
|
647
|
-
/진행\s*(상태|중인\s*작업)/,
|
|
648
|
-
/\b(status|current work|recent work|what are you doing|session state)\b/i,
|
|
649
|
-
].some((pattern) => pattern.test(normalized));
|
|
650
|
-
}
|
|
651
583
|
formatTodoSummary(todo, includeDone = false, detailed = false) {
|
|
652
584
|
const items = includeDone ? todo.items : todo.items.filter((item) => item.status !== "done");
|
|
653
585
|
if (items.length === 0) {
|