@coinseeker/opencode-telegram-plugin 1.0.9 → 1.0.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/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.9"]
18
+ "plugin": ["@coinseeker/opencode-telegram-plugin@1.0.10"]
19
19
  }
20
20
  ```
21
21
 
22
- Current stable version: `@coinseeker/opencode-telegram-plugin@1.0.9`.
22
+ Current stable version: `@coinseeker/opencode-telegram-plugin@1.0.10`.
23
23
 
24
24
  Restart OpenCode after editing the config. OpenCode resolves npm package plugins on startup.
25
25
 
@@ -471,6 +471,7 @@ async function handleNormalizedPermission(permission, ctx) {
471
471
  const pending = {
472
472
  requestID: permission.requestID,
473
473
  sessionID: permission.sessionID,
474
+ serverUrl: ctx.serverUrl.href,
474
475
  title: permission.title,
475
476
  permission: permission.permission,
476
477
  patterns: permission.patterns,
@@ -514,7 +515,13 @@ function createPermissionDispatcher(ctx) {
514
515
  return;
515
516
  }
516
517
  try {
517
- await ctx.replyToPermission(pending.requestID, pending.sessionID, reply, pending.endpoint);
518
+ await ctx.replyToPermission(
519
+ pending.requestID,
520
+ pending.sessionID,
521
+ reply,
522
+ pending.endpoint,
523
+ pending.serverUrl
524
+ );
518
525
  await ctx.bot.editMessageRemoveKeyboard(messageId, `\u2705 Permission ${replyLabel(reply)}
519
526
 
520
527
  ${pending.permission}: ${pending.title}`);
@@ -719,7 +726,7 @@ async function completeIfReady(ctx, pending, shortHash) {
719
726
  const answers = pending.answersInProgress.map((answer) => answer ?? []);
720
727
  const messageId = pending.telegramMessageIds[0];
721
728
  try {
722
- await ctx.replyToQuestion(pending.requestID, answers);
729
+ await ctx.replyToQuestion(pending.requestID, answers, pending.serverUrl);
723
730
  await ctx.bot.editMessageRemoveKeyboard(
724
731
  messageId,
725
732
  `\u2705 Answered:
