@openacp/cli 2026.401.2 → 2026.401.3
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/cli.js +217 -79
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.js +188 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7493,6 +7493,7 @@ function resolveInstanceRoot(opts) {
|
|
|
7493
7493
|
if (opts.global) return path21.join(os10.homedir(), ".openacp");
|
|
7494
7494
|
const localRoot = path21.join(cwd, ".openacp");
|
|
7495
7495
|
if (fs17.existsSync(localRoot)) return localRoot;
|
|
7496
|
+
if (process.env.OPENACP_INSTANCE_ROOT) return process.env.OPENACP_INSTANCE_ROOT;
|
|
7496
7497
|
return null;
|
|
7497
7498
|
}
|
|
7498
7499
|
function getGlobalRoot() {
|
|
@@ -10060,33 +10061,53 @@ var init_formatting = __esm({
|
|
|
10060
10061
|
}
|
|
10061
10062
|
});
|
|
10062
10063
|
|
|
10064
|
+
// src/core/utils/bypass-detection.ts
|
|
10065
|
+
function isPermissionBypass(value) {
|
|
10066
|
+
const lower = value.toLowerCase();
|
|
10067
|
+
return BYPASS_KEYWORDS.some((kw) => lower.includes(kw));
|
|
10068
|
+
}
|
|
10069
|
+
var BYPASS_KEYWORDS;
|
|
10070
|
+
var init_bypass_detection = __esm({
|
|
10071
|
+
"src/core/utils/bypass-detection.ts"() {
|
|
10072
|
+
"use strict";
|
|
10073
|
+
BYPASS_KEYWORDS = ["bypass", "dangerous", "skip", "dontask", "dont_ask", "auto_accept"];
|
|
10074
|
+
}
|
|
10075
|
+
});
|
|
10076
|
+
|
|
10063
10077
|
// src/plugins/telegram/commands/admin.ts
|
|
10064
10078
|
import { InlineKeyboard } from "grammy";
|
|
10079
|
+
function isBypassActive(session) {
|
|
10080
|
+
const modeOpt = session.getConfigByCategory("mode");
|
|
10081
|
+
return modeOpt?.type === "select" && isPermissionBypass(String(modeOpt.currentValue)) || !!session.clientOverrides.bypassPermissions;
|
|
10082
|
+
}
|
|
10065
10083
|
function setupDangerousModeCallbacks(bot, core) {
|
|
10066
10084
|
bot.callbackQuery(/^d:/, async (ctx) => {
|
|
10067
10085
|
const sessionId = ctx.callbackQuery.data.slice(2);
|
|
10068
10086
|
const session = core.sessionManager.getSession(sessionId);
|
|
10069
10087
|
if (session) {
|
|
10070
|
-
const
|
|
10071
|
-
|
|
10072
|
-
log14.info(
|
|
10073
|
-
{ sessionId, dangerousMode: newDangerousMode2 },
|
|
10074
|
-
"Bypass permissions toggled via button"
|
|
10075
|
-
);
|
|
10076
|
-
core.sessionManager.patchRecord(sessionId, { clientOverrides: session.clientOverrides }).catch(() => {
|
|
10077
|
-
});
|
|
10078
|
-
const toastText2 = newDangerousMode2 ? "\u2620\uFE0F Bypass enabled \u2014 permissions auto-approved" : "\u{1F510} Bypass disabled \u2014 approvals required";
|
|
10088
|
+
const wantOn = !isBypassActive(session);
|
|
10089
|
+
const toastText2 = wantOn ? "\u2620\uFE0F Bypass Permissions enabled \u2014 permissions auto-approved" : "\u{1F510} Bypass Permissions disabled \u2014 approvals required";
|
|
10079
10090
|
try {
|
|
10080
10091
|
await ctx.answerCallbackQuery({ text: toastText2 });
|
|
10081
10092
|
} catch {
|
|
10082
10093
|
}
|
|
10094
|
+
const registry = core.lifecycleManager?.serviceRegistry?.get("command-registry");
|
|
10095
|
+
if (registry) {
|
|
10096
|
+
await registry.execute(wantOn ? "/bypass on" : "/bypass off", {
|
|
10097
|
+
raw: wantOn ? "on" : "off",
|
|
10098
|
+
sessionId,
|
|
10099
|
+
channelId: "telegram",
|
|
10100
|
+
userId: String(ctx.from?.id ?? ""),
|
|
10101
|
+
reply: async () => {
|
|
10102
|
+
}
|
|
10103
|
+
}).catch(() => {
|
|
10104
|
+
});
|
|
10105
|
+
}
|
|
10106
|
+
log14.info({ sessionId, wantOn }, "Bypass permissions toggled via button");
|
|
10083
10107
|
try {
|
|
10084
|
-
await ctx.
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
newDangerousMode2,
|
|
10088
|
-
session.voiceMode === "on"
|
|
10089
|
-
)
|
|
10108
|
+
await ctx.editMessageText(buildSessionStatusText(session), {
|
|
10109
|
+
parse_mode: "HTML",
|
|
10110
|
+
reply_markup: buildSessionControlKeyboard(sessionId, isBypassActive(session), session.voiceMode === "on")
|
|
10090
10111
|
});
|
|
10091
10112
|
} catch {
|
|
10092
10113
|
}
|
|
@@ -10109,7 +10130,7 @@ function setupDangerousModeCallbacks(bot, core) {
|
|
|
10109
10130
|
{ sessionId, dangerousMode: newDangerousMode },
|
|
10110
10131
|
"Bypass permissions toggled via button (store-only, session not in memory)"
|
|
10111
10132
|
);
|
|
10112
|
-
const toastText = newDangerousMode ? "\u2620\uFE0F Bypass enabled \u2014 permissions auto-approved" : "\u{1F510} Bypass disabled \u2014 approvals required";
|
|
10133
|
+
const toastText = newDangerousMode ? "\u2620\uFE0F Bypass Permissions enabled \u2014 permissions auto-approved" : "\u{1F510} Bypass Permissions disabled \u2014 approvals required";
|
|
10113
10134
|
try {
|
|
10114
10135
|
await ctx.answerCallbackQuery({ text: toastText });
|
|
10115
10136
|
} catch {
|
|
@@ -10169,7 +10190,7 @@ async function handleEnableDangerous(ctx, core) {
|
|
|
10169
10190
|
});
|
|
10170
10191
|
}
|
|
10171
10192
|
await ctx.reply(
|
|
10172
|
-
`\u2620\uFE0F <b>Bypass enabled</b>
|
|
10193
|
+
`\u2620\uFE0F <b>Bypass Permissions enabled</b>
|
|
10173
10194
|
|
|
10174
10195
|
All permission requests will be auto-approved \u2014 the agent can run any action without asking.
|
|
10175
10196
|
|
|
@@ -10220,19 +10241,42 @@ async function handleDisableDangerous(ctx, core) {
|
|
|
10220
10241
|
});
|
|
10221
10242
|
}
|
|
10222
10243
|
await ctx.reply(
|
|
10223
|
-
"\u{1F510} <b>Bypass disabled</b>\n\nYou will be asked to approve risky actions.",
|
|
10244
|
+
"\u{1F510} <b>Bypass Permissions disabled</b>\n\nYou will be asked to approve risky actions.",
|
|
10224
10245
|
{ parse_mode: "HTML" }
|
|
10225
10246
|
);
|
|
10226
10247
|
}
|
|
10227
10248
|
function buildSessionControlKeyboard(sessionId, dangerousMode, voiceMode) {
|
|
10228
10249
|
return new InlineKeyboard().text(
|
|
10229
|
-
dangerousMode ? "\u{1F510} Disable Bypass" : "\u2620\uFE0F Enable Bypass",
|
|
10250
|
+
dangerousMode ? "\u{1F510} Disable Bypass Permissions" : "\u2620\uFE0F Enable Bypass Permissions",
|
|
10230
10251
|
`d:${sessionId}`
|
|
10231
10252
|
).row().text(
|
|
10232
10253
|
voiceMode ? "\u{1F50A} Text to Speech" : "\u{1F507} Text to Speech",
|
|
10233
10254
|
`v:${sessionId}`
|
|
10234
10255
|
);
|
|
10235
10256
|
}
|
|
10257
|
+
function buildSessionStatusText(session, heading = "\u2705 New chat (same agent & workspace)") {
|
|
10258
|
+
const lines = [heading];
|
|
10259
|
+
lines.push(`<b>Agent:</b> ${escapeHtml4(session.agentName)}`);
|
|
10260
|
+
lines.push(`<b>Workspace:</b> <code>${escapeHtml4(session.workingDirectory)}</code>`);
|
|
10261
|
+
const modelOpt = session.getConfigByCategory("model");
|
|
10262
|
+
if (modelOpt && modelOpt.type === "select") {
|
|
10263
|
+
const choice = modelOpt.options.flatMap((o) => "group" in o ? o.options : [o]).find((c3) => c3.value === modelOpt.currentValue);
|
|
10264
|
+
lines.push(`<b>Model:</b> ${escapeHtml4(choice?.name ?? modelOpt.currentValue)}`);
|
|
10265
|
+
}
|
|
10266
|
+
const thoughtOpt = session.getConfigByCategory("thought_level");
|
|
10267
|
+
if (thoughtOpt && thoughtOpt.type === "select") {
|
|
10268
|
+
const choice = thoughtOpt.options.flatMap((o) => "group" in o ? o.options : [o]).find((c3) => c3.value === thoughtOpt.currentValue);
|
|
10269
|
+
lines.push(`<b>Thinking:</b> ${escapeHtml4(choice?.name ?? thoughtOpt.currentValue)}`);
|
|
10270
|
+
}
|
|
10271
|
+
const modeOpt = session.getConfigByCategory("mode");
|
|
10272
|
+
if (isBypassActive(session)) {
|
|
10273
|
+
lines.push(`<b>Mode:</b> \u2620\uFE0F Bypass Permissions enabled`);
|
|
10274
|
+
} else if (modeOpt && modeOpt.type === "select") {
|
|
10275
|
+
const choice = modeOpt.options.flatMap((o) => "group" in o ? o.options : [o]).find((c3) => c3.value === modeOpt.currentValue);
|
|
10276
|
+
lines.push(`<b>Mode:</b> ${escapeHtml4(choice?.name ?? modeOpt.currentValue)}`);
|
|
10277
|
+
}
|
|
10278
|
+
return lines.join("\n");
|
|
10279
|
+
}
|
|
10236
10280
|
function setupTTSCallbacks(bot, core) {
|
|
10237
10281
|
bot.callbackQuery(/^v:/, async (ctx) => {
|
|
10238
10282
|
const sessionId = ctx.callbackQuery.data.slice(2);
|
|
@@ -10263,12 +10307,14 @@ function setupTTSCallbacks(bot, core) {
|
|
|
10263
10307
|
} catch {
|
|
10264
10308
|
}
|
|
10265
10309
|
try {
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10310
|
+
const keyboard = buildSessionControlKeyboard(
|
|
10311
|
+
sessionId,
|
|
10312
|
+
isBypassActive(session),
|
|
10313
|
+
newMode === "on"
|
|
10314
|
+
);
|
|
10315
|
+
await ctx.editMessageText(buildSessionStatusText(session), {
|
|
10316
|
+
parse_mode: "HTML",
|
|
10317
|
+
reply_markup: keyboard
|
|
10272
10318
|
});
|
|
10273
10319
|
} catch {
|
|
10274
10320
|
}
|
|
@@ -10476,6 +10522,7 @@ var log14, OUTPUT_MODE_LABELS;
|
|
|
10476
10522
|
var init_admin = __esm({
|
|
10477
10523
|
"src/plugins/telegram/commands/admin.ts"() {
|
|
10478
10524
|
"use strict";
|
|
10525
|
+
init_bypass_detection();
|
|
10479
10526
|
init_formatting();
|
|
10480
10527
|
init_log();
|
|
10481
10528
|
log14 = createChildLogger({ module: "telegram-cmd-admin" });
|
|
@@ -10499,14 +10546,14 @@ function cleanupPending(userId) {
|
|
|
10499
10546
|
function botFromCtx(ctx) {
|
|
10500
10547
|
return { api: ctx.api };
|
|
10501
10548
|
}
|
|
10502
|
-
async function handleNew(ctx, core, chatId, assistant) {
|
|
10549
|
+
async function handleNew(ctx, core, chatId, assistant, onControlMessage) {
|
|
10503
10550
|
const rawMatch = ctx.match;
|
|
10504
10551
|
const matchStr = typeof rawMatch === "string" ? rawMatch : "";
|
|
10505
10552
|
const args2 = matchStr.split(" ").filter(Boolean);
|
|
10506
10553
|
const agentName = args2[0];
|
|
10507
10554
|
const workspace = args2[1];
|
|
10508
10555
|
if (agentName && workspace) {
|
|
10509
|
-
await createSessionDirect(ctx, core, chatId, agentName, workspace);
|
|
10556
|
+
await createSessionDirect(ctx, core, chatId, agentName, workspace, onControlMessage);
|
|
10510
10557
|
return;
|
|
10511
10558
|
}
|
|
10512
10559
|
const currentThreadId = ctx.message?.message_thread_id;
|
|
@@ -10584,7 +10631,7 @@ async function startConfirmStep(ctx, chatId, userId, agentName, workspace) {
|
|
|
10584
10631
|
timer: setTimeout(() => pendingNewSessions.delete(userId), PENDING_TIMEOUT_MS)
|
|
10585
10632
|
});
|
|
10586
10633
|
}
|
|
10587
|
-
async function createSessionDirect(ctx, core, chatId, agentName, workspace) {
|
|
10634
|
+
async function createSessionDirect(ctx, core, chatId, agentName, workspace, onControlMessage) {
|
|
10588
10635
|
log15.info({ userId: ctx.from?.id, agentName, workspace }, "New session command (direct)");
|
|
10589
10636
|
let threadId;
|
|
10590
10637
|
try {
|
|
@@ -10602,19 +10649,19 @@ async function createSessionDirect(ctx, core, chatId, agentName, workspace) {
|
|
|
10602
10649
|
await ctx.api.editForumTopic(chatId, threadId, { name: finalName });
|
|
10603
10650
|
} catch {
|
|
10604
10651
|
}
|
|
10605
|
-
await ctx.api.sendMessage(
|
|
10652
|
+
const controlMsg = await ctx.api.sendMessage(
|
|
10606
10653
|
chatId,
|
|
10607
|
-
`\u2705 <b>Session started</b
|
|
10608
|
-
<b>Agent:</b> ${escapeHtml4(session.agentName)}
|
|
10609
|
-
<b>Workspace:</b> <code>${escapeHtml4(session.workingDirectory)}</code>
|
|
10610
|
-
|
|
10611
|
-
This is your coding session \u2014 chat here to work with the agent.`,
|
|
10654
|
+
buildSessionStatusText(session, `\u2705 <b>Session started</b>`),
|
|
10612
10655
|
{
|
|
10613
10656
|
message_thread_id: threadId,
|
|
10614
10657
|
parse_mode: "HTML",
|
|
10615
10658
|
reply_markup: buildSessionControlKeyboard(session.id, false, false)
|
|
10616
10659
|
}
|
|
10617
10660
|
);
|
|
10661
|
+
onControlMessage?.(session.id, controlMsg.message_id);
|
|
10662
|
+
await core.sessionManager.patchRecord(session.id, {
|
|
10663
|
+
platform: { topicId: threadId }
|
|
10664
|
+
});
|
|
10618
10665
|
return threadId ?? null;
|
|
10619
10666
|
} catch (err) {
|
|
10620
10667
|
log15.error({ err }, "Session creation failed");
|
|
@@ -10629,7 +10676,7 @@ This is your coding session \u2014 chat here to work with the agent.`,
|
|
|
10629
10676
|
return null;
|
|
10630
10677
|
}
|
|
10631
10678
|
}
|
|
10632
|
-
async function handleNewChat(ctx, core, chatId) {
|
|
10679
|
+
async function handleNewChat(ctx, core, chatId, onControlMessage) {
|
|
10633
10680
|
const threadId = ctx.message?.message_thread_id;
|
|
10634
10681
|
if (!threadId) {
|
|
10635
10682
|
await ctx.reply(
|
|
@@ -10684,17 +10731,19 @@ async function handleNewChat(ctx, core, chatId) {
|
|
|
10684
10731
|
await core.sessionManager.patchRecord(session.id, { platform: {
|
|
10685
10732
|
topicId: newThreadId
|
|
10686
10733
|
} });
|
|
10687
|
-
await ctx.api.sendMessage(
|
|
10734
|
+
const controlMsg = await ctx.api.sendMessage(
|
|
10688
10735
|
chatId,
|
|
10689
|
-
`\u2705 New chat (same agent & workspace)
|
|
10690
|
-
<b>Agent:</b> ${escapeHtml4(session.agentName)}
|
|
10691
|
-
<b>Workspace:</b> <code>${escapeHtml4(session.workingDirectory)}</code>`,
|
|
10736
|
+
buildSessionStatusText(session, `\u2705 New chat (same agent & workspace)`),
|
|
10692
10737
|
{
|
|
10693
10738
|
message_thread_id: newThreadId,
|
|
10694
10739
|
parse_mode: "HTML",
|
|
10695
10740
|
reply_markup: buildSessionControlKeyboard(session.id, false, false)
|
|
10696
10741
|
}
|
|
10697
10742
|
);
|
|
10743
|
+
onControlMessage?.(session.id, controlMsg.message_id);
|
|
10744
|
+
await core.sessionManager.patchRecord(session.id, {
|
|
10745
|
+
platform: { topicId: newThreadId }
|
|
10746
|
+
});
|
|
10698
10747
|
} catch (err) {
|
|
10699
10748
|
if (newThreadId) {
|
|
10700
10749
|
try {
|
|
@@ -12184,7 +12233,7 @@ Choose the repo that has Entire checkpoints enabled:`;
|
|
|
12184
12233
|
timer: setTimeout(() => pendingResumes.delete(userId), PENDING_TIMEOUT_MS2)
|
|
12185
12234
|
});
|
|
12186
12235
|
}
|
|
12187
|
-
async function executeResume(ctx, core, chatId, query, repoPath) {
|
|
12236
|
+
async function executeResume(ctx, core, chatId, query, repoPath, onControlMessage) {
|
|
12188
12237
|
const provider = await core.contextManager.getProvider(repoPath);
|
|
12189
12238
|
if (!provider) {
|
|
12190
12239
|
await ctx.reply(
|
|
@@ -12242,22 +12291,23 @@ Repo: <code>${escapeHtml4(repoPath)}</code>`,
|
|
|
12242
12291
|
{ parse_mode: "HTML" }
|
|
12243
12292
|
);
|
|
12244
12293
|
}
|
|
12245
|
-
|
|
12246
|
-
chatId,
|
|
12247
|
-
`\u2705 <b>Session resumed with context</b>
|
|
12248
|
-
<b>Agent:</b> ${escapeHtml4(session.agentName)}
|
|
12249
|
-
<b>Workspace:</b> <code>${escapeHtml4(session.workingDirectory)}</code>
|
|
12294
|
+
const resumeHeading = `\u2705 <b>Session resumed with context</b>
|
|
12250
12295
|
<b>Sessions loaded:</b> ${sessionCount}
|
|
12251
12296
|
<b>Mode:</b> ${escapeHtml4(mode)}
|
|
12252
|
-
<b>~Tokens:</b> ${tokens.toLocaleString()}
|
|
12253
|
-
|
|
12254
|
-
|
|
12297
|
+
<b>~Tokens:</b> ${tokens.toLocaleString()}`;
|
|
12298
|
+
const controlMsg = await ctx.api.sendMessage(
|
|
12299
|
+
chatId,
|
|
12300
|
+
buildSessionStatusText(session, resumeHeading),
|
|
12255
12301
|
{
|
|
12256
12302
|
message_thread_id: threadId,
|
|
12257
12303
|
parse_mode: "HTML",
|
|
12258
12304
|
reply_markup: buildSessionControlKeyboard(session.id, false, false)
|
|
12259
12305
|
}
|
|
12260
12306
|
);
|
|
12307
|
+
onControlMessage?.(session.id, controlMsg.message_id);
|
|
12308
|
+
await core.sessionManager.patchRecord(session.id, {
|
|
12309
|
+
platform: { topicId: threadId }
|
|
12310
|
+
});
|
|
12261
12311
|
} catch (err) {
|
|
12262
12312
|
log17.error({ err }, "Resume session creation failed");
|
|
12263
12313
|
if (threadId) {
|
|
@@ -12270,7 +12320,7 @@ Context is ready \u2014 chat here to continue working with the agent.`,
|
|
|
12270
12320
|
await ctx.reply(`\u274C ${escapeHtml4(message)}`, { parse_mode: "HTML" });
|
|
12271
12321
|
}
|
|
12272
12322
|
}
|
|
12273
|
-
async function handleResume(ctx, core, chatId, assistant) {
|
|
12323
|
+
async function handleResume(ctx, core, chatId, assistant, onControlMessage) {
|
|
12274
12324
|
const rawMatch = ctx.match;
|
|
12275
12325
|
const matchStr = typeof rawMatch === "string" ? rawMatch : "";
|
|
12276
12326
|
const parsed = parseResumeArgs(matchStr);
|
|
@@ -12295,7 +12345,7 @@ Usage examples:
|
|
|
12295
12345
|
if (!userId) return;
|
|
12296
12346
|
await showWorkspacePicker(ctx, core, chatId, userId, query);
|
|
12297
12347
|
}
|
|
12298
|
-
async function handlePendingResumeInput(ctx, core, chatId, assistantTopicId) {
|
|
12348
|
+
async function handlePendingResumeInput(ctx, core, chatId, assistantTopicId, onControlMessage) {
|
|
12299
12349
|
const userId = ctx.from?.id;
|
|
12300
12350
|
if (!userId) return false;
|
|
12301
12351
|
const pending = pendingResumes.get(userId);
|
|
@@ -12315,10 +12365,10 @@ async function handlePendingResumeInput(ctx, core, chatId, assistantTopicId) {
|
|
|
12315
12365
|
}
|
|
12316
12366
|
const resolved = core.configManager.resolveWorkspace(workspace);
|
|
12317
12367
|
cleanupPending2(userId);
|
|
12318
|
-
await executeResume(ctx, core, chatId, pending.query, resolved);
|
|
12368
|
+
await executeResume(ctx, core, chatId, pending.query, resolved, onControlMessage);
|
|
12319
12369
|
return true;
|
|
12320
12370
|
}
|
|
12321
|
-
function setupResumeCallbacks(bot, core, chatId) {
|
|
12371
|
+
function setupResumeCallbacks(bot, core, chatId, onControlMessage) {
|
|
12322
12372
|
bot.callbackQuery(/^m:resume:/, async (ctx) => {
|
|
12323
12373
|
const data = ctx.callbackQuery.data;
|
|
12324
12374
|
const userId = ctx.from?.id;
|
|
@@ -12337,7 +12387,7 @@ function setupResumeCallbacks(bot, core, chatId) {
|
|
|
12337
12387
|
await ctx.api.editMessageText(chatId, pending.messageId, `\u23F3 Using <code>${escapeHtml4(resolved)}</code>...`, { parse_mode: "HTML" });
|
|
12338
12388
|
} catch {
|
|
12339
12389
|
}
|
|
12340
|
-
await executeResume(ctx, core, chatId, pending.query, resolved);
|
|
12390
|
+
await executeResume(ctx, core, chatId, pending.query, resolved, onControlMessage);
|
|
12341
12391
|
return;
|
|
12342
12392
|
}
|
|
12343
12393
|
if (data === "m:resume:ws:custom") {
|
|
@@ -12368,7 +12418,7 @@ Or just the folder name (will use workspace baseDir)`,
|
|
|
12368
12418
|
await ctx.api.editMessageText(chatId, pending.messageId, `\u23F3 Using <code>${escapeHtml4(resolved)}</code>...`, { parse_mode: "HTML" });
|
|
12369
12419
|
} catch {
|
|
12370
12420
|
}
|
|
12371
|
-
await executeResume(ctx, core, chatId, pending.query, resolved);
|
|
12421
|
+
await executeResume(ctx, core, chatId, pending.query, resolved, onControlMessage);
|
|
12372
12422
|
return;
|
|
12373
12423
|
}
|
|
12374
12424
|
});
|
|
@@ -13719,8 +13769,9 @@ var init_switch = __esm({
|
|
|
13719
13769
|
|
|
13720
13770
|
// src/plugins/telegram/commands/index.ts
|
|
13721
13771
|
function setupCommands(bot, core, chatId, assistant) {
|
|
13722
|
-
|
|
13723
|
-
bot.command("
|
|
13772
|
+
const onControlMessage = assistant?.setControlMessage;
|
|
13773
|
+
bot.command("new", (ctx) => handleNew(ctx, core, chatId, assistant, onControlMessage));
|
|
13774
|
+
bot.command("newchat", (ctx) => handleNewChat(ctx, core, chatId, onControlMessage));
|
|
13724
13775
|
bot.command("cancel", (ctx) => handleCancel(ctx, core, assistant));
|
|
13725
13776
|
bot.command("status", (ctx) => handleStatus(ctx, core));
|
|
13726
13777
|
bot.command("sessions", (ctx) => handleTopics(ctx, core));
|
|
@@ -13741,12 +13792,12 @@ function setupCommands(bot, core, chatId, assistant) {
|
|
|
13741
13792
|
bot.command("text_to_speech", (ctx) => handleTTS(ctx, core));
|
|
13742
13793
|
bot.command("verbosity", (ctx) => handleVerbosity(ctx, core));
|
|
13743
13794
|
bot.command("outputmode", (ctx) => handleOutputMode(ctx, core));
|
|
13744
|
-
bot.command("resume", (ctx) => handleResume(ctx, core, chatId, assistant));
|
|
13795
|
+
bot.command("resume", (ctx) => handleResume(ctx, core, chatId, assistant, onControlMessage));
|
|
13745
13796
|
bot.command("switch", (ctx) => handleSwitch(ctx, core));
|
|
13746
13797
|
}
|
|
13747
|
-
function setupAllCallbacks(bot, core, chatId, systemTopicIds, getAssistantSession) {
|
|
13798
|
+
function setupAllCallbacks(bot, core, chatId, systemTopicIds, getAssistantSession, onControlMessage) {
|
|
13748
13799
|
setupNewSessionCallbacks(bot, core, chatId);
|
|
13749
|
-
setupResumeCallbacks(bot, core, chatId);
|
|
13800
|
+
setupResumeCallbacks(bot, core, chatId, onControlMessage);
|
|
13750
13801
|
setupSessionCallbacks(bot, core, chatId, systemTopicIds);
|
|
13751
13802
|
setupSettingsCallbacks(bot, core, getAssistantSession ?? (() => void 0));
|
|
13752
13803
|
setupDoctorCallbacks(bot);
|
|
@@ -16344,6 +16395,7 @@ var init_adapter2 = __esm({
|
|
|
16344
16395
|
init_log();
|
|
16345
16396
|
init_topics2();
|
|
16346
16397
|
init_commands3();
|
|
16398
|
+
init_admin();
|
|
16347
16399
|
init_permissions();
|
|
16348
16400
|
init_assistant();
|
|
16349
16401
|
init_formatting();
|
|
@@ -16388,6 +16440,29 @@ var init_adapter2 = __esm({
|
|
|
16388
16440
|
callbackCounter = 0;
|
|
16389
16441
|
/** Pending skill commands queued when session.threadId was not yet set */
|
|
16390
16442
|
_pendingSkillCommands = /* @__PURE__ */ new Map();
|
|
16443
|
+
/** Control message IDs per session (for updating status text/buttons) */
|
|
16444
|
+
controlMsgIds = /* @__PURE__ */ new Map();
|
|
16445
|
+
/** Store control message ID in memory + persist to session record */
|
|
16446
|
+
storeControlMsgId(sessionId, msgId) {
|
|
16447
|
+
this.storeControlMsgId(sessionId, msgId);
|
|
16448
|
+
this.core.sessionManager.patchRecord(sessionId, {
|
|
16449
|
+
platform: { controlMsgId: msgId }
|
|
16450
|
+
}).catch(() => {
|
|
16451
|
+
});
|
|
16452
|
+
}
|
|
16453
|
+
/** Get control message ID (from Map, with fallback to session record) */
|
|
16454
|
+
getControlMsgId(sessionId) {
|
|
16455
|
+
let msgId = this.controlMsgIds.get(sessionId);
|
|
16456
|
+
if (!msgId) {
|
|
16457
|
+
const record = this.core.sessionManager.getSessionRecord(sessionId);
|
|
16458
|
+
const platform2 = record?.platform;
|
|
16459
|
+
if (platform2?.controlMsgId) {
|
|
16460
|
+
msgId = platform2.controlMsgId;
|
|
16461
|
+
this.storeControlMsgId(sessionId, msgId);
|
|
16462
|
+
}
|
|
16463
|
+
}
|
|
16464
|
+
return msgId;
|
|
16465
|
+
}
|
|
16391
16466
|
getThreadId(sessionId) {
|
|
16392
16467
|
const threadId = this._sessionThreadIds.get(sessionId);
|
|
16393
16468
|
if (threadId === void 0) {
|
|
@@ -16594,7 +16669,26 @@ var init_adapter2 = __esm({
|
|
|
16594
16669
|
});
|
|
16595
16670
|
await ctx.answerCallbackQuery();
|
|
16596
16671
|
if (response.type !== "silent") {
|
|
16597
|
-
|
|
16672
|
+
if (response.type === "menu") {
|
|
16673
|
+
const keyboard = response.options.map((opt) => [
|
|
16674
|
+
{
|
|
16675
|
+
text: `${opt.label}${opt.hint ? ` \u2014 ${opt.hint}` : ""}`,
|
|
16676
|
+
callback_data: this.toCallbackData(opt.command)
|
|
16677
|
+
}
|
|
16678
|
+
]);
|
|
16679
|
+
try {
|
|
16680
|
+
await ctx.editMessageText(response.title, {
|
|
16681
|
+
reply_markup: { inline_keyboard: keyboard }
|
|
16682
|
+
});
|
|
16683
|
+
} catch {
|
|
16684
|
+
}
|
|
16685
|
+
} else if (response.type === "text" || response.type === "error") {
|
|
16686
|
+
const text6 = response.type === "text" ? response.text : `\u274C ${response.message}`;
|
|
16687
|
+
try {
|
|
16688
|
+
await ctx.editMessageText(text6, { parse_mode: "Markdown" });
|
|
16689
|
+
} catch {
|
|
16690
|
+
}
|
|
16691
|
+
}
|
|
16598
16692
|
}
|
|
16599
16693
|
} catch {
|
|
16600
16694
|
await ctx.answerCallbackQuery({ text: "Command failed" });
|
|
@@ -16624,6 +16718,9 @@ var init_adapter2 = __esm({
|
|
|
16624
16718
|
topicId: this.assistantTopicId,
|
|
16625
16719
|
enqueuePrompt: (p2) => this.assistantSession.enqueuePrompt(p2)
|
|
16626
16720
|
};
|
|
16721
|
+
},
|
|
16722
|
+
(sessionId, msgId) => {
|
|
16723
|
+
this.storeControlMsgId(sessionId, msgId);
|
|
16627
16724
|
}
|
|
16628
16725
|
);
|
|
16629
16726
|
setupCommands(
|
|
@@ -16633,6 +16730,9 @@ var init_adapter2 = __esm({
|
|
|
16633
16730
|
{
|
|
16634
16731
|
topicId: this.assistantTopicId,
|
|
16635
16732
|
getSession: () => this.assistantSession,
|
|
16733
|
+
setControlMessage: (sessionId, msgId) => {
|
|
16734
|
+
this.storeControlMsgId(sessionId, msgId);
|
|
16735
|
+
},
|
|
16636
16736
|
respawn: async () => {
|
|
16637
16737
|
if (this.assistantSession) {
|
|
16638
16738
|
await this.assistantSession.destroy();
|
|
@@ -16696,6 +16796,10 @@ var init_adapter2 = __esm({
|
|
|
16696
16796
|
}
|
|
16697
16797
|
);
|
|
16698
16798
|
});
|
|
16799
|
+
this.core.eventBus.on("session:configChanged", ({ sessionId }) => {
|
|
16800
|
+
this.updateControlMessage(sessionId).catch(() => {
|
|
16801
|
+
});
|
|
16802
|
+
});
|
|
16699
16803
|
this.setupRoutes();
|
|
16700
16804
|
this.bot.start({
|
|
16701
16805
|
allowed_updates: ["message", "callback_query"],
|
|
@@ -16900,7 +17004,10 @@ ${lines.join("\n")}`;
|
|
|
16900
17004
|
ctx,
|
|
16901
17005
|
this.core,
|
|
16902
17006
|
this.telegramConfig.chatId,
|
|
16903
|
-
this.assistantTopicId
|
|
17007
|
+
this.assistantTopicId,
|
|
17008
|
+
(sessionId2, msgId) => {
|
|
17009
|
+
this.storeControlMsgId(sessionId2, msgId);
|
|
17010
|
+
}
|
|
16904
17011
|
)) {
|
|
16905
17012
|
return;
|
|
16906
17013
|
}
|
|
@@ -17279,6 +17386,41 @@ Task completed.
|
|
|
17279
17386
|
);
|
|
17280
17387
|
}
|
|
17281
17388
|
}
|
|
17389
|
+
async handleConfigUpdate(sessionId, _content) {
|
|
17390
|
+
await this.updateControlMessage(sessionId);
|
|
17391
|
+
}
|
|
17392
|
+
/**
|
|
17393
|
+
* Edit the pinned control message to reflect current session state
|
|
17394
|
+
* (model, thought level, mode, bypass status).
|
|
17395
|
+
*/
|
|
17396
|
+
async updateControlMessage(sessionId) {
|
|
17397
|
+
const session = this.core.sessionManager.getSession(sessionId);
|
|
17398
|
+
if (!session) return;
|
|
17399
|
+
const controlMsgId = this.getControlMsgId(sessionId);
|
|
17400
|
+
if (!controlMsgId) return;
|
|
17401
|
+
const threadId = Number(session.threadId);
|
|
17402
|
+
if (!threadId || isNaN(threadId)) return;
|
|
17403
|
+
const text6 = buildSessionStatusText(session);
|
|
17404
|
+
const keyboard = buildSessionControlKeyboard(
|
|
17405
|
+
sessionId,
|
|
17406
|
+
isBypassActive(session),
|
|
17407
|
+
session.voiceMode === "on"
|
|
17408
|
+
);
|
|
17409
|
+
try {
|
|
17410
|
+
await this.bot.api.editMessageText(
|
|
17411
|
+
this.telegramConfig.chatId,
|
|
17412
|
+
controlMsgId,
|
|
17413
|
+
text6,
|
|
17414
|
+
{ parse_mode: "HTML" }
|
|
17415
|
+
);
|
|
17416
|
+
await this.bot.api.editMessageReplyMarkup(
|
|
17417
|
+
this.telegramConfig.chatId,
|
|
17418
|
+
controlMsgId,
|
|
17419
|
+
{ reply_markup: keyboard }
|
|
17420
|
+
);
|
|
17421
|
+
} catch {
|
|
17422
|
+
}
|
|
17423
|
+
}
|
|
17282
17424
|
async handleError(sessionId, content) {
|
|
17283
17425
|
this.getTracer(sessionId)?.log("telegram", { action: "handle:error", sessionId, text: content.text });
|
|
17284
17426
|
const threadId = this.getThreadId(sessionId);
|
|
@@ -20016,19 +20158,6 @@ var init_session_manager = __esm({
|
|
|
20016
20158
|
}
|
|
20017
20159
|
});
|
|
20018
20160
|
|
|
20019
|
-
// src/core/utils/bypass-detection.ts
|
|
20020
|
-
function isPermissionBypass(value) {
|
|
20021
|
-
const lower = value.toLowerCase();
|
|
20022
|
-
return BYPASS_KEYWORDS.some((kw) => lower.includes(kw));
|
|
20023
|
-
}
|
|
20024
|
-
var BYPASS_KEYWORDS;
|
|
20025
|
-
var init_bypass_detection = __esm({
|
|
20026
|
-
"src/core/utils/bypass-detection.ts"() {
|
|
20027
|
-
"use strict";
|
|
20028
|
-
BYPASS_KEYWORDS = ["bypass", "dangerous", "skip", "dontask", "dont_ask", "auto_accept"];
|
|
20029
|
-
}
|
|
20030
|
-
});
|
|
20031
|
-
|
|
20032
20161
|
// src/core/sessions/session-bridge.ts
|
|
20033
20162
|
var log29, SessionBridge;
|
|
20034
20163
|
var init_session_bridge = __esm({
|
|
@@ -23773,6 +23902,7 @@ function registerCategoryCommand(registry, core, category, commandName) {
|
|
|
23773
23902
|
if (response.configOptions) {
|
|
23774
23903
|
session.configOptions = response.configOptions;
|
|
23775
23904
|
}
|
|
23905
|
+
core.eventBus.emit("session:configChanged", { sessionId: session.id });
|
|
23776
23906
|
return { type: "text", text: labels.successMsg(match.name, configOption.name) };
|
|
23777
23907
|
} catch (err) {
|
|
23778
23908
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -23839,9 +23969,10 @@ function registerDangerousCommand(registry, core) {
|
|
|
23839
23969
|
if (response.configOptions) {
|
|
23840
23970
|
session.configOptions = response.configOptions;
|
|
23841
23971
|
}
|
|
23972
|
+
core.eventBus.emit("session:configChanged", { sessionId: session.id });
|
|
23842
23973
|
return {
|
|
23843
23974
|
type: "text",
|
|
23844
|
-
text: wantOn ? "\u2620\uFE0F **Bypass enabled** \u2014 all permission requests will be auto-approved. The agent can run any action without asking." : "\u{1F510} **Bypass disabled** \u2014 you will be asked to approve risky actions."
|
|
23975
|
+
text: wantOn ? "\u2620\uFE0F **Bypass Permissions enabled** \u2014 all permission requests will be auto-approved. The agent can run any action without asking." : "\u{1F510} **Bypass Permissions disabled** \u2014 you will be asked to approve risky actions."
|
|
23845
23976
|
};
|
|
23846
23977
|
} catch (err) {
|
|
23847
23978
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -23852,9 +23983,10 @@ function registerDangerousCommand(registry, core) {
|
|
|
23852
23983
|
await core.sessionManager.patchRecord(session.id, {
|
|
23853
23984
|
clientOverrides: { ...session.clientOverrides }
|
|
23854
23985
|
});
|
|
23986
|
+
core.eventBus.emit("session:configChanged", { sessionId: session.id });
|
|
23855
23987
|
return {
|
|
23856
23988
|
type: "text",
|
|
23857
|
-
text: wantOn ? "\u2620\uFE0F **Bypass enabled** (client-side) \u2014 all permission requests will be auto-approved.\n\n_Note: This agent doesn't natively support bypass mode, so OpenACP will auto-approve on your behalf._" : "\u{1F510} **Bypass disabled** \u2014 you will be asked to approve risky actions."
|
|
23989
|
+
text: wantOn ? "\u2620\uFE0F **Bypass Permissions enabled** (client-side) \u2014 all permission requests will be auto-approved.\n\n_Note: This agent doesn't natively support bypass mode, so OpenACP will auto-approve on your behalf._" : "\u{1F510} **Bypass Permissions disabled** \u2014 you will be asked to approve risky actions."
|
|
23858
23990
|
};
|
|
23859
23991
|
}
|
|
23860
23992
|
});
|
|
@@ -25735,6 +25867,12 @@ async function startServer(opts) {
|
|
|
25735
25867
|
removePidFile2(ctx.paths.pid);
|
|
25736
25868
|
}
|
|
25737
25869
|
if (exitCode === RESTART_EXIT_CODE) {
|
|
25870
|
+
if (process.env.OPENACP_DEV_LOOP) {
|
|
25871
|
+
const fsMod = await import("fs");
|
|
25872
|
+
const osMod = await import("os");
|
|
25873
|
+
const pathMod2 = await import("path");
|
|
25874
|
+
fsMod.writeFileSync(pathMod2.join(osMod.tmpdir(), "openacp-dev-loop-root"), ctx.root, "utf-8");
|
|
25875
|
+
}
|
|
25738
25876
|
if (isDaemon) {
|
|
25739
25877
|
const { spawn: spawnChild } = await import("child_process");
|
|
25740
25878
|
const { expandHome: expandHome4 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
@@ -25749,7 +25887,7 @@ async function startServer(opts) {
|
|
|
25749
25887
|
const child = spawnChild(process.execPath, [cliPath, "--daemon-child"], {
|
|
25750
25888
|
detached: true,
|
|
25751
25889
|
stdio: ["ignore", out, err],
|
|
25752
|
-
env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: "1" }
|
|
25890
|
+
env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: "1", OPENACP_INSTANCE_ROOT: ctx.root }
|
|
25753
25891
|
});
|
|
25754
25892
|
fs53.closeSync(out);
|
|
25755
25893
|
fs53.closeSync(err);
|
|
@@ -25759,7 +25897,7 @@ async function startServer(opts) {
|
|
|
25759
25897
|
const { spawn: spawnChild } = await import("child_process");
|
|
25760
25898
|
const child = spawnChild(process.execPath, process.argv.slice(1), {
|
|
25761
25899
|
stdio: "inherit",
|
|
25762
|
-
env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: "1" }
|
|
25900
|
+
env: { ...process.env, OPENACP_SKIP_UPDATE_CHECK: "1", OPENACP_INSTANCE_ROOT: ctx.root }
|
|
25763
25901
|
});
|
|
25764
25902
|
await shutdownLogger();
|
|
25765
25903
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
@@ -29401,7 +29539,7 @@ async function cmdDev(args2 = []) {
|
|
|
29401
29539
|
`);
|
|
29402
29540
|
return;
|
|
29403
29541
|
}
|
|
29404
|
-
const pluginPathArg = args2.
|
|
29542
|
+
const pluginPathArg = args2.find((a) => !a.startsWith("--"));
|
|
29405
29543
|
const noWatch = args2.includes("--no-watch");
|
|
29406
29544
|
const verbose = args2.includes("--verbose");
|
|
29407
29545
|
if (!pluginPathArg) {
|