open-agents-ai 0.38.0 → 0.38.1
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 +11 -4
- package/dist/index.js +125 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ An autonomous multi-turn tool-calling agent that reads your code, makes changes,
|
|
|
61
61
|
- **Self-learning** — auto-fetches docs from the web when encountering unfamiliar APIs
|
|
62
62
|
- **Seamless `/update`** — in-place update and reload with automatic context save/restore
|
|
63
63
|
- **Blessed mode** — `/full-send-bless` infinite warm loop keeps model weights in VRAM, auto-cycles tasks, never exits until you say stop
|
|
64
|
-
- **Telegram bridge** — `/telegram <token>` public ingress/egress with mandatory safety filter
|
|
64
|
+
- **Telegram bridge** — `/telegram --key <token> --admin <userid>` public ingress/egress with admin filter and mandatory safety filter; bare `/telegram` toggles the service watchdog
|
|
65
65
|
- **Task control** — `/pause` (gentle halt at turn boundary), `/stop` (immediate kill), `/resume` to continue
|
|
66
66
|
- **Model-tier awareness** — dynamic tool sets, prompt complexity, and context limits scale with model size (small/medium/large)
|
|
67
67
|
|
|
@@ -275,10 +275,17 @@ When blessed mode is active:
|
|
|
275
275
|
Connect the agent to a Telegram bot for public-facing message handling. Messages received from Telegram are processed with a mandatory safety filter that warns the agent it is talking to the general public.
|
|
276
276
|
|
|
277
277
|
```bash
|
|
278
|
-
/telegram <
|
|
279
|
-
/telegram
|
|
278
|
+
/telegram --key <token> # Save bot token (persisted to .oa/settings.json)
|
|
279
|
+
/telegram --admin <userid> # Set admin filter — only this user can interact
|
|
280
|
+
/telegram # Toggle bridge on/off (uses saved key)
|
|
281
|
+
/telegram status # Show connection status
|
|
282
|
+
/telegram stop # Disconnect
|
|
280
283
|
```
|
|
281
284
|
|
|
285
|
+
The bot token and admin ID are persisted to project settings, so you only need to set them once. After that, bare `/telegram` toggles the bridge on and off like a service watchdog.
|
|
286
|
+
|
|
287
|
+
**Admin filter** — when `--admin` is set, only messages from that user ID (numeric Telegram ID or username) are processed. All other messages are silently ignored. This lets you lock down the bot to a single operator.
|
|
288
|
+
|
|
282
289
|
**Safety filter** — every Telegram-sourced task is wrapped with strict safety instructions:
|
|
283
290
|
- Never share private information, API keys, file paths, or system internals
|
|
284
291
|
- Never execute destructive commands based on Telegram input
|
|
@@ -288,7 +295,7 @@ Connect the agent to a Telegram bot for public-facing message handling. Messages
|
|
|
288
295
|
|
|
289
296
|
**Egress** — when a task completes that originated from Telegram, the agent's summary is automatically sent back to the originating chat. Long responses are truncated to Telegram's 4096-character limit.
|
|
290
297
|
|
|
291
|
-
**Combined with blessed mode** — `/full-send-bless` + `/telegram
|
|
298
|
+
**Combined with blessed mode** — `/full-send-bless` + `/telegram` creates a persistent, always-on agent that processes Telegram messages around the clock while keeping the model warm.
|
|
292
299
|
|
|
293
300
|
## Listen Mode — Live Bidirectional Audio
|
|
294
301
|
|
package/dist/index.js
CHANGED
|
@@ -16920,7 +16920,10 @@ function renderSlashHelp() {
|
|
|
16920
16920
|
["/<skill-name> [args]", "Invoke an AIWG skill directly"],
|
|
16921
16921
|
["/full-send-bless", "Infinite warm loop \u2014 keeps model in VRAM, auto-cycles tasks"],
|
|
16922
16922
|
["/bless stop", "End blessed mode"],
|
|
16923
|
-
["/telegram <token>", "
|
|
16923
|
+
["/telegram --key <token>", "Save Telegram bot token (persisted to settings)"],
|
|
16924
|
+
["/telegram --admin <userid>", "Set admin user filter (only this user can interact)"],
|
|
16925
|
+
["/telegram", "Toggle Telegram bridge on/off (uses saved key)"],
|
|
16926
|
+
["/telegram status", "Show Telegram bridge status"],
|
|
16924
16927
|
["/telegram stop", "Disconnect Telegram bridge"],
|
|
16925
16928
|
["/style", "Show current response style"],
|
|
16926
16929
|
["/style <preset>", "Set style: concise, balanced, verbose, pedagogical"],
|
|
@@ -19645,7 +19648,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
19645
19648
|
}
|
|
19646
19649
|
case "telegram":
|
|
19647
19650
|
case "tg": {
|
|
19648
|
-
|
|
19651
|
+
const parts = arg ? arg.split(/\s+/) : [];
|
|
19652
|
+
if (parts[0] === "stop" || parts[0] === "off") {
|
|
19649
19653
|
if (ctx.isTelegramActive?.()) {
|
|
19650
19654
|
ctx.telegramStop?.();
|
|
19651
19655
|
} else {
|
|
@@ -19653,20 +19657,59 @@ async function handleSlashCommand(input, ctx) {
|
|
|
19653
19657
|
}
|
|
19654
19658
|
return "handled";
|
|
19655
19659
|
}
|
|
19656
|
-
if (
|
|
19657
|
-
|
|
19660
|
+
if (parts[0] === "status") {
|
|
19661
|
+
ctx.telegramStatus?.();
|
|
19658
19662
|
return "handled";
|
|
19659
19663
|
}
|
|
19660
|
-
|
|
19661
|
-
|
|
19662
|
-
|
|
19664
|
+
const keyIdx = parts.indexOf("--key");
|
|
19665
|
+
if (keyIdx !== -1) {
|
|
19666
|
+
const token = parts[keyIdx + 1];
|
|
19667
|
+
if (!token) {
|
|
19668
|
+
renderWarning("Usage: /telegram --key <bot-token>");
|
|
19669
|
+
renderInfo("Get a bot token from @BotFather on Telegram.");
|
|
19670
|
+
return "handled";
|
|
19671
|
+
}
|
|
19672
|
+
ctx.saveTelegramSettings?.({ key: token });
|
|
19673
|
+
renderInfo(`Telegram bot token saved (${token.slice(0, 6)}...). Use /telegram to start.`);
|
|
19663
19674
|
return "handled";
|
|
19664
19675
|
}
|
|
19665
|
-
|
|
19666
|
-
|
|
19667
|
-
|
|
19668
|
-
|
|
19676
|
+
const adminIdx = parts.indexOf("--admin");
|
|
19677
|
+
if (adminIdx !== -1) {
|
|
19678
|
+
const userId = parts[adminIdx + 1];
|
|
19679
|
+
if (!userId) {
|
|
19680
|
+
renderWarning("Usage: /telegram --admin <user-id-or-username>");
|
|
19681
|
+
return "handled";
|
|
19682
|
+
}
|
|
19683
|
+
ctx.saveTelegramSettings?.({ admin: userId });
|
|
19684
|
+
renderInfo(`Telegram admin set to ${c2.bold(userId)}. Only this user's messages will be processed.`);
|
|
19685
|
+
return "handled";
|
|
19669
19686
|
}
|
|
19687
|
+
if (!arg) {
|
|
19688
|
+
if (ctx.isTelegramActive?.()) {
|
|
19689
|
+
ctx.telegramStop?.();
|
|
19690
|
+
return "handled";
|
|
19691
|
+
}
|
|
19692
|
+
const settings = ctx.getTelegramSettings?.() ?? {};
|
|
19693
|
+
if (!settings.key) {
|
|
19694
|
+
renderWarning("No Telegram bot token configured.");
|
|
19695
|
+
renderInfo("Set one first: /telegram --key <bot-token>");
|
|
19696
|
+
renderInfo("Get a token from @BotFather on Telegram.");
|
|
19697
|
+
return "handled";
|
|
19698
|
+
}
|
|
19699
|
+
try {
|
|
19700
|
+
await ctx.telegramStart?.(settings.key, settings.admin);
|
|
19701
|
+
} catch (err) {
|
|
19702
|
+
renderError(`Telegram error: ${err instanceof Error ? err.message : String(err)}`);
|
|
19703
|
+
}
|
|
19704
|
+
return "handled";
|
|
19705
|
+
}
|
|
19706
|
+
renderWarning(`Unknown argument: "${arg}"`);
|
|
19707
|
+
renderInfo("Usage:");
|
|
19708
|
+
renderInfo(" /telegram --key <token> Save bot token");
|
|
19709
|
+
renderInfo(" /telegram --admin <id> Set admin user filter");
|
|
19710
|
+
renderInfo(" /telegram Toggle on/off");
|
|
19711
|
+
renderInfo(" /telegram stop Stop bridge");
|
|
19712
|
+
renderInfo(" /telegram status Show status");
|
|
19670
19713
|
return "handled";
|
|
19671
19714
|
}
|
|
19672
19715
|
default: {
|
|
@@ -23535,18 +23578,43 @@ var init_bless_engine = __esm({
|
|
|
23535
23578
|
});
|
|
23536
23579
|
|
|
23537
23580
|
// packages/cli/dist/tui/telegram-bridge.js
|
|
23538
|
-
function renderTelegramStart(botUsername) {
|
|
23581
|
+
function renderTelegramStart(botUsername, adminId) {
|
|
23539
23582
|
process.stdout.write(`
|
|
23540
23583
|
${c2.cyan("\u2708")} ${c2.bold("Telegram Bridge")} connected as @${botUsername}
|
|
23541
23584
|
`);
|
|
23542
|
-
|
|
23585
|
+
if (adminId) {
|
|
23586
|
+
process.stdout.write(` ${c2.dim(`Admin filter: only user ${adminId}`)}
|
|
23543
23587
|
`);
|
|
23588
|
+
}
|
|
23544
23589
|
process.stdout.write(` ${c2.dim("Safety filter: ACTIVE \u2014 public channel mode")}
|
|
23545
23590
|
`);
|
|
23546
|
-
process.stdout.write(` ${c2.dim("Use /telegram
|
|
23591
|
+
process.stdout.write(` ${c2.dim("Use /telegram to toggle off, or /telegram stop")}
|
|
23547
23592
|
|
|
23548
23593
|
`);
|
|
23549
23594
|
}
|
|
23595
|
+
function renderTelegramStatus(active, botUsername, adminId) {
|
|
23596
|
+
if (active) {
|
|
23597
|
+
process.stdout.write(`
|
|
23598
|
+
${c2.green("\u25CF")} Telegram bridge: ${c2.bold("ACTIVE")} (@${botUsername ?? "?"})
|
|
23599
|
+
`);
|
|
23600
|
+
if (adminId) {
|
|
23601
|
+
process.stdout.write(` Admin: ${adminId}
|
|
23602
|
+
`);
|
|
23603
|
+
}
|
|
23604
|
+
process.stdout.write(` ${c2.dim("Use /telegram to toggle off")}
|
|
23605
|
+
|
|
23606
|
+
`);
|
|
23607
|
+
} else {
|
|
23608
|
+
process.stdout.write(`
|
|
23609
|
+
${c2.dim("\u25CB")} Telegram bridge: ${c2.bold("INACTIVE")}
|
|
23610
|
+
`);
|
|
23611
|
+
process.stdout.write(` ${c2.dim("Use /telegram --key <token> to set bot token")}
|
|
23612
|
+
`);
|
|
23613
|
+
process.stdout.write(` ${c2.dim("Use /telegram to toggle on (after key is set)")}
|
|
23614
|
+
|
|
23615
|
+
`);
|
|
23616
|
+
}
|
|
23617
|
+
}
|
|
23550
23618
|
function renderTelegramStop(state) {
|
|
23551
23619
|
process.stdout.write(`
|
|
23552
23620
|
${c2.yellow("\u2708")} ${c2.bold("Telegram Bridge")} disconnected
|
|
@@ -23599,10 +23667,16 @@ prioritize safety and privacy over helpfulness. When in doubt, decline politely.
|
|
|
23599
23667
|
messagesReceived: 0,
|
|
23600
23668
|
messagesSent: 0
|
|
23601
23669
|
};
|
|
23670
|
+
/** Admin user ID — if set, only messages from this user are processed */
|
|
23671
|
+
adminUserId = null;
|
|
23602
23672
|
constructor(botToken, onMessage) {
|
|
23603
23673
|
this.botToken = botToken;
|
|
23604
23674
|
this.onMessage = onMessage;
|
|
23605
23675
|
}
|
|
23676
|
+
/** Set admin user ID filter. Only messages from this user will be processed. */
|
|
23677
|
+
setAdmin(userId) {
|
|
23678
|
+
this.adminUserId = userId;
|
|
23679
|
+
}
|
|
23606
23680
|
get isActive() {
|
|
23607
23681
|
return this.polling;
|
|
23608
23682
|
}
|
|
@@ -23673,11 +23747,19 @@ prioritize safety and privacy over helpfulness. When in doubt, decline politely.
|
|
|
23673
23747
|
for (const update of result.result) {
|
|
23674
23748
|
this.lastUpdateId = update.update_id;
|
|
23675
23749
|
if (update.message?.text) {
|
|
23750
|
+
const fromId = String(update.message.from?.id ?? "");
|
|
23751
|
+
const fromUser = update.message.from?.username ?? "";
|
|
23752
|
+
if (this.adminUserId) {
|
|
23753
|
+
const isAdmin = fromId === this.adminUserId || fromUser === this.adminUserId;
|
|
23754
|
+
if (!isAdmin) {
|
|
23755
|
+
continue;
|
|
23756
|
+
}
|
|
23757
|
+
}
|
|
23676
23758
|
this.state.messagesReceived++;
|
|
23677
23759
|
this.onMessage({
|
|
23678
23760
|
chatId: update.message.chat.id,
|
|
23679
23761
|
text: update.message.text,
|
|
23680
|
-
username:
|
|
23762
|
+
username: fromUser || "unknown",
|
|
23681
23763
|
firstName: update.message.from?.first_name,
|
|
23682
23764
|
messageId: update.message.message_id
|
|
23683
23765
|
});
|
|
@@ -25803,7 +25885,7 @@ async function startInteractive(config, repoPath) {
|
|
|
25803
25885
|
return blessEngine?.isActive ?? false;
|
|
25804
25886
|
},
|
|
25805
25887
|
// Telegram bridge
|
|
25806
|
-
async telegramStart(token) {
|
|
25888
|
+
async telegramStart(token, adminId) {
|
|
25807
25889
|
telegramBridge = new TelegramBridge(token, (msg) => {
|
|
25808
25890
|
writeContent(() => renderTelegramMessage(msg.username, msg.text));
|
|
25809
25891
|
if (!activeTask) {
|
|
@@ -25825,8 +25907,11 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
25825
25907
|
showPrompt();
|
|
25826
25908
|
}
|
|
25827
25909
|
});
|
|
25910
|
+
if (adminId) {
|
|
25911
|
+
telegramBridge.setAdmin(adminId);
|
|
25912
|
+
}
|
|
25828
25913
|
await telegramBridge.start();
|
|
25829
|
-
writeContent(() => renderTelegramStart(telegramBridge.botUsername));
|
|
25914
|
+
writeContent(() => renderTelegramStart(telegramBridge.botUsername, adminId));
|
|
25830
25915
|
showPrompt();
|
|
25831
25916
|
},
|
|
25832
25917
|
telegramStop() {
|
|
@@ -25840,6 +25925,29 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
25840
25925
|
isTelegramActive() {
|
|
25841
25926
|
return telegramBridge?.isActive ?? false;
|
|
25842
25927
|
},
|
|
25928
|
+
getTelegramSettings() {
|
|
25929
|
+
return {
|
|
25930
|
+
key: savedSettings.telegramKey,
|
|
25931
|
+
admin: savedSettings.telegramAdmin
|
|
25932
|
+
};
|
|
25933
|
+
},
|
|
25934
|
+
saveTelegramSettings(settings) {
|
|
25935
|
+
if (settings.key !== void 0) {
|
|
25936
|
+
savedSettings.telegramKey = settings.key;
|
|
25937
|
+
}
|
|
25938
|
+
if (settings.admin !== void 0) {
|
|
25939
|
+
savedSettings.telegramAdmin = settings.admin;
|
|
25940
|
+
}
|
|
25941
|
+
saveProjectSettings(repoRoot, {
|
|
25942
|
+
...settings.key !== void 0 ? { telegramKey: settings.key } : {},
|
|
25943
|
+
...settings.admin !== void 0 ? { telegramAdmin: settings.admin } : {}
|
|
25944
|
+
});
|
|
25945
|
+
},
|
|
25946
|
+
telegramStatus() {
|
|
25947
|
+
const active = telegramBridge?.isActive ?? false;
|
|
25948
|
+
const botUser = active ? telegramBridge?.botUsername : void 0;
|
|
25949
|
+
writeContent(() => renderTelegramStatus(active, botUser, savedSettings.telegramAdmin));
|
|
25950
|
+
},
|
|
25843
25951
|
// Listen mode (transcribe-cli integration)
|
|
25844
25952
|
async listenToggle() {
|
|
25845
25953
|
const engine = getListenEngine();
|
package/package.json
CHANGED