@@ -759,6 +766,7 @@ async function handleQuestionAsked(event, ctx) {
759
766
  const pending = {
760
767
  requestID: request.id,
761
768
  sessionID: request.sessionID,
769
+ serverUrl: ctx.serverUrl.href,
762
770
  questions: request.questions,
763
771
  sentAt,
764
772
  expiresAt: sentAt + QUESTION_EXPIRY_MS,
@@ -1000,15 +1008,19 @@ async function sendIdleNotification(sessionId, ctx) {
1000
1008
  async function flushDeferredParentIfReady(parentID, ctx) {
1001
1009
  if (!ctx.sessionTitleService.hasDeferredIdleNotification(parentID)) return;
1002
1010
  if (ctx.sessionTitleService.hasUnfinishedDescendants(parentID)) return;
1003
- if (ctx.sessionTitleService.getSessionStatus(parentID) !== "idle") {
1011
+ const parentStatus = ctx.sessionTitleService.getSessionStatus(parentID);
1012
+ if (parentStatus === "idle") {
1013
+ ctx.logger.info("keeping deferred parent idle notification - waiting for parent to resume", {
1014
+ sessionId: parentID
1015
+ });
1016
+ return;
1017
+ }
1018
+ if (parentStatus !== void 0) {
1004
1019
  ctx.sessionTitleService.clearDeferredIdleNotification(parentID);
1005
1020
  ctx.logger.info("clearing deferred parent idle notification - parent resumed", {
1006
1021
  sessionId: parentID
1007
1022
  });
1008
- return;
1009
1023
  }
1010
- ctx.logger.info("sending deferred parent idle notification", { sessionId: parentID });
1011
- await sendIdleNotification(parentID, ctx);
1012
1024
  }
1013
1025
  async function deferParentIdleIfDescendantsRunning(sessionId, ctx) {
1014
1026
  await hydrateDescendants(sessionId, ctx);
@@ -1021,8 +1033,8 @@ async function deferParentIdleIfDescendantsRunning(sessionId, ctx) {
1021
1033
  }
1022
1034
  async function handleSessionIdle(event, ctx) {
1023
1035
  const sessionId = event.properties.sessionID;
1024
- ctx.sessionTitleService.setSessionStatus(sessionId, "idle");
1025
1036
  const parentID = await resolveParentID(sessionId, ctx);
1037
+ ctx.sessionTitleService.setSessionStatus(sessionId, "idle");
1026
1038
  if (typeof parentID === "string") {
1027
1039
  ctx.logger.info("suppressing child session idle notification", { sessionId, parentID });
1028
1040
  await flushDeferredParentIfReady(parentID, ctx);
@@ -1315,7 +1327,7 @@ var SessionTitleService = class {
1315
1327
  const existing = this.sessions.get(sessionId);
1316
1328
  this.sessions.set(sessionId, {
1317
1329
  title,
1318
- parentID: existing?.parentID ?? null,
1330
+ parentID: existing?.parentID,
1319
1331
  status: existing?.status,
1320
1332
  idleNotificationPending: existing?.idleNotificationPending ?? false
1321
1333
  });
@@ -1324,7 +1336,7 @@ var SessionTitleService = class {
1324
1336
  const existing = this.sessions.get(sessionId);
1325
1337
  this.sessions.set(sessionId, {
1326
1338
  title: existing?.title ?? null,
1327
- parentID: existing?.parentID ?? null,
1339
+ parentID: existing?.parentID,
1328
1340
  status,
1329
1341
  idleNotificationPending: status === "idle" ? existing?.idleNotificationPending ?? false : false
1330
1342
  });
@@ -1350,7 +1362,7 @@ var SessionTitleService = class {
1350
1362
  const existing = this.sessions.get(sessionId);
1351
1363
  this.sessions.set(sessionId, {
1352
1364
  title: existing?.title ?? null,
1353
- parentID: existing?.parentID ?? null,
1365
+ parentID: existing?.parentID,
1354
1366
  status: existing?.status ?? "idle",
1355
1367
  idleNotificationPending: true
1356
1368
  });
@@ -1370,6 +1382,17 @@ var SessionTitleService = class {
1370
1382
 
1371
1383
  // src/telegram-remote.ts
1372
1384
  var pluginDir = dirname4(fileURLToPath(import.meta.url));
1385
+ async function postToServer(serverUrl, path, body) {
1386
+ const url = new URL(path, serverUrl);
1387
+ const response = await fetch(url, {
1388
+ method: "POST",
1389
+ headers: { "Content-Type": "application/json" },
1390
+ body: JSON.stringify(body)
1391
+ });
1392
+ if (response.ok) return;
1393
+ const text = await response.text();
1394
+ throw new Error(`OpenCode request failed: ${response.status} ${response.statusText}${text ? ` - ${text}` : ""}`);
1395
+ }
1373
1396
  var TelegramRemote = async (input) => {
1374
1397
  const logger = createLogger({ namespace: "telegram" });
1375
1398
  try {
@@ -1396,26 +1419,41 @@ var TelegramRemote = async (input) => {
1396
1419
  });
1397
1420
  const sessionTitleService = new SessionTitleService();
1398
1421
  const client = input.client;
1399
- const replyToQuestion = async (requestID, answers) => {
1422
+ const replyToQuestion = async (requestID, answers, serverUrl = input.serverUrl.href) => {
1423
+ const path = `/question/${encodeURIComponent(requestID)}/reply`;
1424
+ if (serverUrl !== input.serverUrl.href) {
1425
+ await postToServer(serverUrl, path, { answers });
1426
+ return;
1427
+ }
1400
1428
  await client._client.post({
1401
- url: `/question/${encodeURIComponent(requestID)}/reply`,
1429
+ url: path,
1402
1430
  headers: { "Content-Type": "application/json" },
1403
1431
  body: { answers },
1404
1432
  throwOnError: true
1405
1433
  });
1406
1434
  };
1407
- const replyToPermission = async (requestID, sessionID, reply, endpoint) => {
1435
+ const replyToPermission = async (requestID, sessionID, reply, endpoint, serverUrl = input.serverUrl.href) => {
1408
1436
  if (endpoint === "request") {
1437
+ const path2 = `/permission/${encodeURIComponent(requestID)}/reply`;
1438
+ if (serverUrl !== input.serverUrl.href) {
1439
+ await postToServer(serverUrl, path2, { reply });
1440
+ return;
1441
+ }
1409
1442
  await client._client.post({
1410
- url: `/permission/${encodeURIComponent(requestID)}/reply`,
1443
+ url: path2,
1411
1444
  headers: { "Content-Type": "application/json" },
1412
1445
  body: { reply },
1413
1446
  throwOnError: true
1414
1447
  });
1415
1448
  return;
1416
1449
  }
1450
+ const path = `/session/${encodeURIComponent(sessionID)}/permissions/${encodeURIComponent(requestID)}`;
1451
+ if (serverUrl !== input.serverUrl.href) {
1452
+ await postToServer(serverUrl, path, { response: reply });
1453
+ return;
1454
+ }
1417
1455
  await client._client.post({
1418
- url: `/session/${encodeURIComponent(sessionID)}/permissions/${encodeURIComponent(requestID)}`,
1456
+ url: path,
1419
1457
  headers: { "Content-Type": "application/json" },
1420
1458
  body: { response: reply },
1421
1459
  throwOnError: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinseeker/opencode-telegram-plugin",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
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",