sensorium-mcp 3.1.0-refactor.0 → 3.1.0-refactor.10
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/Install-Sensorium.ps1 +113 -20
- package/dist/config/agent-settings.d.ts +7 -0
- package/dist/config/agent-settings.d.ts.map +1 -1
- package/dist/config/agent-settings.js +14 -0
- package/dist/config/agent-settings.js.map +1 -1
- package/dist/dashboard/log-parser.d.ts +3 -0
- package/dist/dashboard/log-parser.d.ts.map +1 -1
- package/dist/dashboard/log-parser.js +38 -4
- package/dist/dashboard/log-parser.js.map +1 -1
- package/dist/dashboard/routes/claude.d.ts.map +1 -1
- package/dist/dashboard/routes/claude.js +9 -1
- package/dist/dashboard/routes/claude.js.map +1 -1
- package/dist/dashboard/routes/threads.js +1 -1
- package/dist/dashboard/routes/threads.js.map +1 -1
- package/dist/dashboard/spa.html +11 -11
- package/dist/data/memory/bootstrap.d.ts +7 -0
- package/dist/data/memory/bootstrap.d.ts.map +1 -1
- package/dist/data/memory/bootstrap.js +45 -16
- package/dist/data/memory/bootstrap.js.map +1 -1
- package/dist/data/memory/consolidation.d.ts +9 -4
- package/dist/data/memory/consolidation.d.ts.map +1 -1
- package/dist/data/memory/consolidation.js +24 -12
- package/dist/data/memory/consolidation.js.map +1 -1
- package/dist/data/memory/index.d.ts +1 -2
- package/dist/data/memory/index.d.ts.map +1 -1
- package/dist/data/memory/index.js +1 -2
- package/dist/data/memory/index.js.map +1 -1
- package/dist/data/memory/migration-runner.d.ts +24 -1
- package/dist/data/memory/migration-runner.d.ts.map +1 -1
- package/dist/data/memory/migration-runner.js +85 -1
- package/dist/data/memory/migration-runner.js.map +1 -1
- package/dist/data/memory/narrative.d.ts.map +1 -1
- package/dist/data/memory/narrative.js +5 -1
- package/dist/data/memory/narrative.js.map +1 -1
- package/dist/data/memory/note-archival.d.ts +29 -4
- package/dist/data/memory/note-archival.d.ts.map +1 -1
- package/dist/data/memory/note-archival.js +55 -26
- package/dist/data/memory/note-archival.js.map +1 -1
- package/dist/data/memory/reflection-dedup.js +2 -2
- package/dist/data/memory/reflection-dedup.js.map +1 -1
- package/dist/data/memory/reflection.d.ts.map +1 -1
- package/dist/data/memory/reflection.js +7 -3
- package/dist/data/memory/reflection.js.map +1 -1
- package/dist/data/memory/schema-ddl.d.ts +1 -1
- package/dist/data/memory/schema-ddl.d.ts.map +1 -1
- package/dist/data/memory/schema-ddl.js +8 -8
- package/dist/data/memory/semantic-notes.d.ts +30 -2
- package/dist/data/memory/semantic-notes.d.ts.map +1 -1
- package/dist/data/memory/semantic-notes.js +94 -13
- package/dist/data/memory/semantic-notes.js.map +1 -1
- package/dist/data/memory/semantic-search.d.ts.map +1 -1
- package/dist/data/memory/semantic-search.js +6 -4
- package/dist/data/memory/semantic-search.js.map +1 -1
- package/dist/data/memory/thread-registry.d.ts.map +1 -1
- package/dist/data/memory/thread-registry.js +20 -4
- package/dist/data/memory/thread-registry.js.map +1 -1
- package/dist/data/memory/topic-shift.js +2 -2
- package/dist/data/memory/topic-shift.js.map +1 -1
- package/dist/index.js +19 -9
- package/dist/index.js.map +1 -1
- package/dist/integrations/openai/chat.d.ts +7 -1
- package/dist/integrations/openai/chat.d.ts.map +1 -1
- package/dist/integrations/openai/chat.js +19 -2
- package/dist/integrations/openai/chat.js.map +1 -1
- package/dist/integrations/openai/speech.d.ts +4 -1
- package/dist/integrations/openai/speech.d.ts.map +1 -1
- package/dist/integrations/openai/speech.js +6 -1
- package/dist/integrations/openai/speech.js.map +1 -1
- package/dist/integrations/telegram/types.d.ts +9 -0
- package/dist/integrations/telegram/types.d.ts.map +1 -1
- package/dist/lib/markdown.d.ts +0 -13
- package/dist/lib/markdown.d.ts.map +1 -1
- package/dist/lib/markdown.js +45 -0
- package/dist/lib/markdown.js.map +1 -1
- package/dist/lib/usage-metering/index.d.ts +13 -0
- package/dist/lib/usage-metering/index.d.ts.map +1 -0
- package/dist/lib/usage-metering/index.js +10 -0
- package/dist/lib/usage-metering/index.js.map +1 -0
- package/dist/lib/usage-metering/meter.d.ts +34 -0
- package/dist/lib/usage-metering/meter.d.ts.map +1 -0
- package/dist/lib/usage-metering/meter.js +28 -0
- package/dist/lib/usage-metering/meter.js.map +1 -0
- package/dist/lib/usage-metering/pricing.d.ts +39 -0
- package/dist/lib/usage-metering/pricing.d.ts.map +1 -0
- package/dist/lib/usage-metering/pricing.js +49 -0
- package/dist/lib/usage-metering/pricing.js.map +1 -0
- package/dist/lib/usage-metering/sink.d.ts +24 -0
- package/dist/lib/usage-metering/sink.d.ts.map +1 -0
- package/dist/lib/usage-metering/sink.js +56 -0
- package/dist/lib/usage-metering/sink.js.map +1 -0
- package/dist/server/factory.js +12 -9
- package/dist/server/factory.js.map +1 -1
- package/dist/server/http-server.d.ts +1 -0
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/http-server.js +45 -3
- package/dist/server/http-server.js.map +1 -1
- package/dist/services/background-runner.d.ts.map +1 -1
- package/dist/services/background-runner.js +11 -1
- package/dist/services/background-runner.js.map +1 -1
- package/dist/services/claude-spawn.service.d.ts.map +1 -1
- package/dist/services/claude-spawn.service.js +78 -4
- package/dist/services/claude-spawn.service.js.map +1 -1
- package/dist/services/codex-spawn.service.d.ts.map +1 -1
- package/dist/services/codex-spawn.service.js.map +1 -1
- package/dist/services/consolidation.service.d.ts.map +1 -1
- package/dist/services/consolidation.service.js +51 -35
- package/dist/services/consolidation.service.js.map +1 -1
- package/dist/services/copilot-spawn.service.d.ts.map +1 -1
- package/dist/services/copilot-spawn.service.js +8 -1
- package/dist/services/copilot-spawn.service.js.map +1 -1
- package/dist/services/dispatcher/broker.d.ts +6 -0
- package/dist/services/dispatcher/broker.d.ts.map +1 -1
- package/dist/services/dispatcher/broker.js.map +1 -1
- package/dist/services/dispatcher/poller.d.ts.map +1 -1
- package/dist/services/dispatcher/poller.js +15 -0
- package/dist/services/dispatcher/poller.js.map +1 -1
- package/dist/services/keeper.service.d.ts.map +1 -1
- package/dist/services/keeper.service.js +97 -1
- package/dist/services/keeper.service.js.map +1 -1
- package/dist/services/memory-pruning.service.d.ts.map +1 -1
- package/dist/services/memory-pruning.service.js +3 -1
- package/dist/services/memory-pruning.service.js.map +1 -1
- package/dist/services/process.service.d.ts +51 -0
- package/dist/services/process.service.d.ts.map +1 -1
- package/dist/services/process.service.js +247 -7
- package/dist/services/process.service.js.map +1 -1
- package/dist/services/spawn-common.d.ts.map +1 -1
- package/dist/services/spawn-common.js +9 -2
- package/dist/services/spawn-common.js.map +1 -1
- package/dist/services/thread-config.service.d.ts.map +1 -1
- package/dist/services/thread-config.service.js +1 -1
- package/dist/services/thread-config.service.js.map +1 -1
- package/dist/services/thread-health.service.d.ts +19 -1
- package/dist/services/thread-health.service.d.ts.map +1 -1
- package/dist/services/thread-health.service.js +74 -4
- package/dist/services/thread-health.service.js.map +1 -1
- package/dist/services/thread-lifecycle.service.d.ts.map +1 -1
- package/dist/services/thread-lifecycle.service.js +5 -0
- package/dist/services/thread-lifecycle.service.js.map +1 -1
- package/dist/services/worker-cleanup.service.d.ts +12 -0
- package/dist/services/worker-cleanup.service.d.ts.map +1 -1
- package/dist/services/worker-cleanup.service.js +281 -70
- package/dist/services/worker-cleanup.service.js.map +1 -1
- package/dist/sessions/mcp-registry.d.ts +6 -0
- package/dist/sessions/mcp-registry.d.ts.map +1 -1
- package/dist/sessions/mcp-registry.js +8 -0
- package/dist/sessions/mcp-registry.js.map +1 -1
- package/dist/tools/defs/session-defs.d.ts.map +1 -1
- package/dist/tools/defs/session-defs.js +20 -2
- package/dist/tools/defs/session-defs.js.map +1 -1
- package/dist/tools/delegate-tool.d.ts.map +1 -1
- package/dist/tools/delegate-tool.js +84 -4
- package/dist/tools/delegate-tool.js.map +1 -1
- package/dist/tools/memory-tools.d.ts +1 -1
- package/dist/tools/memory-tools.d.ts.map +1 -1
- package/dist/tools/memory-tools.js +4 -4
- package/dist/tools/memory-tools.js.map +1 -1
- package/dist/tools/utility-tools.d.ts.map +1 -1
- package/dist/tools/utility-tools.js +1 -1
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/wait/drive-handler.js +1 -1
- package/dist/tools/wait/drive-handler.js.map +1 -1
- package/dist/tools/wait/media-processor.d.ts.map +1 -1
- package/dist/tools/wait/media-processor.js +2 -2
- package/dist/tools/wait/media-processor.js.map +1 -1
- package/dist/tools/wait/message-delivery.d.ts +10 -0
- package/dist/tools/wait/message-delivery.d.ts.map +1 -1
- package/dist/tools/wait/message-delivery.js +48 -1
- package/dist/tools/wait/message-delivery.js.map +1 -1
- package/dist/tools/wait/poll-loop.d.ts.map +1 -1
- package/dist/tools/wait/poll-loop.js +18 -0
- package/dist/tools/wait/poll-loop.js.map +1 -1
- package/package.json +3 -2
- package/templates/swarm.default.md +4 -1
- package/dist/data/memory/topic-index.d.ts +0 -20
- package/dist/data/memory/topic-index.d.ts.map +0 -1
- package/dist/data/memory/topic-index.js +0 -91
- package/dist/data/memory/topic-index.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/integrations/openai/chat.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/integrations/openai/chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,10 @@ export declare function textToSpeech(text: string, apiKey: string, voice?: TTSVo
|
|
|
21
21
|
*
|
|
22
22
|
* @param audioBuffer Raw audio content (OGG Opus from Telegram voice messages).
|
|
23
23
|
* @param apiKey Fallback API key (used when TRANSCRIPTION_API_KEY is unset).
|
|
24
|
+
* @param filename Upload filename (extension drives Whisper's format sniffing).
|
|
25
|
+
* @param audioSeconds Clip duration, when known — used for cost metering only.
|
|
26
|
+
* @param threadId Originating thread, when known — used for usage attribution only.
|
|
24
27
|
* @returns The transcribed text (empty string if no speech detected).
|
|
25
28
|
*/
|
|
26
|
-
export declare function transcribeAudio(audioBuffer: Buffer, apiKey: string, filename?: string): Promise<string>;
|
|
29
|
+
export declare function transcribeAudio(audioBuffer: Buffer, apiKey: string, filename?: string, audioSeconds?: number, threadId?: number): Promise<string>;
|
|
27
30
|
//# sourceMappingURL=speech.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speech.d.ts","sourceRoot":"","sources":["../../../src/integrations/openai/speech.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"speech.d.ts","sourceRoot":"","sources":["../../../src/integrations/openai/speech.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,6BAA6B;AAC7B,eAAO,MAAM,UAAU,gEAAiE,CAAC;AACzF,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD;;;GAGG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,QAAiB,GACvB,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAoB,EAC9B,YAAY,CAAC,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAkCjB"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Extracted from openai.ts for modular decomposition (Phase 3B).
|
|
5
5
|
*/
|
|
6
|
+
import { recordUsage } from "../../lib/usage-metering/index.js";
|
|
6
7
|
// ─── TTS ──────────────────────────────────────────────────────────────────
|
|
7
8
|
/** Valid TTS voice names. */
|
|
8
9
|
export const TTS_VOICES = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"];
|
|
@@ -42,9 +43,12 @@ export async function textToSpeech(text, apiKey, voice = "nova") {
|
|
|
42
43
|
*
|
|
43
44
|
* @param audioBuffer Raw audio content (OGG Opus from Telegram voice messages).
|
|
44
45
|
* @param apiKey Fallback API key (used when TRANSCRIPTION_API_KEY is unset).
|
|
46
|
+
* @param filename Upload filename (extension drives Whisper's format sniffing).
|
|
47
|
+
* @param audioSeconds Clip duration, when known — used for cost metering only.
|
|
48
|
+
* @param threadId Originating thread, when known — used for usage attribution only.
|
|
45
49
|
* @returns The transcribed text (empty string if no speech detected).
|
|
46
50
|
*/
|
|
47
|
-
export async function transcribeAudio(audioBuffer, apiKey, filename = "voice.ogg") {
|
|
51
|
+
export async function transcribeAudio(audioBuffer, apiKey, filename = "voice.ogg", audioSeconds, threadId) {
|
|
48
52
|
const baseUrl = (process.env.TRANSCRIPTION_BASE_URL || "https://api.openai.com/v1").replace(/\/+$/, "");
|
|
49
53
|
const key = process.env.TRANSCRIPTION_API_KEY || apiKey;
|
|
50
54
|
const model = process.env.TRANSCRIPTION_MODEL || "whisper-1";
|
|
@@ -65,6 +69,7 @@ export async function transcribeAudio(audioBuffer, apiKey, filename = "voice.ogg
|
|
|
65
69
|
const errText = await response.text().catch(() => response.statusText);
|
|
66
70
|
throw new Error(`Whisper transcription failed (${model} @ ${baseUrl}): ${response.status} ${errText}`);
|
|
67
71
|
}
|
|
72
|
+
recordUsage({ category: "transcription", model, audioSeconds, threadId });
|
|
68
73
|
const result = (await response.json());
|
|
69
74
|
return result.text ?? "";
|
|
70
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speech.js","sourceRoot":"","sources":["../../../src/integrations/openai/speech.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,6EAA6E;AAE7E,6BAA6B;AAC7B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;AAGzF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,MAAc,EACd,QAAkB,MAAM;IAExB,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,wCAAwC,EAAE;QACrE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,MAAM,EAAE;SAClC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,KAAK,EAAE,OAAO;YACd,KAAK,EAAE,IAAI;YACX,KAAK;YACL,eAAe,EAAE,MAAM;SACxB,CAAC;QACF,MAAM;KACP,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;AACnD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"speech.js","sourceRoot":"","sources":["../../../src/integrations/openai/speech.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,6 +41,15 @@ export interface TelegramMessage {
|
|
|
41
41
|
forum_topic_edited?: {
|
|
42
42
|
name?: string;
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Present when the operator replies to a message with part of it selected
|
|
46
|
+
* (Telegram's "quote" feature). `text` is the exact excerpt they highlighted.
|
|
47
|
+
*/
|
|
48
|
+
quote?: {
|
|
49
|
+
text: string;
|
|
50
|
+
position?: number;
|
|
51
|
+
is_manual?: boolean;
|
|
52
|
+
};
|
|
44
53
|
}
|
|
45
54
|
export interface PhotoSize {
|
|
46
55
|
file_id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/integrations/telegram/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,kBAAkB,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/integrations/telegram/types.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/markdown.d.ts
CHANGED
|
@@ -4,19 +4,6 @@
|
|
|
4
4
|
* Converts standard Markdown to Telegram MarkdownV2, working around
|
|
5
5
|
* several telegramify-markdown limitations.
|
|
6
6
|
*/
|
|
7
|
-
/**
|
|
8
|
-
* Convert standard Markdown to Telegram MarkdownV2.
|
|
9
|
-
*
|
|
10
|
-
* Works around several telegramify-markdown limitations:
|
|
11
|
-
* 1. Fenced code blocks are emitted as single-backtick inline code instead
|
|
12
|
-
* of triple-backtick blocks → pre-extract, re-insert after conversion.
|
|
13
|
-
* 2. Markdown tables contain `|` which is a MarkdownV2 reserved character;
|
|
14
|
-
* telegramify-markdown does not handle tables → pre-extract and wrap in
|
|
15
|
-
* a plain code block so the table layout is preserved.
|
|
16
|
-
* 3. Blockquotes with 'escape' strategy produce double-escaped characters
|
|
17
|
-
* (e.g. `\\.` instead of `\.`) → pre-convert `> text` to `▎ text`
|
|
18
|
-
* (a common Telegram convention) so the library never sees blockquotes.
|
|
19
|
-
*/
|
|
20
7
|
export declare function convertMarkdown(markdown: string): string;
|
|
21
8
|
/**
|
|
22
9
|
* Split a message into chunks that fit Telegram's 4096-char limit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/lib/markdown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/lib/markdown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwDH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAyFxD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAO,GAAG,MAAM,EAAE,CAelE"}
|
package/dist/lib/markdown.js
CHANGED
|
@@ -19,7 +19,38 @@ const telegramifyMarkdown = esmRequire("telegramify-markdown");
|
|
|
19
19
|
* 3. Blockquotes with 'escape' strategy produce double-escaped characters
|
|
20
20
|
* (e.g. `\\.` instead of `\.`) → pre-convert `> text` to `▎ text`
|
|
21
21
|
* (a common Telegram convention) so the library never sees blockquotes.
|
|
22
|
+
* 4. `\` is itself a MarkdownV2 reserved character but the library leaves it
|
|
23
|
+
* bare, so Telegram eats it as an escape lead-in and Windows paths lose
|
|
24
|
+
* every separator → protect literal backslashes across the conversion.
|
|
22
25
|
*/
|
|
26
|
+
/**
|
|
27
|
+
* Base stand-in for a literal `\` while telegramify-markdown runs. Must survive the
|
|
28
|
+
* library untouched — hence plain uppercase ASCII, which nothing escapes.
|
|
29
|
+
*
|
|
30
|
+
* The token is lengthened per call until it does not occur in the input (see
|
|
31
|
+
* {@link uniqueToken}): a message that legitimately contains this word — a paste of
|
|
32
|
+
* this very file, for instance — would otherwise have it rewritten to `\\`.
|
|
33
|
+
*/
|
|
34
|
+
const BACKSLASH_PLACEHOLDER_BASE = "BACKSLASHPLACEHOLDERX";
|
|
35
|
+
/** Extend `base` with `X`s until it appears nowhere in `source`. */
|
|
36
|
+
function uniqueToken(base, source) {
|
|
37
|
+
let token = base;
|
|
38
|
+
while (source.includes(token))
|
|
39
|
+
token += "X";
|
|
40
|
+
return token;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Backslashes we leave alone because they are a deliberate Markdown escape rather
|
|
44
|
+
* than a path separator.
|
|
45
|
+
*
|
|
46
|
+
* Restricted to the *inline formatting* delimiters. The wider MarkdownV2 reserved
|
|
47
|
+
* set (`.`, `-`, `+`, `=`, `|`, `{`, `}`, `>`, `#`) is only meaningful in Telegram's
|
|
48
|
+
* OUTPUT encoding, not in the standard Markdown we are given as INPUT — but those
|
|
49
|
+
* characters follow a separator constantly in real paths (`.\dist`, `..\..\src`,
|
|
50
|
+
* `C:\src\.git`). Treating `\.` as an escape swallowed the separator and reproduced
|
|
51
|
+
* the exact bug this protection exists to fix.
|
|
52
|
+
*/
|
|
53
|
+
const DELIBERATE_ESCAPE_TARGETS = /\\(?![_*[\]()~`!\\])/g;
|
|
23
54
|
export function convertMarkdown(markdown) {
|
|
24
55
|
const blocks = [];
|
|
25
56
|
const placeholder = (i) => `CODEBLOCKPLACEHOLDER${i}END`;
|
|
@@ -68,8 +99,22 @@ export function convertMarkdown(markdown) {
|
|
|
68
99
|
});
|
|
69
100
|
// 3. Convert Markdown blockquotes to ▎ prefix lines.
|
|
70
101
|
preprocessed = preprocessed.replace(/^>\s?(.*)$/gm, "▎ $1");
|
|
102
|
+
// 3b. Protect literal backslashes. telegramify-markdown escapes every
|
|
103
|
+
// MarkdownV2 reserved character except `\` itself, so a Windows path
|
|
104
|
+
// reaches Telegram as `C:\src\lib` — and Telegram's parser reads each
|
|
105
|
+
// `\x` as an escape sequence and swallows the separator ("C:srclib").
|
|
106
|
+
// Only backslashes that are NOT a deliberate Markdown escape are
|
|
107
|
+
// protected, so `\*literal star\*` keeps working.
|
|
108
|
+
const backslashToken = uniqueToken(BACKSLASH_PLACEHOLDER_BASE, markdown);
|
|
109
|
+
preprocessed = preprocessed.replace(DELIBERATE_ESCAPE_TARGETS, backslashToken);
|
|
71
110
|
// 4. Convert the rest with telegramify-markdown.
|
|
72
111
|
let converted = telegramifyMarkdown(preprocessed, "escape");
|
|
112
|
+
// 4b. Restore protected backslashes as MarkdownV2-escaped literals. This MUST
|
|
113
|
+
// happen before the code-block and table re-insertion below: those splice
|
|
114
|
+
// raw user content back in, already carrying their own escaping, and a
|
|
115
|
+
// later sweep for the token would rewrite any literal occurrence inside
|
|
116
|
+
// them (a code block quoting this file, say) into a stray `\\`.
|
|
117
|
+
converted = converted.replaceAll(backslashToken, "\\\\");
|
|
73
118
|
// 5. Re-insert code blocks in MarkdownV2 format.
|
|
74
119
|
converted = converted.replace(/CODEBLOCKPLACEHOLDER(\d+)END/g, (_m, idx) => {
|
|
75
120
|
const { lang, code } = blocks[parseInt(idx, 10)];
|
package/dist/lib/markdown.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/lib/markdown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,mBAAmB,GAAG,UAAU,CAAC,sBAAsB,CAGlD,CAAC;AAEZ
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/lib/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token-usage meter — public surface.
|
|
3
|
+
*
|
|
4
|
+
* Call sites import ONLY `recordUsage` from here (DIP). The pricing table and
|
|
5
|
+
* sink are internal details that can change without touching any call site.
|
|
6
|
+
*/
|
|
7
|
+
export { recordUsage } from "./meter.js";
|
|
8
|
+
export type { UsageEvent, UsageEventInput } from "./meter.js";
|
|
9
|
+
export { costOf, MODEL_PRICES } from "./pricing.js";
|
|
10
|
+
export type { ModelPrice, Priceable } from "./pricing.js";
|
|
11
|
+
export type { UsageSink } from "./sink.js";
|
|
12
|
+
export { JsonlUsageSink } from "./sink.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/usage-metering/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC1D,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token-usage meter — public surface.
|
|
3
|
+
*
|
|
4
|
+
* Call sites import ONLY `recordUsage` from here (DIP). The pricing table and
|
|
5
|
+
* sink are internal details that can change without touching any call site.
|
|
6
|
+
*/
|
|
7
|
+
export { recordUsage } from "./meter.js";
|
|
8
|
+
export { costOf, MODEL_PRICES } from "./pricing.js";
|
|
9
|
+
export { JsonlUsageSink } from "./sink.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/usage-metering/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGpD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token/cost meter (SRP): it ONLY meters. It computes cost via the pricing
|
|
3
|
+
* module and appends one record via a sink. It never throws into the caller —
|
|
4
|
+
* telemetry must not be able to break a real OpenAI call.
|
|
5
|
+
*
|
|
6
|
+
* Call sites depend on {@link recordUsage} alone (DIP) — not on the pricing
|
|
7
|
+
* table or the sink implementation.
|
|
8
|
+
*/
|
|
9
|
+
import { type UsageSink } from "./sink.js";
|
|
10
|
+
/** One metered OpenAI call. */
|
|
11
|
+
export interface UsageEvent {
|
|
12
|
+
/** Logical bucket: "chat" | "embedding" | "consolidation" | "transcription" … */
|
|
13
|
+
category: string;
|
|
14
|
+
/** Model id as sent to the provider (drives pricing). */
|
|
15
|
+
model: string;
|
|
16
|
+
/** Prompt/input tokens (chat, embeddings). */
|
|
17
|
+
promptTokens?: number;
|
|
18
|
+
/** Completion/output tokens (chat). */
|
|
19
|
+
completionTokens?: number;
|
|
20
|
+
/** Audio length in seconds (transcription). */
|
|
21
|
+
audioSeconds?: number;
|
|
22
|
+
/** Originating thread, when known. */
|
|
23
|
+
threadId?: number;
|
|
24
|
+
/** Epoch ms; stamped by {@link recordUsage}. */
|
|
25
|
+
timestamp: number;
|
|
26
|
+
}
|
|
27
|
+
/** Everything a caller supplies — the meter stamps {@link UsageEvent.timestamp}. */
|
|
28
|
+
export type UsageEventInput = Omit<UsageEvent, "timestamp">;
|
|
29
|
+
/**
|
|
30
|
+
* Record one usage event: compute its cost and append it via the sink.
|
|
31
|
+
* Best-effort — wrapped in try/catch so it NEVER throws into the caller.
|
|
32
|
+
*/
|
|
33
|
+
export declare function recordUsage(event: UsageEventInput, sink?: UsageSink): void;
|
|
34
|
+
//# sourceMappingURL=meter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meter.d.ts","sourceRoot":"","sources":["../../../src/lib/usage-metering/meter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3D,+BAA+B;AAC/B,MAAM,WAAW,UAAU;IACzB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,oFAAoF;AACpF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAK5D;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,GAAE,SAAuB,GAAG,IAAI,CASvF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token/cost meter (SRP): it ONLY meters. It computes cost via the pricing
|
|
3
|
+
* module and appends one record via a sink. It never throws into the caller —
|
|
4
|
+
* telemetry must not be able to break a real OpenAI call.
|
|
5
|
+
*
|
|
6
|
+
* Call sites depend on {@link recordUsage} alone (DIP) — not on the pricing
|
|
7
|
+
* table or the sink implementation.
|
|
8
|
+
*/
|
|
9
|
+
import { costOf } from "./pricing.js";
|
|
10
|
+
import { JsonlUsageSink } from "./sink.js";
|
|
11
|
+
/** The default JSONL sink; overridable (e.g. in tests) via the 2nd arg. */
|
|
12
|
+
const defaultSink = new JsonlUsageSink();
|
|
13
|
+
/**
|
|
14
|
+
* Record one usage event: compute its cost and append it via the sink.
|
|
15
|
+
* Best-effort — wrapped in try/catch so it NEVER throws into the caller.
|
|
16
|
+
*/
|
|
17
|
+
export function recordUsage(event, sink = defaultSink) {
|
|
18
|
+
try {
|
|
19
|
+
const timestamp = Date.now();
|
|
20
|
+
const costUsd = costOf(event);
|
|
21
|
+
const record = { ...event, timestamp, time: new Date(timestamp).toISOString(), costUsd };
|
|
22
|
+
sink.write(JSON.stringify(record));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
/* best-effort telemetry — swallow everything */
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=meter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meter.js","sourceRoot":"","sources":["../../../src/lib/usage-metering/meter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,cAAc,EAAkB,MAAM,WAAW,CAAC;AAuB3D,2EAA2E;AAC3E,MAAM,WAAW,GAAc,IAAI,cAAc,EAAE,CAAC;AAEpD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAsB,EAAE,OAAkB,WAAW;IAC/E,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC;QACzF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-model price table + a pure cost function (Open/Closed).
|
|
3
|
+
*
|
|
4
|
+
* Adding a model or provider is a TABLE edit here — never a change to the meter
|
|
5
|
+
* or the call sites. Prices are list rates; keep them in one place so a rate
|
|
6
|
+
* change is a one-line diff.
|
|
7
|
+
*
|
|
8
|
+
* Units:
|
|
9
|
+
* - inputPerMTok / outputPerMTok : USD per 1,000,000 tokens
|
|
10
|
+
* - audioPerMinute : USD per minute of audio (Whisper family)
|
|
11
|
+
*/
|
|
12
|
+
export interface ModelPrice {
|
|
13
|
+
/** USD per 1M prompt/input tokens. */
|
|
14
|
+
inputPerMTok?: number;
|
|
15
|
+
/** USD per 1M completion/output tokens. */
|
|
16
|
+
outputPerMTok?: number;
|
|
17
|
+
/** USD per minute of transcribed audio. */
|
|
18
|
+
audioPerMinute?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* List prices as of 2026-07. Sources:
|
|
22
|
+
* - OpenAI gpt-4o / gpt-4o-mini / text-embedding-3-small / whisper-1: openai.com/pricing
|
|
23
|
+
* - Groq whisper-large-v3: $0.111/hr (groq.com/pricing)
|
|
24
|
+
*/
|
|
25
|
+
export declare const MODEL_PRICES: Record<string, ModelPrice>;
|
|
26
|
+
/** Minimal shape needed to price a call — a subset of {@link UsageEvent}. */
|
|
27
|
+
export interface Priceable {
|
|
28
|
+
model: string;
|
|
29
|
+
promptTokens?: number;
|
|
30
|
+
completionTokens?: number;
|
|
31
|
+
audioSeconds?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Pure cost in USD for one usage event. Unknown models (absent from the table)
|
|
35
|
+
* cost 0 — pricing is best-effort telemetry, never a hard dependency. Missing
|
|
36
|
+
* token/audio fields simply contribute nothing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function costOf(event: Priceable): number;
|
|
39
|
+
//# sourceMappingURL=pricing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../../src/lib/usage-metering/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAUnD,CAAC;AAEF,6EAA6E;AAC7E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAc/C"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-model price table + a pure cost function (Open/Closed).
|
|
3
|
+
*
|
|
4
|
+
* Adding a model or provider is a TABLE edit here — never a change to the meter
|
|
5
|
+
* or the call sites. Prices are list rates; keep them in one place so a rate
|
|
6
|
+
* change is a one-line diff.
|
|
7
|
+
*
|
|
8
|
+
* Units:
|
|
9
|
+
* - inputPerMTok / outputPerMTok : USD per 1,000,000 tokens
|
|
10
|
+
* - audioPerMinute : USD per minute of audio (Whisper family)
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* List prices as of 2026-07. Sources:
|
|
14
|
+
* - OpenAI gpt-4o / gpt-4o-mini / text-embedding-3-small / whisper-1: openai.com/pricing
|
|
15
|
+
* - Groq whisper-large-v3: $0.111/hr (groq.com/pricing)
|
|
16
|
+
*/
|
|
17
|
+
export const MODEL_PRICES = {
|
|
18
|
+
// OpenAI chat
|
|
19
|
+
"gpt-4o": { inputPerMTok: 2.5, outputPerMTok: 10 },
|
|
20
|
+
"gpt-4o-mini": { inputPerMTok: 0.15, outputPerMTok: 0.6 },
|
|
21
|
+
// OpenAI embeddings (input only)
|
|
22
|
+
"text-embedding-3-small": { inputPerMTok: 0.02 },
|
|
23
|
+
// OpenAI transcription — $0.006/min
|
|
24
|
+
"whisper-1": { audioPerMinute: 0.006 },
|
|
25
|
+
// Groq transcription — $0.111/hr → per minute
|
|
26
|
+
"whisper-large-v3": { audioPerMinute: 0.111 / 60 },
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Pure cost in USD for one usage event. Unknown models (absent from the table)
|
|
30
|
+
* cost 0 — pricing is best-effort telemetry, never a hard dependency. Missing
|
|
31
|
+
* token/audio fields simply contribute nothing.
|
|
32
|
+
*/
|
|
33
|
+
export function costOf(event) {
|
|
34
|
+
const price = MODEL_PRICES[event.model];
|
|
35
|
+
if (!price)
|
|
36
|
+
return 0;
|
|
37
|
+
let usd = 0;
|
|
38
|
+
if (price.inputPerMTok && event.promptTokens) {
|
|
39
|
+
usd += (event.promptTokens / 1_000_000) * price.inputPerMTok;
|
|
40
|
+
}
|
|
41
|
+
if (price.outputPerMTok && event.completionTokens) {
|
|
42
|
+
usd += (event.completionTokens / 1_000_000) * price.outputPerMTok;
|
|
43
|
+
}
|
|
44
|
+
if (price.audioPerMinute && event.audioSeconds) {
|
|
45
|
+
usd += (event.audioSeconds / 60) * price.audioPerMinute;
|
|
46
|
+
}
|
|
47
|
+
return usd;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../../src/lib/usage-metering/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAA+B;IACtD,cAAc;IACd,QAAQ,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE;IAClD,aAAa,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE;IACzD,iCAAiC;IACjC,wBAAwB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;IAChD,oCAAoC;IACpC,WAAW,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE;IACtC,8CAA8C;IAC9C,kBAAkB,EAAE,EAAE,cAAc,EAAE,KAAK,GAAG,EAAE,EAAE;CACnD,CAAC;AAUF;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,KAAgB;IACrC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC;IACrB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QAC7C,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC;IAC/D,CAAC;IACD,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAClD,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC;IACpE,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QAC/C,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC;IAC1D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage sink (ISP + DIP): the meter depends only on this one tiny method, so
|
|
3
|
+
* swapping the JSONL file for a DB, HTTP endpoint, or UI stream later is a
|
|
4
|
+
* one-class change with no meter or call-site edits.
|
|
5
|
+
*/
|
|
6
|
+
export interface UsageSink {
|
|
7
|
+
/** Append one already-serialized record. Implementations must not throw. */
|
|
8
|
+
write(line: string): void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Default sink: appends one JSONL line per event to
|
|
12
|
+
* `<data>/logs/usage/usage-YYYYMMDD.jsonl` (one file per day). Best-effort —
|
|
13
|
+
* any filesystem error is swallowed so telemetry never breaks a real call.
|
|
14
|
+
*/
|
|
15
|
+
export declare class JsonlUsageSink implements UsageSink {
|
|
16
|
+
private readonly dir;
|
|
17
|
+
/** Dirs already `mkdir`-ed this process, so we hit the FS once, not per write. */
|
|
18
|
+
private readonly ensured;
|
|
19
|
+
constructor(dir?: string);
|
|
20
|
+
/** Create the target dir at most once per process; swallow any FS error. */
|
|
21
|
+
private ensureDir;
|
|
22
|
+
write(line: string): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=sink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sink.d.ts","sourceRoot":"","sources":["../../../src/lib/usage-metering/sink.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,SAAS;IACxB,4EAA4E;IAC5E,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAaD;;;;GAIG;AACH,qBAAa,cAAe,YAAW,SAAS;IAIlC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHhC,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEhB,GAAG,GAAE,MAAkB;IAEpD,4EAA4E;IAC5E,OAAO,CAAC,SAAS;IAWjB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAU1B"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage sink (ISP + DIP): the meter depends only on this one tiny method, so
|
|
3
|
+
* swapping the JSONL file for a DB, HTTP endpoint, or UI stream later is a
|
|
4
|
+
* one-class change with no meter or call-site edits.
|
|
5
|
+
*/
|
|
6
|
+
import { mkdirSync } from "node:fs";
|
|
7
|
+
import { appendFile } from "node:fs/promises";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
/** Base data dir, matching the pattern used across the app (see process.service.ts). */
|
|
11
|
+
const USAGE_DIR = join(homedir(), ".remote-copilot-mcp", "logs", "usage");
|
|
12
|
+
/** Local YYYYMMDD for daily-rotated filenames. */
|
|
13
|
+
function dayStamp(d) {
|
|
14
|
+
const y = d.getFullYear();
|
|
15
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
16
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
17
|
+
return `${y}${m}${day}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Default sink: appends one JSONL line per event to
|
|
21
|
+
* `<data>/logs/usage/usage-YYYYMMDD.jsonl` (one file per day). Best-effort —
|
|
22
|
+
* any filesystem error is swallowed so telemetry never breaks a real call.
|
|
23
|
+
*/
|
|
24
|
+
export class JsonlUsageSink {
|
|
25
|
+
dir;
|
|
26
|
+
/** Dirs already `mkdir`-ed this process, so we hit the FS once, not per write. */
|
|
27
|
+
ensured = new Set();
|
|
28
|
+
constructor(dir = USAGE_DIR) {
|
|
29
|
+
this.dir = dir;
|
|
30
|
+
}
|
|
31
|
+
/** Create the target dir at most once per process; swallow any FS error. */
|
|
32
|
+
ensureDir() {
|
|
33
|
+
if (this.ensured.has(this.dir))
|
|
34
|
+
return true;
|
|
35
|
+
try {
|
|
36
|
+
mkdirSync(this.dir, { recursive: true });
|
|
37
|
+
this.ensured.add(this.dir);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
write(line) {
|
|
45
|
+
if (!this.ensureDir())
|
|
46
|
+
return;
|
|
47
|
+
const file = join(this.dir, `usage-${dayStamp(new Date())}.jsonl`);
|
|
48
|
+
// Fire-and-forget: no synchronous FS on the hot path. Ordering within the
|
|
49
|
+
// file is best-effort. The .catch() no-ops so a rejected write never
|
|
50
|
+
// surfaces as an unhandled rejection or reaches the caller.
|
|
51
|
+
void appendFile(file, line + "\n").catch(() => {
|
|
52
|
+
/* best-effort telemetry — never throw into the caller */
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=sink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sink.js","sourceRoot":"","sources":["../../../src/lib/usage-metering/sink.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAOjC,wFAAwF;AACxF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,qBAAqB,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1E,kDAAkD;AAClD,SAAS,QAAQ,CAAC,CAAO;IACvB,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAII;IAH7B,kFAAkF;IACjE,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAE7C,YAA6B,MAAc,SAAS;QAAvB,QAAG,GAAH,GAAG,CAAoB;IAAG,CAAC;IAExD,4EAA4E;IACpE,SAAS;QACf,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC5C,IAAI,CAAC;YACH,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE,OAAO;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC;QACnE,0EAA0E;QAC1E,qEAAqE;QACrE,4DAA4D;QAC5D,KAAK,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YAC5C,yDAAyD;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/dist/server/factory.js
CHANGED
|
@@ -424,20 +424,23 @@ function createMcpServer(telegram, telegramChatId, getMemoryDb, threadLifecycle,
|
|
|
424
424
|
return handleStartThread(safeArgs, delegateCtx);
|
|
425
425
|
},
|
|
426
426
|
send_message_to_thread: async (typedArgs) => {
|
|
427
|
-
//
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
|
|
427
|
+
// Does NOT count as an operator-facing send: this routes output to another
|
|
428
|
+
// thread's topic, not the operator's view of THIS thread. An orchestrator
|
|
429
|
+
// that delegates to a worker AND writes its status for the operator as
|
|
430
|
+
// plain stdout in the same turn must still have that status auto-forwarded
|
|
431
|
+
// to its own topic — otherwise the operator sees the thread go silent.
|
|
432
|
+
return handleSendMessageToThreadFile({
|
|
431
433
|
...typedArgs,
|
|
432
434
|
_callerThreadId: currentThreadId,
|
|
433
435
|
});
|
|
434
|
-
if (!result.isError)
|
|
435
|
-
operatorSendsThisTurn++;
|
|
436
|
-
return result;
|
|
437
436
|
},
|
|
438
|
-
get_threads_health: () => {
|
|
437
|
+
get_threads_health: (typedArgs) => {
|
|
439
438
|
try {
|
|
440
|
-
const markdown = getThreadsHealth(getMemoryDb
|
|
439
|
+
const markdown = getThreadsHealth(getMemoryDb, {
|
|
440
|
+
status: typedArgs?.status,
|
|
441
|
+
includeDead: typedArgs?.includeDead,
|
|
442
|
+
limit: typedArgs?.limit,
|
|
443
|
+
});
|
|
441
444
|
return { content: [{ type: "text", text: markdown }] };
|
|
442
445
|
}
|
|
443
446
|
catch (err) {
|