@coinseeker/opencode-telegram-plugin 1.0.8 → 1.0.9

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 CHANGED
@@ -15,11 +15,11 @@ Configure the npm package in `~/.config/opencode/opencode.json`:
15
15
 
16
16
  ```json
17
17
  {
18
- "plugin": ["@coinseeker/opencode-telegram-plugin@1.0.8"]
18
+ "plugin": ["@coinseeker/opencode-telegram-plugin@1.0.9"]
19
19
  }
20
20
  ```
21
21
 
22
- Current stable version: `@coinseeker/opencode-telegram-plugin@1.0.8`.
22
+ Current stable version: `@coinseeker/opencode-telegram-plugin@1.0.9`.
23
23
 
24
24
  Restart OpenCode after editing the config. OpenCode resolves npm package plugins on startup.
25
25
 
@@ -45,7 +45,6 @@ function createTelegramBot(opts) {
45
45
  let activeChatId = opts.initialChatId;
46
46
  let questionDispatcher;
47
47
  let permissionDispatcher;
48
- let startWorkDispatcher;
49
48
  if (polling) {
50
49
  bot.use(async (ctx, next) => {
51
50
  const userId = ctx.from?.id;
@@ -98,13 +97,6 @@ This chat is now active for OpenCode notifications.`
98
97
  if (!permissionDispatcher || messageId === void 0) return;
99
98
  await permissionDispatcher.handleCallbackQuery(data, messageId);
100
99
  });
101
- bot.callbackQuery(/^sw:(.+)$/, async (ctx) => {
102
- await ctx.answerCallbackQuery();
103
- const data = ctx.callbackQuery.data;
104
- const messageId = ctx.callbackQuery.message?.message_id;
105
- if (!startWorkDispatcher || messageId === void 0) return;
106
- await startWorkDispatcher.handleCallbackQuery(data, messageId);
107
- });
108
100
  bot.on("message:text", async (ctx) => {
109
101
  const replyToMessageId = ctx.message.reply_to_message?.message_id;
110
102
  const chatId = ctx.chat.id;
@@ -198,9 +190,6 @@ This chat is now active for OpenCode notifications.`
198
190
  },
199
191
  setPermissionDispatcher(dispatcher) {
200
192
  permissionDispatcher = dispatcher;
201
- },
202
- setStartWorkDispatcher(dispatcher) {
203
- startWorkDispatcher = dispatcher;
204
193
  }
205
194
  };
206
195
  }
@@ -953,84 +942,6 @@ async function handleSessionError(event, ctx) {
953
942
  ctx.logger.info("session abort recorded", { sessionId: event.properties.sessionID ?? "global" });
954
943
  }
955
944
 
956
- // src/events/start-work.ts
957
- var CALLBACK_RE3 = /^sw:(.+)$/;
958
- var START_WORK_COMMAND = "start-work";
959
- var START_WORK_RE = /(?:^|[\s`])\/start-work(?:\s+([^\n`]+))?/g;
960
- var StartWorkCommandStore = class {
961
- commands = /* @__PURE__ */ new Map();
962
- updateFromText(sessionID, text) {
963
- const command = extractStartWorkCommand(sessionID, text);
964
- if (!command) return void 0;
965
- this.commands.set(sessionID, command.arguments);
966
- return command;
967
- }
968
- get(sessionID) {
969
- const args = this.commands.get(sessionID);
970
- if (args === void 0) return void 0;
971
- return { sessionID, arguments: args };
972
- }
973
- delete(sessionID) {
974
- this.commands.delete(sessionID);
975
- }
976
- };
977
- function extractStartWorkCommand(sessionID, text) {
978
- let latestArgs;
979
- for (const match of text.matchAll(START_WORK_RE)) {
980
- const args = (match[1] ?? "").trim();
981
- if (args) latestArgs = args;
982
- }
983
- if (latestArgs === void 0) return void 0;
984
- return { sessionID, arguments: latestArgs };
985
- }
986
- function startWorkCallbackData(sessionID) {
987
- const data = `sw:${encodeURIComponent(sessionID)}`;
988
- return Buffer.byteLength(data, "utf8") <= 64 ? data : void 0;
989
- }
990
- function startWorkKeyboard(sessionID) {
991
- const callbackData = startWorkCallbackData(sessionID);
992
- if (!callbackData) return void 0;
993
- return [[{ text: "\u25B6\uFE0F Run /start-work", callback_data: callbackData }]];
994
- }
995
- function createStartWorkDispatcher(ctx) {
996
- return {
997
- async handleCallbackQuery(data, messageId) {
998
- const match = CALLBACK_RE3.exec(data);
999
- if (!match) return;
1000
- const sessionID = decodeURIComponent(match[1]);
1001
- const command = ctx.startWorkCommands.get(sessionID);
1002
- if (!command) {
1003
- await ctx.bot.editMessageRemoveKeyboard(
1004
- messageId,
1005
- `\u26A0\uFE0F No /start-work command was detected for this session.
1006
-
1007
- Session: ${sessionID}`
1008
- );
1009
- return;
1010
- }
1011
- try {
1012
- await ctx.runSessionCommand(sessionID, START_WORK_COMMAND, command.arguments);
1013
- await ctx.bot.editMessageRemoveKeyboard(
1014
- messageId,
1015
- `\u25B6\uFE0F Sent /start-work ${command.arguments} to opencode.
1016
-
1017
- Session: ${sessionID}`
1018
- );
1019
- ctx.startWorkCommands.delete(sessionID);
1020
- ctx.logger.info("start-work command sent", { sessionID });
1021
- } catch (err) {
1022
- await ctx.bot.editMessageRemoveKeyboard(
1023
- messageId,
1024
- `\u26A0\uFE0F Failed to send /start-work to opencode.
1025
-
1026
- Session: ${sessionID}`
1027
- );
1028
- ctx.logger.error("failed to send start-work command", { sessionID, error: String(err) });
1029
- }
1030
- }
1031
- };
1032
- }
1033
-
1034
945
  // src/events/session-idle.ts
