@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 +2 -2
- package/dist/telegram-remote.js +53 -15
- package/package.json +1 -1
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.
|
|
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.
|
|
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
|
|
package/dist/telegram-remote.js
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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.
|
|
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",
|