@phuetz/code-buddy 1.5.0 → 1.6.0
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 +9 -3
- package/dist/agent/codebuddy-agent.d.ts +6 -0
- package/dist/agent/codebuddy-agent.js +8 -0
- package/dist/agent/tool-handler.d.ts +6 -0
- package/dist/agent/tool-handler.js +9 -0
- package/dist/channels/core.d.ts +3 -0
- package/dist/channels/telegram/client.d.ts +14 -0
- package/dist/channels/telegram/client.js +60 -12
- package/dist/codebuddy/tools.js +6 -2
- package/dist/commands/council.d.ts +29 -0
- package/dist/commands/council.js +299 -0
- package/dist/commands/handlers/channel-handlers.d.ts +9 -6
- package/dist/commands/handlers/channel-handlers.js +216 -41
- package/dist/fleet/model-scoreboard.d.ts +62 -0
- package/dist/fleet/model-scoreboard.js +131 -0
- package/dist/index.js +21 -0
- package/dist/mcp/client.js +10 -2
- package/dist/memory/persistent-memory.d.ts +7 -1
- package/dist/memory/persistent-memory.js +26 -5
- package/dist/security/approval-modes.js +4 -0
- package/dist/tools/registry/memory-tools.d.ts +5 -5
- package/dist/tools/registry/memory-tools.js +24 -8
- package/dist/tools/registry/types.d.ts +3 -0
- package/dist/voice/local-tts.d.ts +6 -0
- package/dist/voice/local-tts.js +32 -1
- package/package.json +4 -1
|
@@ -17,8 +17,12 @@ import { executeHermesLifecycleHook } from '../../hooks/hermes-lifecycle-hooks.j
|
|
|
17
17
|
export class RememberTool {
|
|
18
18
|
name = 'remember';
|
|
19
19
|
description = 'Store important information, decisions, or preferences in persistent memory. This survives across sessions and is project-scoped by default.';
|
|
20
|
-
async execute(input) {
|
|
21
|
-
|
|
20
|
+
async execute(input, context) {
|
|
21
|
+
// Per-bot memory (multi-bot channels): scope by botId so bots don't share
|
|
22
|
+
// each other's facts. No botId = global memory (default). initialize() is
|
|
23
|
+
// idempotent, so this is cheap for the already-initialized global instance.
|
|
24
|
+
const mm = getMemoryManager(undefined, context?.botId);
|
|
25
|
+
await mm.initialize();
|
|
22
26
|
let key = input.key;
|
|
23
27
|
let value = input.value;
|
|
24
28
|
let scope = input.scope ?? 'project';
|
|
@@ -126,8 +130,12 @@ export class RememberTool {
|
|
|
126
130
|
export class ReplaceMemoryTool {
|
|
127
131
|
name = 'replace_memory';
|
|
128
132
|
description = 'Replace an existing persistent memory entry. Use when a stored fact is obsolete or too verbose and must be rewritten under the memory char budget.';
|
|
129
|
-
async execute(input) {
|
|
130
|
-
|
|
133
|
+
async execute(input, context) {
|
|
134
|
+
// Per-bot memory (multi-bot channels): scope by botId so bots don't share
|
|
135
|
+
// each other's facts. No botId = global memory (default). initialize() is
|
|
136
|
+
// idempotent, so this is cheap for the already-initialized global instance.
|
|
137
|
+
const mm = getMemoryManager(undefined, context?.botId);
|
|
138
|
+
await mm.initialize();
|
|
131
139
|
let key = input.key;
|
|
132
140
|
let value = input.value;
|
|
133
141
|
let scope = input.scope ?? 'project';
|
|
@@ -343,8 +351,12 @@ export class MemoryProposeTool {
|
|
|
343
351
|
export class RecallTool {
|
|
344
352
|
name = 'recall';
|
|
345
353
|
description = 'Explicitly retrieve a specific memory entry by its key. Use this if the information is not currently in your system prompt.';
|
|
346
|
-
async execute(input) {
|
|
347
|
-
|
|
354
|
+
async execute(input, context) {
|
|
355
|
+
// Per-bot memory (multi-bot channels): scope by botId so bots don't share
|
|
356
|
+
// each other's facts. No botId = global memory (default). initialize() is
|
|
357
|
+
// idempotent, so this is cheap for the already-initialized global instance.
|
|
358
|
+
const mm = getMemoryManager(undefined, context?.botId);
|
|
359
|
+
await mm.initialize();
|
|
348
360
|
const key = input.key;
|
|
349
361
|
const scope = input.scope;
|
|
350
362
|
const value = mm.recall(key, scope);
|
|
@@ -416,8 +428,12 @@ ${value}`,
|
|
|
416
428
|
export class ForgetTool {
|
|
417
429
|
name = 'forget';
|
|
418
430
|
description = 'Remove a memory entry that is no longer valid or useful.';
|
|
419
|
-
async execute(input) {
|
|
420
|
-
|
|
431
|
+
async execute(input, context) {
|
|
432
|
+
// Per-bot memory (multi-bot channels): scope by botId so bots don't share
|
|
433
|
+
// each other's facts. No botId = global memory (default). initialize() is
|
|
434
|
+
// idempotent, so this is cheap for the already-initialized global instance.
|
|
435
|
+
const mm = getMemoryManager(undefined, context?.botId);
|
|
436
|
+
await mm.initialize();
|
|
421
437
|
const key = input.key;
|
|
422
438
|
const scope = input.scope ?? 'project';
|
|
423
439
|
const deleted = await mm.forget(key, scope);
|
|
@@ -157,6 +157,9 @@ export interface IToolExecutionContext {
|
|
|
157
157
|
dryRun?: boolean;
|
|
158
158
|
/** Abort signal for cancellation */
|
|
159
159
|
abortSignal?: AbortSignal;
|
|
160
|
+
/** Multi-bot channels (e.g. Telegram): the bot that triggered this call, used
|
|
161
|
+
* to scope per-bot persistent memory / lessons. Undefined = global (default). */
|
|
162
|
+
botId?: string;
|
|
160
163
|
/** Custom context data */
|
|
161
164
|
extra?: Record<string, unknown>;
|
|
162
165
|
}
|
|
@@ -5,6 +5,12 @@ export interface LocalTtsOptions {
|
|
|
5
5
|
ffmpeg?: string;
|
|
6
6
|
timeoutMs?: number;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Turn Markdown into clean prose for speech, so the TTS doesn't literally read
|
|
10
|
+
* out "asterisk asterisk", backticks, hashes or bullet dashes — it should sound
|
|
11
|
+
* like a person talking, not a screen reader narrating syntax.
|
|
12
|
+
*/
|
|
13
|
+
export declare function cleanForSpeech(text: string): string;
|
|
8
14
|
/**
|
|
9
15
|
* Synthesize `text` to an OGG/Opus file (Telegram voice-note format) and return
|
|
10
16
|
* its path. Caller is responsible for deleting the file. Throws if Piper or
|
package/dist/voice/local-tts.js
CHANGED
|
@@ -74,6 +74,37 @@ function run(cmd, args, opts) {
|
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Turn Markdown into clean prose for speech, so the TTS doesn't literally read
|
|
79
|
+
* out "asterisk asterisk", backticks, hashes or bullet dashes — it should sound
|
|
80
|
+
* like a person talking, not a screen reader narrating syntax.
|
|
81
|
+
*/
|
|
82
|
+
export function cleanForSpeech(text) {
|
|
83
|
+
let t = text;
|
|
84
|
+
// Fenced code blocks: keep the inner text, drop the ``` fences/language tag.
|
|
85
|
+
t = t.replace(/```[\w-]*\n?/g, '').replace(/```/g, '');
|
|
86
|
+
// Inline code, bold, italic — keep the words, drop the markers.
|
|
87
|
+
t = t.replace(/`([^`]+)`/g, '$1');
|
|
88
|
+
t = t.replace(/\*\*([^*]+)\*\*/g, '$1').replace(/\*([^*]+)\*/g, '$1');
|
|
89
|
+
t = t.replace(/__([^_]+)__/g, '$1').replace(/_([^_]+)_/g, '$1');
|
|
90
|
+
// Links / images → spoken label only.
|
|
91
|
+
t = t.replace(/!\[([^\]]*)\]\([^)]*\)/g, '$1');
|
|
92
|
+
t = t.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1');
|
|
93
|
+
// Line-start markers: headings, blockquotes, list bullets, ordered items.
|
|
94
|
+
t = t.replace(/^\s{0,3}#{1,6}\s+/gm, '');
|
|
95
|
+
t = t.replace(/^\s*>\s?/gm, '');
|
|
96
|
+
t = t.replace(/^\s*[-*+]\s+/gm, '');
|
|
97
|
+
t = t.replace(/^\s*\d+[.)]\s+/gm, '');
|
|
98
|
+
// Horizontal rules.
|
|
99
|
+
t = t.replace(/^\s*([-*_])\1{2,}\s*$/gm, '');
|
|
100
|
+
// Any leftover Markdown punctuation a voice would mispronounce.
|
|
101
|
+
t = t.replace(/[*_`#>~]/g, '');
|
|
102
|
+
// Newlines → sentence breaks; collapse and de-duplicate punctuation/space.
|
|
103
|
+
t = t.replace(/\n{2,}/g, '. ').replace(/\n/g, '. ');
|
|
104
|
+
t = t.replace(/\s{2,}/g, ' ');
|
|
105
|
+
t = t.replace(/\s*\.(\s*\.)+\s*/g, '. ');
|
|
106
|
+
return t.trim();
|
|
107
|
+
}
|
|
77
108
|
/**
|
|
78
109
|
* Synthesize `text` to an OGG/Opus file (Telegram voice-note format) and return
|
|
79
110
|
* its path. Caller is responsible for deleting the file. Throws if Piper or
|
|
@@ -91,7 +122,7 @@ export async function synthesizeToOgg(text, options = {}) {
|
|
|
91
122
|
if (voice)
|
|
92
123
|
piperArgs.push('--model', voice);
|
|
93
124
|
try {
|
|
94
|
-
await run(bin, piperArgs, { stdin: text, timeoutMs });
|
|
125
|
+
await run(bin, piperArgs, { stdin: cleanForSpeech(text), timeoutMs });
|
|
95
126
|
// Telegram voice notes want OGG/Opus mono. 32 kbps is plenty for speech.
|
|
96
127
|
await run(ffmpeg, ['-y', '-loglevel', 'error', '-i', wav, '-ac', '1', '-c:a', 'libopus', '-b:a', '32k', ogg], { timeoutMs });
|
|
97
128
|
return ogg;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phuetz/code-buddy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Open-source multi-provider AI coding agent for the terminal, desktop, and HTTP. 15 LLM providers (Grok, Claude, ChatGPT, Gemini, Ollama, LM Studio, …) with ~110 tools, a peer-to-peer fleet, opt-in self-improvement, multi-channel messaging, and a skills system.",
|
|
5
5
|
"author": "Patrice Huetz <patrice.huetz@gmail.com>",
|
|
6
6
|
"repository": {
|
|
@@ -143,7 +143,9 @@
|
|
|
143
143
|
"@opentelemetry/api": "^1.9.0",
|
|
144
144
|
"@opentelemetry/exporter-trace-otlp-http": "^0.212.0",
|
|
145
145
|
"@opentelemetry/instrumentation-http": "^0.212.0",
|
|
146
|
+
"@opentelemetry/resources": "^2.5.1",
|
|
146
147
|
"@opentelemetry/sdk-node": "^0.212.0",
|
|
148
|
+
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
147
149
|
"@resvg/resvg-js": "^2.6.2",
|
|
148
150
|
"@sentry/node": "^10.40.0",
|
|
149
151
|
"@vscode/ripgrep": "^1.17.0",
|
|
@@ -161,6 +163,7 @@
|
|
|
161
163
|
"form-data": "^4.0.5",
|
|
162
164
|
"fs-extra": "^11.3.2",
|
|
163
165
|
"google-auth-library": "^10.6.2",
|
|
166
|
+
"highlight.js": "^10.7.3",
|
|
164
167
|
"ignore": "^5.3.2",
|
|
165
168
|
"ink": "^4.4.1",
|
|
166
169
|
"marked": "^15.0.12",
|