1035
946
  var ROOT_IDLE_RECHECK_DELAY_MS = 2500;
1036
947
  function sleep(ms) {
@@ -1077,17 +988,9 @@ async function sendIdleNotification(sessionId, ctx) {
1077
988
  });
1078
989
  if (!claimed) return;
1079
990
  const title = ctx.sessionTitleService.getSessionTitle(sessionId);
1080
- const startWorkCommand = ctx.startWorkCommands.get(sessionId);
1081
- const message = title ? `Agent has finished: ${title}` : "Agent has finished.";
1082
- const keyboard = startWorkCommand ? startWorkKeyboard(sessionId) : void 0;
1083
- const text = startWorkCommand ? `${message}
1084
-
1085
- Plan is ready. Tap below to run /start-work ${startWorkCommand.arguments}.` : message;
991
+ const text = title ? `Agent has finished: ${title}` : "Agent has finished.";
1086
992
  try {
1087
- await ctx.bot.sendMessage(
1088
- text,
1089
- keyboard ? { reply_markup: { inline_keyboard: keyboard } } : void 0
1090
- );
993
+ await ctx.bot.sendMessage(text);
1091
994
  ctx.sessionTitleService.clearDeferredIdleNotification(sessionId);
1092
995
  ctx.logger.info("idle notification sent", { sessionId, title });
1093
996
  } catch (err) {
@@ -1467,16 +1370,6 @@ var SessionTitleService = class {
1467
1370
 
1468
1371
  // src/telegram-remote.ts
1469
1372
  var pluginDir = dirname4(fileURLToPath(import.meta.url));
1470
- function getTextPartFromMessagePartUpdated(event) {
1471
- if (event.type !== "message.part.updated") return void 0;
1472
- const part = event.properties?.part;
1473
- if (!part || typeof part !== "object") return void 0;
1474
- const candidate = part;
1475
- if (candidate.type !== "text" || typeof candidate.sessionID !== "string" || typeof candidate.text !== "string") {
1476
- return void 0;
1477
- }
1478
- return { type: "text", sessionID: candidate.sessionID, text: candidate.text };
1479
- }
1480
1373
  var TelegramRemote = async (input) => {
1481
1374
  const logger = createLogger({ namespace: "telegram" });
1482
1375
  try {
@@ -1490,7 +1383,6 @@ var TelegramRemote = async (input) => {
1490
1383
  const claimsDir = join6(tmpdir4(), `opencoder-telegram-claims-${tokenHash}`);
1491
1384
  const pendingQuestions = createPendingQuestionStore({ tokenHash });
1492
1385
  const pendingPermissions = createPendingPermissionStore({ tokenHash });
1493
- const startWorkCommands = new StartWorkCommandStore();
1494
1386
  const lockResult = await acquireLock({ lockPath });
1495
1387
  const isLeader = lockResult.acquired;
1496
1388
  logger.info(
@@ -1529,13 +1421,6 @@ var TelegramRemote = async (input) => {
1529
1421
  throwOnError: true
1530
1422
  });
1531
1423
  };
1532
- const runSessionCommand = async (sessionID, command, args) => {
1533
- await input.client.session.command({
1534
- path: { id: sessionID },
1535
- body: { command, arguments: args },
1536
- throwOnError: true
1537
- });
1538
- };
1539
1424
  const bot = createTelegramBot({
1540
1425
  config,
1541
1426
  stateStore,
@@ -1580,15 +1465,12 @@ var TelegramRemote = async (input) => {
1580
1465
  tokenHash,
1581
1466
  pendingQuestions,
1582
1467
  pendingPermissions,
1583
- startWorkCommands,
1584
1468
  replyToQuestion,
1585
- replyToPermission,
1586
- runSessionCommand
1469
+ replyToPermission
1587
1470
  };
1588
1471
  if (isLeader) {
1589
1472
  bot.setQuestionDispatcher(createQuestionDispatcher(ctx));
1590
1473
  bot.setPermissionDispatcher(createPermissionDispatcher(ctx));
1591
- bot.setStartWorkDispatcher(createStartWorkDispatcher(ctx));
1592
1474
  }
1593
1475
  return {
1594
1476
  event: async ({ event }) => {
@@ -1606,17 +1488,6 @@ var TelegramRemote = async (input) => {
1606
1488
  case "permission.updated":
1607
1489
  return handlePermissionUpdated(event, ctx);
1608
1490
  default: {
1609
- const textPart = getTextPartFromMessagePartUpdated(extEvent);
1610
- if (textPart) {
1611
- const command = startWorkCommands.updateFromText(textPart.sessionID, textPart.text);
1612
- if (command) {
1613
- logger.info("start-work command detected", {
1614
- sessionID: command.sessionID,
1615
- arguments: command.arguments
1616
- });
1617
- }
1618
- return;
1619
- }
1620
1491
  if (isEventPermissionAsked(extEvent)) {
1621
1492
  if (!isLeader) return;
1622
1493
  return handlePermissionAsked(extEvent, ctx);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinseeker/opencode-telegram-plugin",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Control and monitor OpenCode from Telegram with notifications, question replies, and subagent-aware completion.",
5
5
  "type": "module",
6
6
  "main": "dist/telegram-remote.js",