omnius 1.0.169 → 1.0.171
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/index.js +148 -35
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -546736,14 +546736,30 @@ function estimateTokens2(text) {
|
|
|
546736
546736
|
function normalizeSignalContent(content) {
|
|
546737
546737
|
return content.replace(/\r\n/g, "\n").split("\n").map((line) => line.trimEnd()).join("\n").trim();
|
|
546738
546738
|
}
|
|
546739
|
+
function urlSpanAt(text, index) {
|
|
546740
|
+
URL_RE.lastIndex = 0;
|
|
546741
|
+
for (const match of text.matchAll(URL_RE)) {
|
|
546742
|
+
const start2 = match.index ?? 0;
|
|
546743
|
+
const end = start2 + match[0].length;
|
|
546744
|
+
if (start2 < index && index < end)
|
|
546745
|
+
return { start: start2, end };
|
|
546746
|
+
}
|
|
546747
|
+
return null;
|
|
546748
|
+
}
|
|
546739
546749
|
function truncateText2(text, maxChars) {
|
|
546740
546750
|
if (text.length <= maxChars)
|
|
546741
546751
|
return { text, truncated: false };
|
|
546742
546752
|
if (maxChars <= 40)
|
|
546743
546753
|
return { text: text.slice(0, maxChars), truncated: true };
|
|
546754
|
+
const suffix = CONTEXT_FABRIC_TRUNCATION_SUFFIX;
|
|
546755
|
+
let cutIndex = maxChars - suffix.length;
|
|
546756
|
+
const urlSpan = urlSpanAt(text, cutIndex);
|
|
546757
|
+
if (urlSpan) {
|
|
546758
|
+
cutIndex = urlSpan.start;
|
|
546759
|
+
}
|
|
546760
|
+
const prefix = text.slice(0, Math.max(0, cutIndex)).trimEnd();
|
|
546744
546761
|
return {
|
|
546745
|
-
text: `${
|
|
546746
|
-
... [truncated by context fabric]`,
|
|
546762
|
+
text: `${prefix}${suffix}`,
|
|
546747
546763
|
truncated: true
|
|
546748
546764
|
};
|
|
546749
546765
|
}
|
|
@@ -546812,7 +546828,7 @@ function signalFromBlock(kind, source, content, options2 = {}) {
|
|
|
546812
546828
|
metadata: options2.metadata
|
|
546813
546829
|
};
|
|
546814
546830
|
}
|
|
546815
|
-
var KIND_ORDER, KIND_LABELS, DEFAULT_KIND_CHAR_BUDGET, ContextLedger, ContextFrameBuilder;
|
|
546831
|
+
var KIND_ORDER, KIND_LABELS, DEFAULT_KIND_CHAR_BUDGET, URL_RE, CONTEXT_FABRIC_TRUNCATION_SUFFIX, ContextLedger, ContextFrameBuilder;
|
|
546816
546832
|
var init_context_fabric = __esm({
|
|
546817
546833
|
"packages/orchestrator/dist/context-fabric.js"() {
|
|
546818
546834
|
"use strict";
|
|
@@ -546864,6 +546880,8 @@ var init_context_fabric = __esm({
|
|
|
546864
546880
|
environment: 900,
|
|
546865
546881
|
compaction_summary: 1200
|
|
546866
546882
|
};
|
|
546883
|
+
URL_RE = /\bhttps?:\/\/[^\s<>"'()[\]{}]+/gi;
|
|
546884
|
+
CONTEXT_FABRIC_TRUNCATION_SUFFIX = "\n... [truncated by context fabric]";
|
|
546867
546885
|
ContextLedger = class {
|
|
546868
546886
|
signals = /* @__PURE__ */ new Map();
|
|
546869
546887
|
sequence = 0;
|
|
@@ -592291,7 +592309,7 @@ function extractMediaReferences(text) {
|
|
|
592291
592309
|
const offset = match[0].indexOf("MEDIA:");
|
|
592292
592310
|
addCandidate(value2, match[0].slice(offset), match.index + offset, match.index + match[0].length);
|
|
592293
592311
|
}
|
|
592294
|
-
for (const match of matchAll(
|
|
592312
|
+
for (const match of matchAll(URL_RE2, text)) {
|
|
592295
592313
|
const original = trimTrailingPunctuation(match[0]);
|
|
592296
592314
|
if (original.length !== match[0].length) {
|
|
592297
592315
|
addCandidate(original, original, match.index, match.index + original.length);
|
|
@@ -592415,7 +592433,7 @@ function decodeUri(value2) {
|
|
|
592415
592433
|
function trimTrailingPunctuation(value2) {
|
|
592416
592434
|
return value2.replace(/[),.;:!?]+$/, "");
|
|
592417
592435
|
}
|
|
592418
|
-
var IMAGE_EXT, AUDIO_EXT, VIDEO_EXT, DOC_EXT, MEDIA_DIRECTIVE_RE, AUDIO_AS_VOICE_RE, MARKDOWN_IMAGE_RE, HTML_IMG_RE,
|
|
592436
|
+
var IMAGE_EXT, AUDIO_EXT, VIDEO_EXT, DOC_EXT, MEDIA_DIRECTIVE_RE, AUDIO_AS_VOICE_RE, MARKDOWN_IMAGE_RE, HTML_IMG_RE, URL_RE2, LOCAL_PATH_RE;
|
|
592419
592437
|
var init_media_routing = __esm({
|
|
592420
592438
|
"packages/cli/src/tui/media-routing.ts"() {
|
|
592421
592439
|
"use strict";
|
|
@@ -592447,7 +592465,7 @@ var init_media_routing = __esm({
|
|
|
592447
592465
|
AUDIO_AS_VOICE_RE = /\[\[audio_as_voice\]\]/gi;
|
|
592448
592466
|
MARKDOWN_IMAGE_RE = /!\[[^\]]*]\(([^)\s]+)(?:\s+"[^"]*")?\)/g;
|
|
592449
592467
|
HTML_IMG_RE = /<img\b[^>]*\bsrc\s*=\s*["']([^"']+)["'][^>]*>/gi;
|
|
592450
|
-
|
|
592468
|
+
URL_RE2 = /\bhttps?:\/\/[^\s<>"')]+/gi;
|
|
592451
592469
|
LOCAL_PATH_RE = /(?:^|[\s([])((?:~|\/)[^\s<>"')\]]+\.(?:png|jpe?g|webp|gif|bmp|tiff?|svg|wav|mp3|ogg|oga|opus|m4a|flac|aac|mp4|mov|mkv|webm|avi|m4v|pdf|txt|md|markdown|csv|tsv|jsonl?|xlsx?|docx?|pptx?|html?|xml|zip|tar|gz))(?:$|[\s),.\]])/gim;
|
|
592452
592470
|
}
|
|
592453
592471
|
});
|
|
@@ -615859,9 +615877,10 @@ function buildRealtimeSystemPrompt(opts) {
|
|
|
615859
615877
|
`- Produce one natural spoken turn, normally ${maxReplyWords} words or fewer.`,
|
|
615860
615878
|
"- Use one sentence when possible; two short sentences only when repair or confirmation needs it.",
|
|
615861
615879
|
"- Lead with the answer. Do not preface with status, analysis, summaries, or implementation narration.",
|
|
615862
|
-
"- No markdown, bullets, tables, headings, citations, code blocks, JSON, or labels like 'Assistant:'.",
|
|
615880
|
+
"- No markdown, bullets, tables, headings, citations, inline code, code blocks, JSON, or labels like 'Assistant:'.",
|
|
615863
615881
|
"- Sound like a person on a live call: brief acknowledgment, direct answer, one focused follow-up only if needed.",
|
|
615864
615882
|
"- If the ASR text is garbled or underspecified, ask a single compact repair question.",
|
|
615883
|
+
"- Do not invent app modes, method names, settings, or implementation details when the caller has not supplied them.",
|
|
615865
615884
|
"- Do not mention ASR, TTS, prompts, realtime mode, hidden reasoning, tools, or policy unless the caller explicitly asks.",
|
|
615866
615885
|
"- If a request needs work outside this text-only exchange, say the next handoff in one short sentence."
|
|
615867
615886
|
].join("\n"),
|
|
@@ -615952,7 +615971,7 @@ function wordParts(text) {
|
|
|
615952
615971
|
}
|
|
615953
615972
|
function finalizeRealtimeReply(text, opts = {}) {
|
|
615954
615973
|
const maxWords = clampInt2(opts.maxReplyWords, DEFAULT_REALTIME_MAX_REPLY_WORDS, 8, 80);
|
|
615955
|
-
let clean5 = stripHiddenThinking(String(text ?? "")).replace(/```[\s\S]*?```/g, "").split("\n").map((line) => line.replace(/^\s*(?:[-*]+|\d+[.)])\s+/, "").trim()).filter(Boolean).join(" ").replace(/^(?:assistant|omnius|agent)\s*:\s*/i, "").replace(/\s+/g, " ").trim();
|
|
615974
|
+
let clean5 = stripHiddenThinking(String(text ?? "")).replace(/```[\s\S]*?```/g, "").split("\n").map((line) => line.replace(/^\s*(?:[-*]+|\d+[.)])\s+/, "").trim()).filter(Boolean).join(" ").replace(/^(?:assistant|omnius|agent)\s*:\s*/i, "").replace(/`([^`]+)`/g, "$1").replace(/\s+/g, " ").trim();
|
|
615956
615975
|
if (!clean5) return "I didn't catch that. Can you say it again?";
|
|
615957
615976
|
const sentences = clean5.match(/[^.!?]+[.!?]+(?=\s|$)|[^.!?]+$/g) ?? [clean5];
|
|
615958
615977
|
const selected = [];
|
|
@@ -627419,7 +627438,7 @@ function parseTelegramReflectionFollowupDecision(text) {
|
|
|
627419
627438
|
}
|
|
627420
627439
|
}
|
|
627421
627440
|
function convertMarkdownToTelegramHTML(md) {
|
|
627422
|
-
let html = md;
|
|
627441
|
+
let html = normalizeTelegramOutboundLinks(md);
|
|
627423
627442
|
html = html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
627424
627443
|
html = html.replace(
|
|
627425
627444
|
/```[\w]*\n([\s\S]*?)```/g,
|
|
@@ -627439,6 +627458,13 @@ function convertMarkdownToTelegramHTML(md) {
|
|
|
627439
627458
|
function escapeTelegramHTML(text) {
|
|
627440
627459
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
627441
627460
|
}
|
|
627461
|
+
function normalizeTelegramOutboundLinks(text) {
|
|
627462
|
+
if (!text) return text;
|
|
627463
|
+
return text.replace(
|
|
627464
|
+
TELEGRAM_SPACED_URL_RE,
|
|
627465
|
+
(match) => match.replace(/^(https?:\/\/)\s*/i, "$1").replace(/\s*\.\s*/g, ".").replace(/\s*:\s*(\d+)/g, ":$1")
|
|
627466
|
+
);
|
|
627467
|
+
}
|
|
627442
627468
|
function splitTelegramMessageText(text, maxLength = 3900) {
|
|
627443
627469
|
const trimmed = text.trim();
|
|
627444
627470
|
if (!trimmed) return [];
|
|
@@ -627544,7 +627570,7 @@ function stripTelegramStuckSelfTalk(text) {
|
|
|
627544
627570
|
return kept.join("\n\n");
|
|
627545
627571
|
}
|
|
627546
627572
|
function cleanTelegramVisibleReply(text, options2 = {}) {
|
|
627547
|
-
const clean5 = stripTelegramHiddenThinking(text).trim();
|
|
627573
|
+
const clean5 = normalizeTelegramOutboundLinks(stripTelegramHiddenThinking(text)).trim();
|
|
627548
627574
|
if (!clean5) return "";
|
|
627549
627575
|
if (options2.suppressPotentialNoReplyPrefix && isTelegramPotentialNoReplyPrefix(clean5)) return "";
|
|
627550
627576
|
if (isTelegramInternalStatusText(clean5)) return "";
|
|
@@ -628621,7 +628647,7 @@ function renderTelegramSubAgentError(username, error) {
|
|
|
628621
628647
|
process.stdout.write(` ${c3.dim("│")} ${c3.magenta("✘")} @${username}: ${c3.dim(preview)}
|
|
628622
628648
|
`);
|
|
628623
628649
|
}
|
|
628624
|
-
var TELEGRAM_TOOL_ACTION_GROUPS, TELEGRAM_TOOL_ACTION_GROUP, TELEGRAM_TOOL_MUTATING_GROUPS, DEFAULT_TELEGRAM_TOOL_GROUP_POLICY, TELEGRAM_TOOL_BUTTON_LABELS, TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, TELEGRAM_PUBLIC_VISION_STACK_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT, TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT, TELEGRAM_INTERACTION_DECISION_MINIMAL_SCHEMA, TELEGRAM_INTERACTION_DECISION_REPAIR_SCHEMA, TELEGRAM_CHAT_REPLY_RESPONSE_FORMAT, TELEGRAM_STUCK_SELF_TALK_PREFIXES, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_ASSOCIATIVE_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_USER_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_ACTION_LIMIT, TELEGRAM_ASSOCIATIVE_RELATION_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_MEMORY_GENERIC_QUERY_TOKENS, TELEGRAM_SUB_AGENT_BOUNDED_OPTIONS, TELEGRAM_SUB_AGENT_DEFAULT_LIMIT, TELEGRAM_SUB_AGENT_MAX_LIMIT, TELEGRAM_SUB_AGENT_BURST_CONTEXT_LIMIT, TELEGRAM_PUBLIC_HELP_COMMANDS2, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_PUBLIC_BOT_COMMAND_NAMES, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TELEGRAM_ALLOWED_UPDATES, TELEGRAM_PUBLIC_TOOL_QUOTAS, TelegramBridge;
|
|
628650
|
+
var TELEGRAM_TOOL_ACTION_GROUPS, TELEGRAM_TOOL_ACTION_GROUP, TELEGRAM_TOOL_MUTATING_GROUPS, DEFAULT_TELEGRAM_TOOL_GROUP_POLICY, TELEGRAM_TOOL_BUTTON_LABELS, TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, TELEGRAM_PUBLIC_VISION_STACK_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT, TELEGRAM_LINK_INTEGRITY_CONTRACT, TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT, TELEGRAM_INTERACTION_DECISION_MINIMAL_SCHEMA, TELEGRAM_INTERACTION_DECISION_REPAIR_SCHEMA, TELEGRAM_CHAT_REPLY_RESPONSE_FORMAT, TELEGRAM_SPACED_URL_RE, TELEGRAM_STUCK_SELF_TALK_PREFIXES, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_ASSOCIATIVE_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_USER_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_ACTION_LIMIT, TELEGRAM_ASSOCIATIVE_RELATION_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_MEMORY_GENERIC_QUERY_TOKENS, TELEGRAM_SUB_AGENT_BOUNDED_OPTIONS, TELEGRAM_SUB_AGENT_DEFAULT_LIMIT, TELEGRAM_SUB_AGENT_MAX_LIMIT, TELEGRAM_SUB_AGENT_BURST_CONTEXT_LIMIT, TELEGRAM_PUBLIC_HELP_COMMANDS2, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_PUBLIC_BOT_COMMAND_NAMES, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TELEGRAM_ALLOWED_UPDATES, TELEGRAM_PUBLIC_TOOL_QUOTAS, TelegramBridge;
|
|
628625
628651
|
var init_telegram_bridge = __esm({
|
|
628626
628652
|
"packages/cli/src/tui/telegram-bridge.ts"() {
|
|
628627
628653
|
"use strict";
|
|
@@ -628889,6 +628915,13 @@ External acquisition contract:
|
|
|
628889
628915
|
- Treat repeated invalid downloads (saved HTML/JSON/login pages instead of the expected file type) as the same blocker; do not retry past a small bounded number of attempts.
|
|
628890
628916
|
- The browser tool is for interactive web work; it does not save arbitrary rendered files to disk. For file acquisition, use the download/file tool and verify content-type + size before reporting success.
|
|
628891
628917
|
- Report the exact blocker concisely and offer lawful alternatives (library hold, official store, summary/discussion if the user supplies an authorized copy).
|
|
628918
|
+
`.trim();
|
|
628919
|
+
TELEGRAM_LINK_INTEGRITY_CONTRACT = `
|
|
628920
|
+
Telegram link integrity contract:
|
|
628921
|
+
- When sending public http(s) URLs, copy the URL exactly from source/tool output.
|
|
628922
|
+
- Never defang, space out, redact, or rewrite dots, slashes, host labels, or TLDs in normal public URLs.
|
|
628923
|
+
- Prefer Markdown links when helpful, but keep the href URL contiguous and parseable.
|
|
628924
|
+
- If you are uncertain a URL is real, say so or omit it instead of reconstructing a broken URL.
|
|
628892
628925
|
`.trim();
|
|
628893
628926
|
TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT = {
|
|
628894
628927
|
type: "json_object"
|
|
@@ -628913,6 +628946,7 @@ External acquisition contract:
|
|
|
628913
628946
|
}
|
|
628914
628947
|
}
|
|
628915
628948
|
};
|
|
628949
|
+
TELEGRAM_SPACED_URL_RE = /\bhttps?:\/\/\s*[A-Za-z0-9-]+(?:\s*\.\s*[A-Za-z0-9-]+)+(?:\s*:\s*\d+)?(?:[/?#][^\s<>"'()[\]{}]*)?/gi;
|
|
628916
628950
|
TELEGRAM_STUCK_SELF_TALK_PREFIXES = [
|
|
628917
628951
|
/^i'?ve been stuck for\b/i,
|
|
628918
628952
|
/^i am (still |currently )?stuck\b/i,
|
|
@@ -634268,7 +634302,8 @@ Todo/session id: ${sessionId}
|
|
|
634268
634302
|
Profile: ${profile}
|
|
634269
634303
|
Tool context: ${toolContext}
|
|
634270
634304
|
${chatLabel}`,
|
|
634271
|
-
TELEGRAM_ACTION_RESPONSE_CONTRACT
|
|
634305
|
+
TELEGRAM_ACTION_RESPONSE_CONTRACT,
|
|
634306
|
+
TELEGRAM_LINK_INTEGRITY_CONTRACT
|
|
634272
634307
|
];
|
|
634273
634308
|
sections.push(conversationStream);
|
|
634274
634309
|
const sendTargetContext = this.buildTelegramSendTargetContext(msg, isAdminDM);
|
|
@@ -634637,10 +634672,11 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
634637
634672
|
* streamed content. Returns the message_id for subsequent edits.
|
|
634638
634673
|
*/
|
|
634639
634674
|
async sendLiveMessage(chatId, initialText, replyToMessageId) {
|
|
634675
|
+
const normalizedInitialText = normalizeTelegramOutboundLinks(initialText);
|
|
634640
634676
|
try {
|
|
634641
634677
|
const body = {
|
|
634642
634678
|
chat_id: chatId,
|
|
634643
|
-
text:
|
|
634679
|
+
text: normalizedInitialText,
|
|
634644
634680
|
parse_mode: "HTML"
|
|
634645
634681
|
};
|
|
634646
634682
|
const replyParameters = telegramReplyParameters(replyToMessageId);
|
|
@@ -634657,7 +634693,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
634657
634693
|
try {
|
|
634658
634694
|
const body = {
|
|
634659
634695
|
chat_id: chatId,
|
|
634660
|
-
text:
|
|
634696
|
+
text: normalizedInitialText
|
|
634661
634697
|
};
|
|
634662
634698
|
const replyParameters = telegramReplyParameters(replyToMessageId);
|
|
634663
634699
|
if (replyParameters) body["reply_parameters"] = replyParameters;
|
|
@@ -634692,7 +634728,8 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
634692
634728
|
* Handles rate limits and Telegram's "message is not modified" error silently.
|
|
634693
634729
|
*/
|
|
634694
634730
|
async editLiveMessage(chatId, messageId, html) {
|
|
634695
|
-
const
|
|
634731
|
+
const normalizedHtml = normalizeTelegramOutboundLinks(html);
|
|
634732
|
+
const truncated = normalizedHtml.length > 4e3 ? normalizedHtml.slice(0, 3950) + "\n\n<i>... (streaming)</i>" : normalizedHtml;
|
|
634696
634733
|
try {
|
|
634697
634734
|
const result = await this.apiCall("editMessageText", {
|
|
634698
634735
|
chat_id: chatId,
|
|
@@ -634705,7 +634742,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
634705
634742
|
return true;
|
|
634706
634743
|
} catch {
|
|
634707
634744
|
try {
|
|
634708
|
-
const plain =
|
|
634745
|
+
const plain = normalizedHtml.replace(/<[^>]+>/g, "");
|
|
634709
634746
|
const truncPlain = plain.length > 4e3 ? plain.slice(0, 3950) + "\n\n... (streaming)" : plain;
|
|
634710
634747
|
const result = await this.apiCall("editMessageText", {
|
|
634711
634748
|
chat_id: chatId,
|
|
@@ -635404,6 +635441,8 @@ ${TELEGRAM_PUBLIC_VISION_STACK_CONTRACT}`;
|
|
|
635404
635441
|
role: "system",
|
|
635405
635442
|
content: `${TELEGRAM_CHAT_MODE_PROMPT}
|
|
635406
635443
|
|
|
635444
|
+
${TELEGRAM_LINK_INTEGRITY_CONTRACT}
|
|
635445
|
+
|
|
635407
635446
|
## Runtime Context
|
|
635408
635447
|
|
|
635409
635448
|
${runtime}
|
|
@@ -635729,6 +635768,8 @@ ${GROUP_REPLY_DISCRETION_PROMPT}` : "";
|
|
|
635729
635768
|
|
|
635730
635769
|
${TELEGRAM_ACTION_RESPONSE_CONTRACT}
|
|
635731
635770
|
|
|
635771
|
+
${TELEGRAM_LINK_INTEGRITY_CONTRACT}
|
|
635772
|
+
|
|
635732
635773
|
${TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT}
|
|
635733
635774
|
|
|
635734
635775
|
${reminderToolContract}
|
|
@@ -635741,6 +635782,7 @@ ${currentTelegramPrompt}`;
|
|
|
635741
635782
|
"You have access to isolated per-chat memory (memory_write, memory_read, memory_search) scoped to this conversation.",
|
|
635742
635783
|
"memory_search may use scope=group/current_chat for this group or scope=user with user_id/username for a participant in this same group. Other groups, admin chats, and private DMs are not accessible here.",
|
|
635743
635784
|
"You can remember facts about users and retrieve them later. Durable associative memory in the prompt includes participant profiles, relationships, scoped facts, and prior actions retained across days, sessions, and Omnius updates. You also have web_search and web_fetch to look up information.",
|
|
635785
|
+
TELEGRAM_LINK_INTEGRITY_CONTRACT,
|
|
635744
635786
|
"If a user explicitly states a durable preference for reply cadence/order, call telegram_preference_set. Do not infer or classify reply-mode preferences from keywords, style, tone, or task type.",
|
|
635745
635787
|
"You have the full scoped Telegram media-analysis stack by default: telegram_media_recent, image_read, ocr, ocr_image_advanced, vision, pdf_to_text, ocr_pdf, transcribe_file, video_understand, audio_analyze, and identity_memory. For complex textual imagery, screenshots, forms, scans, or dense labels, prefer ocr_image_advanced after resolving media with path='reply' or path='latest'.",
|
|
635746
635788
|
formatIdentityMemoryContext(chatLabel || "Telegram private chat"),
|
|
@@ -638321,9 +638363,10 @@ ${text}`.trim());
|
|
|
638321
638363
|
return result.messageId ?? null;
|
|
638322
638364
|
}
|
|
638323
638365
|
async sendMessageHTMLDetailed(chatId, html, replyToMessageId, options2 = {}) {
|
|
638324
|
-
const
|
|
638366
|
+
const normalizedHtml = normalizeTelegramOutboundLinks(html);
|
|
638367
|
+
const extracted = extractMediaReferences(normalizedHtml);
|
|
638325
638368
|
const mediaRefs = this.filterTelegramMediaReferences(extracted.media, options2);
|
|
638326
|
-
const sendHtml = extracted.text || (extracted.media.length > 0 ? "" :
|
|
638369
|
+
const sendHtml = extracted.text || (extracted.media.length > 0 ? "" : normalizedHtml);
|
|
638327
638370
|
let sentId = null;
|
|
638328
638371
|
if (!sendHtml.trim()) {
|
|
638329
638372
|
for (let idx = 0; idx < mediaRefs.length; idx++) {
|
|
@@ -638790,7 +638833,8 @@ Content-Type: ${mimeForPath(pathOrFileId, field === "photo" ? "image" : "video")
|
|
|
638790
638833
|
* article carrying the message text Telegram should send to the guest chat.
|
|
638791
638834
|
*/
|
|
638792
638835
|
async answerGuestQuery(guestQueryId, text, options2 = {}) {
|
|
638793
|
-
const
|
|
638836
|
+
const normalizedText = normalizeTelegramOutboundLinks(text);
|
|
638837
|
+
const truncated = normalizedText.length > 4e3 ? normalizedText.slice(0, 3950) + "\n\n... (truncated)" : normalizedText;
|
|
638794
638838
|
const inputMessageContent = {
|
|
638795
638839
|
message_text: truncated
|
|
638796
638840
|
};
|
|
@@ -657279,6 +657323,49 @@ function bodyString(body, keys) {
|
|
|
657279
657323
|
}
|
|
657280
657324
|
return "";
|
|
657281
657325
|
}
|
|
657326
|
+
function realtimeFallbackCacheKey(ollamaUrl, missingModel) {
|
|
657327
|
+
return `${ollamaUrl}
|
|
657328
|
+
${missingModel}`;
|
|
657329
|
+
}
|
|
657330
|
+
function isOllamaMissingModelError(body) {
|
|
657331
|
+
return /model ['\"]?[^'\"]+['\"]? not found/i.test(body);
|
|
657332
|
+
}
|
|
657333
|
+
async function resolveRealtimeOllamaFallbackModel(ollamaUrl, timeoutMs, missingModel) {
|
|
657334
|
+
try {
|
|
657335
|
+
const cacheKey = realtimeFallbackCacheKey(ollamaUrl, missingModel);
|
|
657336
|
+
const cached = realtimeOllamaFallbackCache.get(cacheKey);
|
|
657337
|
+
if (cached) return cached;
|
|
657338
|
+
const result = await ollamaRequest(ollamaUrl, "/api/tags", "GET", void 0, Math.min(timeoutMs, 1e4));
|
|
657339
|
+
if (result.status >= 400) return null;
|
|
657340
|
+
const parsed = JSON.parse(result.body);
|
|
657341
|
+
const names = (parsed.models ?? []).map((entry) => typeof entry.name === "string" ? entry.name : typeof entry.model === "string" ? entry.model : "").filter(Boolean);
|
|
657342
|
+
if (!names.length) return null;
|
|
657343
|
+
const remember = (name10) => {
|
|
657344
|
+
realtimeOllamaFallbackCache.set(cacheKey, name10);
|
|
657345
|
+
return name10;
|
|
657346
|
+
};
|
|
657347
|
+
const exactLatest = `${missingModel}:latest`;
|
|
657348
|
+
if (names.includes(exactLatest)) return remember(exactLatest);
|
|
657349
|
+
const preferred = [
|
|
657350
|
+
"qwen3.5-9b-r10:q4km",
|
|
657351
|
+
"open-agents-qwen35-9b-r10-q4km:latest",
|
|
657352
|
+
"open-agents-qwen35-9b-r10-parsed-q4km:latest",
|
|
657353
|
+
"open-agents-qwen35-9b-r9-q4km:latest",
|
|
657354
|
+
"qwen3:8b",
|
|
657355
|
+
"open-agents-qwen3-8b:latest",
|
|
657356
|
+
"omnius-qwen36-35b:latest",
|
|
657357
|
+
"open-agents-qwen36:latest",
|
|
657358
|
+
"qwen3.6:35b"
|
|
657359
|
+
];
|
|
657360
|
+
for (const name10 of preferred) {
|
|
657361
|
+
if (names.includes(name10)) return remember(name10);
|
|
657362
|
+
}
|
|
657363
|
+
const fallback = names.find((name10) => /qwen/i.test(name10) && !/embed|vision/i.test(name10)) ?? names.find((name10) => !/embed|vision|moondream/i.test(name10)) ?? null;
|
|
657364
|
+
return fallback ? remember(fallback) : null;
|
|
657365
|
+
} catch {
|
|
657366
|
+
return null;
|
|
657367
|
+
}
|
|
657368
|
+
}
|
|
657282
657369
|
function realtimeEndpointMessages(body) {
|
|
657283
657370
|
const messages2 = [];
|
|
657284
657371
|
const suppliedSoul = bodyString(body, ["soul_md", "soul", "soulMd"]);
|
|
@@ -657305,13 +657392,14 @@ ${suppliedContext}` });
|
|
|
657305
657392
|
}
|
|
657306
657393
|
async function completeRealtimeTextOnly(opts) {
|
|
657307
657394
|
const cfg = loadConfig();
|
|
657308
|
-
const
|
|
657395
|
+
const requestedModel = bodyString(opts.body, ["model"]);
|
|
657396
|
+
const model = requestedModel || opts.defaultModel || cfg.model;
|
|
657309
657397
|
const route = resolveModelEndpoint(model);
|
|
657310
657398
|
const limitErr = route?.endpoint ? checkEndpointRateLimit(route.endpoint) : null;
|
|
657311
657399
|
if (limitErr) throw new Error(limitErr);
|
|
657312
657400
|
const targetUrl = route?.endpoint.url ?? opts.ollamaUrl;
|
|
657313
|
-
const targetType = route?.endpoint.type ?? cfg.backendType ?? "ollama";
|
|
657314
|
-
|
|
657401
|
+
const targetType = route?.endpoint.type ?? opts.defaultBackendType ?? cfg.backendType ?? "ollama";
|
|
657402
|
+
let originalModel = route?.originalId ?? model.replace(/^[a-z]+\//, "");
|
|
657315
657403
|
const realtimeOpts = {
|
|
657316
657404
|
...realtimeOptionsFromBody(opts.body, process.cwd(), opts.sessionId),
|
|
657317
657405
|
surface: "voice_adapter"
|
|
@@ -657333,13 +657421,24 @@ async function completeRealtimeTextOnly(opts) {
|
|
|
657333
657421
|
}
|
|
657334
657422
|
const maxTokens = typeof requestBody["max_tokens"] === "number" ? requestBody["max_tokens"] : 120;
|
|
657335
657423
|
const temperature = typeof requestBody["temperature"] === "number" ? requestBody["temperature"] : 0.6;
|
|
657336
|
-
|
|
657337
|
-
|
|
657424
|
+
if (!requestedModel) {
|
|
657425
|
+
originalModel = realtimeOllamaFallbackCache.get(realtimeFallbackCacheKey(targetUrl, originalModel)) ?? originalModel;
|
|
657426
|
+
}
|
|
657427
|
+
const makeOllamaChatBody = (modelName) => JSON.stringify({
|
|
657428
|
+
model: modelName,
|
|
657338
657429
|
messages: requestBody["messages"],
|
|
657339
657430
|
stream: false,
|
|
657340
657431
|
think: false,
|
|
657341
657432
|
options: { temperature, num_predict: maxTokens }
|
|
657342
|
-
})
|
|
657433
|
+
});
|
|
657434
|
+
let result = await ollamaRequest(targetUrl, "/api/chat", "POST", makeOllamaChatBody(originalModel), timeoutMs, route?.endpoint);
|
|
657435
|
+
if (result.status >= 400 && !requestedModel && isOllamaMissingModelError(result.body)) {
|
|
657436
|
+
const fallbackModel = await resolveRealtimeOllamaFallbackModel(targetUrl, timeoutMs, originalModel);
|
|
657437
|
+
if (fallbackModel && fallbackModel !== originalModel) {
|
|
657438
|
+
originalModel = fallbackModel;
|
|
657439
|
+
result = await ollamaRequest(targetUrl, "/api/chat", "POST", makeOllamaChatBody(originalModel), timeoutMs, route?.endpoint);
|
|
657440
|
+
}
|
|
657441
|
+
}
|
|
657343
657442
|
if (result.status >= 400) throw new Error(`Backend HTTP ${result.status}: ${result.body.slice(0, 300)}`);
|
|
657344
657443
|
const parsed = JSON.parse(result.body);
|
|
657345
657444
|
const rawReply = String(parsed?.message?.content ?? "").trim();
|
|
@@ -657354,7 +657453,7 @@ async function completeRealtimeTextOnly(opts) {
|
|
|
657354
657453
|
}
|
|
657355
657454
|
};
|
|
657356
657455
|
}
|
|
657357
|
-
async function handleRealtimeText(req2, res, ollamaUrl) {
|
|
657456
|
+
async function handleRealtimeText(req2, res, ollamaUrl, defaults3 = {}) {
|
|
657358
657457
|
const body = await parseJsonBody(req2);
|
|
657359
657458
|
if (!body || typeof body !== "object") {
|
|
657360
657459
|
jsonResponse(res, 400, { error: "invalid_request", message: "Expected a JSON object." });
|
|
@@ -657367,7 +657466,14 @@ async function handleRealtimeText(req2, res, ollamaUrl) {
|
|
|
657367
657466
|
}
|
|
657368
657467
|
try {
|
|
657369
657468
|
const sessionId = typeof body["session_id"] === "string" ? body["session_id"] : void 0;
|
|
657370
|
-
const result = await completeRealtimeTextOnly({
|
|
657469
|
+
const result = await completeRealtimeTextOnly({
|
|
657470
|
+
body,
|
|
657471
|
+
messages: messages2,
|
|
657472
|
+
ollamaUrl,
|
|
657473
|
+
defaultModel: defaults3.model,
|
|
657474
|
+
defaultBackendType: defaults3.backendType,
|
|
657475
|
+
sessionId
|
|
657476
|
+
});
|
|
657371
657477
|
const wantsPlain = String(req2.headers["accept"] ?? "").includes("text/plain") || body["format"] === "text";
|
|
657372
657478
|
if (wantsPlain) {
|
|
657373
657479
|
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
@@ -660331,7 +660437,7 @@ async function handlePostCommand(res, cmd) {
|
|
|
660331
660437
|
});
|
|
660332
660438
|
}
|
|
660333
660439
|
}
|
|
660334
|
-
async function handleRequest(req2, res, ollamaUrl, verbose) {
|
|
660440
|
+
async function handleRequest(req2, res, ollamaUrl, verbose, runtimeDefaults = {}) {
|
|
660335
660441
|
try {
|
|
660336
660442
|
const _liveCfg = loadConfig();
|
|
660337
660443
|
if (_liveCfg.backendUrl) ollamaUrl = _liveCfg.backendUrl;
|
|
@@ -660606,7 +660712,7 @@ async function handleRequest(req2, res, ollamaUrl, verbose) {
|
|
|
660606
660712
|
status = 401;
|
|
660607
660713
|
return;
|
|
660608
660714
|
}
|
|
660609
|
-
await handleRealtimeText(req2, res, ollamaUrl);
|
|
660715
|
+
await handleRealtimeText(req2, res, ollamaUrl, runtimeDefaults);
|
|
660610
660716
|
return;
|
|
660611
660717
|
}
|
|
660612
660718
|
if (pathname === "/v1/files" && method === "GET") {
|
|
@@ -662614,13 +662720,14 @@ ${historyLines}
|
|
|
662614
662720
|
}));
|
|
662615
662721
|
}
|
|
662616
662722
|
} finally {
|
|
662617
|
-
|
|
662723
|
+
const finalStatus = res.headersSent ? res.statusCode : status;
|
|
662724
|
+
recordMetric(method, pathname, finalStatus);
|
|
662618
662725
|
const latencyMs = Math.round(performance.now() - startMs);
|
|
662619
662726
|
logRequest({
|
|
662620
662727
|
requestId,
|
|
662621
662728
|
method,
|
|
662622
662729
|
path: pathname,
|
|
662623
|
-
status,
|
|
662730
|
+
status: finalStatus,
|
|
662624
662731
|
latencyMs,
|
|
662625
662732
|
user: req2._authUser ?? "anonymous",
|
|
662626
662733
|
scope: req2._authScope ?? "none"
|
|
@@ -662630,7 +662737,7 @@ ${historyLines}
|
|
|
662630
662737
|
requestId,
|
|
662631
662738
|
method,
|
|
662632
662739
|
path: pathname,
|
|
662633
|
-
status,
|
|
662740
|
+
status: finalStatus,
|
|
662634
662741
|
user: req2._authUser ?? "anonymous",
|
|
662635
662742
|
scope: req2._authScope ?? "none",
|
|
662636
662743
|
latencyMs: Math.round(performance.now() - startMs),
|
|
@@ -663552,7 +663659,10 @@ function startApiServer(options2 = {}) {
|
|
|
663552
663659
|
}
|
|
663553
663660
|
} catch {
|
|
663554
663661
|
}
|
|
663555
|
-
handleRequest(req2, res, ollamaUrl, verbose
|
|
663662
|
+
handleRequest(req2, res, ollamaUrl, verbose, {
|
|
663663
|
+
model: options2.model ?? config.model,
|
|
663664
|
+
backendType: options2.backendType ?? config.backendType
|
|
663665
|
+
}).catch((err) => {
|
|
663556
663666
|
metrics.totalErrors++;
|
|
663557
663667
|
try {
|
|
663558
663668
|
jsonResponse(res, 500, {
|
|
@@ -664374,7 +664484,9 @@ async function apiServeCommand(opts, config) {
|
|
|
664374
664484
|
port: opts.port,
|
|
664375
664485
|
// Let startApiServer() parse OMNIUS_HOST env if no explicit --port
|
|
664376
664486
|
verbose: opts.verbose,
|
|
664377
|
-
ollamaUrl: config.backendUrl
|
|
664487
|
+
ollamaUrl: config.backendUrl,
|
|
664488
|
+
model: config.model,
|
|
664489
|
+
backendType: config.backendType
|
|
664378
664490
|
});
|
|
664379
664491
|
await new Promise((resolve57) => {
|
|
664380
664492
|
server2.on("close", resolve57);
|
|
@@ -664429,7 +664541,7 @@ function setTimerEnabled(name10, enabled2) {
|
|
|
664429
664541
|
return false;
|
|
664430
664542
|
}
|
|
664431
664543
|
}
|
|
664432
|
-
var require4, NEXUS_DIRECTORY_ORIGIN2, NEXUS_SPONSORS_URL2, endpointRegistry, modelRouteMap, endpointUsage, _lastEndpointDiagnostics, BACKEND_TIMEOUT_DEFAULT_MS, BACKEND_TIMEOUT_MAX_MS, MODEL_LIST_TIMEOUT_DEFAULT_MS, metrics, startedAt, runningProcesses, perKeyUsage, CRON_MARKER2;
|
|
664544
|
+
var require4, NEXUS_DIRECTORY_ORIGIN2, NEXUS_SPONSORS_URL2, endpointRegistry, modelRouteMap, endpointUsage, _lastEndpointDiagnostics, BACKEND_TIMEOUT_DEFAULT_MS, BACKEND_TIMEOUT_MAX_MS, MODEL_LIST_TIMEOUT_DEFAULT_MS, metrics, startedAt, realtimeOllamaFallbackCache, runningProcesses, perKeyUsage, CRON_MARKER2;
|
|
664433
664545
|
var init_serve = __esm({
|
|
664434
664546
|
"packages/cli/src/api/serve.ts"() {
|
|
664435
664547
|
"use strict";
|
|
@@ -664477,6 +664589,7 @@ var init_serve = __esm({
|
|
|
664477
664589
|
totalErrors: 0
|
|
664478
664590
|
};
|
|
664479
664591
|
startedAt = Date.now();
|
|
664592
|
+
realtimeOllamaFallbackCache = /* @__PURE__ */ new Map();
|
|
664480
664593
|
runningProcesses = /* @__PURE__ */ new Map();
|
|
664481
664594
|
perKeyUsage = /* @__PURE__ */ new Map();
|
|
664482
664595
|
CRON_MARKER2 = "# OMNIUS-SCHEDULED:";
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.171",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.171",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED