negotium 0.4.8 → 0.4.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/dist/agent-helpers.js +9 -2
- package/dist/agent-helpers.js.map +4 -4
- package/dist/hosted-agent.js +2 -2
- package/dist/hosted-agent.js.map +2 -2
- package/dist/main.js +354 -97
- package/dist/main.js.map +12 -12
- package/dist/mcp-factories.js +9 -2
- package/dist/mcp-factories.js.map +4 -4
- package/dist/registry.js +2 -2
- package/dist/registry.js.map +2 -2
- package/dist/runtime/src/index.ts +3 -0
- package/dist/runtime/src/node-host.ts +2 -0
- package/dist/runtime/src/storage/runtime-events.ts +69 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/types/packages/core/src/storage/runtime-events.d.ts +14 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1868,7 +1868,7 @@ var exports_version = {};
|
|
|
1868
1868
|
__export(exports_version, {
|
|
1869
1869
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
1870
1870
|
});
|
|
1871
|
-
var NEGOTIUM_VERSION = "0.4.
|
|
1871
|
+
var NEGOTIUM_VERSION = "0.4.9";
|
|
1872
1872
|
|
|
1873
1873
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
1874
1874
|
import { spawn } from "child_process";
|
|
@@ -6962,6 +6962,10 @@ function latestRuntimeEventSeq() {
|
|
|
6962
6962
|
const row = db.query("SELECT MAX(seq) AS seq FROM runtime_events").get();
|
|
6963
6963
|
return Number(row?.seq ?? 0);
|
|
6964
6964
|
}
|
|
6965
|
+
function earliestRuntimeEventSeq() {
|
|
6966
|
+
const row = db.query("SELECT MIN(seq) AS seq FROM runtime_events").get();
|
|
6967
|
+
return Number(row?.seq ?? 0);
|
|
6968
|
+
}
|
|
6965
6969
|
function appendRuntimeEvent(sourceId, event) {
|
|
6966
6970
|
const createdAt = new Date().toISOString();
|
|
6967
6971
|
const result = db.query(`INSERT INTO runtime_events
|
|
@@ -6978,6 +6982,30 @@ function listRuntimeEventsAfter(seq, limit = 500) {
|
|
|
6978
6982
|
LIMIT ?`).all(Math.max(0, seq), Math.max(1, Math.min(limit, 5000)));
|
|
6979
6983
|
return rows.map(rowToEvent).filter((event) => event !== null);
|
|
6980
6984
|
}
|
|
6985
|
+
function heartbeatRuntimeEventConsumer(consumerId, cursor, now = Date.now()) {
|
|
6986
|
+
db.query(`INSERT INTO runtime_event_consumers (consumer_id, cursor, heartbeat_at)
|
|
6987
|
+
VALUES (?, ?, ?)
|
|
6988
|
+
ON CONFLICT(consumer_id) DO UPDATE SET
|
|
6989
|
+
cursor = MAX(runtime_event_consumers.cursor, excluded.cursor),
|
|
6990
|
+
heartbeat_at = excluded.heartbeat_at`).run(consumerId, Math.max(0, cursor), now);
|
|
6991
|
+
}
|
|
6992
|
+
function pruneRuntimeEvents(options = {}) {
|
|
6993
|
+
const maxEvents = Math.max(1, Math.floor(options.maxEvents ?? 1e5));
|
|
6994
|
+
const now = options.now ?? Date.now();
|
|
6995
|
+
const activeAfter = now - Math.max(1000, options.activeConsumerMaxAgeMs ?? 5 * 60000);
|
|
6996
|
+
db.query("DELETE FROM runtime_event_consumers WHERE heartbeat_at < ?").run(activeAfter);
|
|
6997
|
+
const boundary = db.query("SELECT seq FROM runtime_events ORDER BY seq DESC LIMIT 1 OFFSET ?").get(maxEvents - 1);
|
|
6998
|
+
if (!boundary)
|
|
6999
|
+
return { deleted: 0, cutoff: 0, retainedForConsumer: null };
|
|
7000
|
+
const targetCutoff = Math.max(0, Number(boundary.seq) - 1);
|
|
7001
|
+
const consumer = db.query("SELECT MIN(cursor) AS cursor FROM runtime_event_consumers").get();
|
|
7002
|
+
const retainedForConsumer = consumer?.cursor == null ? null : Number(consumer.cursor);
|
|
7003
|
+
const cutoff = Math.min(targetCutoff, retainedForConsumer ?? targetCutoff);
|
|
7004
|
+
if (cutoff <= 0)
|
|
7005
|
+
return { deleted: 0, cutoff, retainedForConsumer };
|
|
7006
|
+
const result = db.query("DELETE FROM runtime_events WHERE seq <= ?").run(cutoff);
|
|
7007
|
+
return { deleted: Number(result.changes), cutoff, retainedForConsumer };
|
|
7008
|
+
}
|
|
6981
7009
|
function listRecentRuntimeEventsForTopic(topicId, limit = 300) {
|
|
6982
7010
|
const rows = db.query(`SELECT seq, source_id, event_type, topic_id, payload_json, created_at
|
|
6983
7011
|
FROM (
|
|
@@ -7021,6 +7049,13 @@ var init_runtime_events = __esm(async () => {
|
|
|
7021
7049
|
payload_json TEXT NOT NULL,
|
|
7022
7050
|
created_at TEXT NOT NULL
|
|
7023
7051
|
)
|
|
7052
|
+
`);
|
|
7053
|
+
database.exec(`
|
|
7054
|
+
CREATE TABLE IF NOT EXISTS runtime_event_consumers (
|
|
7055
|
+
consumer_id TEXT PRIMARY KEY,
|
|
7056
|
+
cursor INTEGER NOT NULL,
|
|
7057
|
+
heartbeat_at INTEGER NOT NULL
|
|
7058
|
+
)
|
|
7024
7059
|
`);
|
|
7025
7060
|
database.exec("CREATE INDEX IF NOT EXISTS idx_runtime_events_topic_seq ON runtime_events(topic_id, seq)");
|
|
7026
7061
|
});
|
|
@@ -23001,6 +23036,7 @@ __export(exports_src, {
|
|
|
23001
23036
|
reconcilePendingAskUserQuestionGates: () => reconcilePendingAskUserQuestionGates,
|
|
23002
23037
|
reapOrphanBrowsers: () => reapPlaywrightOrphans,
|
|
23003
23038
|
purgeTopicLogs: () => purgeTopicLogs,
|
|
23039
|
+
pruneRuntimeEvents: () => pruneRuntimeEvents,
|
|
23004
23040
|
prepareDeliveryAck: () => prepareDeliveryAck,
|
|
23005
23041
|
onShutdown: () => onShutdown,
|
|
23006
23042
|
normalizeVaultKey: () => normalizeVaultKey,
|
|
@@ -23040,6 +23076,7 @@ __export(exports_src, {
|
|
|
23040
23076
|
isAgentKind: () => isAgentKind,
|
|
23041
23077
|
interSessionQueue: () => interSessionQueue,
|
|
23042
23078
|
ingestAttachment: () => ingestAttachment,
|
|
23079
|
+
heartbeatRuntimeEventConsumer: () => heartbeatRuntimeEventConsumer,
|
|
23043
23080
|
grantSubagentTellTarget: () => grantSubagentTellTarget,
|
|
23044
23081
|
getVisibleTopics: () => getVisibleTopics,
|
|
23045
23082
|
getTopics: () => getTopics,
|
|
@@ -23074,6 +23111,7 @@ __export(exports_src, {
|
|
|
23074
23111
|
errMsg: () => errMsg,
|
|
23075
23112
|
ensurePersonalGeneral: () => ensurePersonalGeneral,
|
|
23076
23113
|
ensureBgBash: () => ensureBgBash,
|
|
23114
|
+
earliestRuntimeEventSeq: () => earliestRuntimeEventSeq,
|
|
23077
23115
|
dispatchPeerRuntimeVisual: () => dispatchPeerRuntimeVisual,
|
|
23078
23116
|
dispatchPeerRuntimeSpawn: () => dispatchPeerRuntimeSpawn,
|
|
23079
23117
|
dispatchPeerRuntimeSelfConfig: () => dispatchPeerRuntimeSelfConfig,
|
|
@@ -23572,6 +23610,7 @@ __export(exports_node_host, {
|
|
|
23572
23610
|
reconcilePendingAskUserQuestionGates: () => reconcilePendingAskUserQuestionGates,
|
|
23573
23611
|
reapOrphanBrowsers: () => reapPlaywrightOrphans,
|
|
23574
23612
|
readDecisions: () => readDecisions,
|
|
23613
|
+
pruneRuntimeEvents: () => pruneRuntimeEvents,
|
|
23575
23614
|
onShutdown: () => onShutdown,
|
|
23576
23615
|
nodeRequestHandlerNames: () => nodeRequestHandlerNames,
|
|
23577
23616
|
logger: () => logger,
|
|
@@ -23595,6 +23634,7 @@ __export(exports_node_host, {
|
|
|
23595
23634
|
flushBashrsCompletions: () => flushBashrsCompletions,
|
|
23596
23635
|
executeVaultCommand: () => executeVaultCommand,
|
|
23597
23636
|
ensurePersonalGeneral: () => ensurePersonalGeneral,
|
|
23637
|
+
earliestRuntimeEventSeq: () => earliestRuntimeEventSeq,
|
|
23598
23638
|
deleteVaultEntry: () => deleteVaultEntry,
|
|
23599
23639
|
compactTopicSession: () => compactTopicSession,
|
|
23600
23640
|
appendApiMessage: () => appendApiMessage,
|
|
@@ -29840,8 +29880,8 @@ function createPollingSseStream(req, options) {
|
|
|
29840
29880
|
} catch {}
|
|
29841
29881
|
};
|
|
29842
29882
|
const send = (event, data, id) => {
|
|
29843
|
-
if (closed)
|
|
29844
|
-
return;
|
|
29883
|
+
if (closed || controller.desiredSize !== null && controller.desiredSize <= 0)
|
|
29884
|
+
return false;
|
|
29845
29885
|
try {
|
|
29846
29886
|
const lines = [
|
|
29847
29887
|
id === undefined ? "" : `id: ${id}`,
|
|
@@ -29852,8 +29892,10 @@ function createPollingSseStream(req, options) {
|
|
|
29852
29892
|
controller.enqueue(encoder.encode(`${lines}
|
|
29853
29893
|
|
|
29854
29894
|
`));
|
|
29895
|
+
return true;
|
|
29855
29896
|
} catch (error2) {
|
|
29856
29897
|
fail(error2);
|
|
29898
|
+
return false;
|
|
29857
29899
|
}
|
|
29858
29900
|
};
|
|
29859
29901
|
const close = () => {
|
|
@@ -29896,7 +29938,7 @@ function createPollingSseStream(req, options) {
|
|
|
29896
29938
|
return;
|
|
29897
29939
|
pollTimer = setInterval(pump, options.pollIntervalMs ?? 100);
|
|
29898
29940
|
heartbeatTimer = setInterval(() => {
|
|
29899
|
-
if (closed)
|
|
29941
|
+
if (closed || controller.desiredSize !== null && controller.desiredSize <= 0)
|
|
29900
29942
|
return;
|
|
29901
29943
|
try {
|
|
29902
29944
|
controller.enqueue(encoder.encode(`: heartbeat ${Date.now()}
|
|
@@ -29910,7 +29952,7 @@ function createPollingSseStream(req, options) {
|
|
|
29910
29952
|
cancel() {
|
|
29911
29953
|
stop();
|
|
29912
29954
|
}
|
|
29913
|
-
});
|
|
29955
|
+
}, { highWaterMark: 64 });
|
|
29914
29956
|
return new Response(stream, {
|
|
29915
29957
|
headers: {
|
|
29916
29958
|
"cache-control": "no-cache, no-transform",
|
|
@@ -30018,7 +30060,6 @@ function runtimeEvent(event) {
|
|
|
30018
30060
|
}
|
|
30019
30061
|
function createRuntimeContractEventStream(req, after, topicId, scope = {}) {
|
|
30020
30062
|
const scoped = "surfaceScope" in scope;
|
|
30021
|
-
const wanted = scope.surfaceScope ?? null;
|
|
30022
30063
|
const visible = new Map;
|
|
30023
30064
|
const eventInScope = (eventTopicId) => {
|
|
30024
30065
|
if (!scoped)
|
|
@@ -30026,26 +30067,39 @@ function createRuntimeContractEventStream(req, after, topicId, scope = {}) {
|
|
|
30026
30067
|
const cached = visible.get(eventTopicId);
|
|
30027
30068
|
if (cached !== undefined)
|
|
30028
30069
|
return cached;
|
|
30029
|
-
const
|
|
30030
|
-
const allowed =
|
|
30070
|
+
const topic = getTopic(eventTopicId);
|
|
30071
|
+
const allowed = Boolean(topic && topicInRequestScope(req, topic));
|
|
30031
30072
|
visible.set(eventTopicId, allowed);
|
|
30032
30073
|
return allowed;
|
|
30033
30074
|
};
|
|
30034
30075
|
let cursor = Math.max(0, after);
|
|
30076
|
+
let reportedCursor = cursor;
|
|
30077
|
+
const oldestCursor = earliestRuntimeEventSeq();
|
|
30035
30078
|
return createPollingSseStream(req, {
|
|
30036
|
-
ready: {
|
|
30079
|
+
ready: {
|
|
30080
|
+
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
30081
|
+
cursor,
|
|
30082
|
+
oldestCursor,
|
|
30083
|
+
truncated: oldestCursor > 0 && cursor < oldestCursor - 1
|
|
30084
|
+
},
|
|
30037
30085
|
pump(send) {
|
|
30038
|
-
|
|
30086
|
+
for (let batch = 0;batch < 5; batch += 1) {
|
|
30039
30087
|
const events = listRuntimeEventsAfter(cursor, 500);
|
|
30040
|
-
if (events.length === 0)
|
|
30088
|
+
if (events.length === 0) {
|
|
30089
|
+
if (reportedCursor < cursor && send("cursor", { cursor }, cursor))
|
|
30090
|
+
reportedCursor = cursor;
|
|
30041
30091
|
break;
|
|
30092
|
+
}
|
|
30042
30093
|
for (const event of events) {
|
|
30043
|
-
cursor = event.seq;
|
|
30044
30094
|
if ((!topicId || event.topicId === topicId) && eventInScope(event.topicId)) {
|
|
30045
|
-
send("runtime", runtimeEvent(event), event.seq)
|
|
30095
|
+
if (!send("runtime", runtimeEvent(event), event.seq))
|
|
30096
|
+
return;
|
|
30046
30097
|
}
|
|
30098
|
+
cursor = event.seq;
|
|
30047
30099
|
}
|
|
30048
|
-
send("cursor", { cursor }, cursor)
|
|
30100
|
+
if (!send("cursor", { cursor }, cursor))
|
|
30101
|
+
return;
|
|
30102
|
+
reportedCursor = cursor;
|
|
30049
30103
|
if (events.length < 500)
|
|
30050
30104
|
break;
|
|
30051
30105
|
}
|
|
@@ -30055,15 +30109,24 @@ function createRuntimeContractEventStream(req, after, topicId, scope = {}) {
|
|
|
30055
30109
|
function createEventStream(req, userId, after, surface) {
|
|
30056
30110
|
const allowedTopics = new Set(topicsForUser(userId, surface).map((topic) => topic.id));
|
|
30057
30111
|
let cursor = Math.max(0, after);
|
|
30112
|
+
let reportedCursor = cursor;
|
|
30113
|
+
const oldestCursor = earliestRuntimeEventSeq();
|
|
30058
30114
|
return createPollingSseStream(req, {
|
|
30059
|
-
ready: {
|
|
30115
|
+
ready: {
|
|
30116
|
+
protocolVersion: NODE_CONTROL_PROTOCOL_VERSION,
|
|
30117
|
+
cursor,
|
|
30118
|
+
oldestCursor,
|
|
30119
|
+
truncated: oldestCursor > 0 && cursor < oldestCursor - 1
|
|
30120
|
+
},
|
|
30060
30121
|
pump(send) {
|
|
30061
|
-
|
|
30122
|
+
for (let batch = 0;batch < 5; batch += 1) {
|
|
30062
30123
|
const events = listRuntimeEventsAfter(cursor, 500);
|
|
30063
|
-
if (events.length === 0)
|
|
30124
|
+
if (events.length === 0) {
|
|
30125
|
+
if (reportedCursor < cursor && send("cursor", { cursor }, cursor))
|
|
30126
|
+
reportedCursor = cursor;
|
|
30064
30127
|
break;
|
|
30128
|
+
}
|
|
30065
30129
|
for (const event of events) {
|
|
30066
|
-
cursor = event.seq;
|
|
30067
30130
|
if (event.type === "topic-created" || event.type === "topic-updated") {
|
|
30068
30131
|
const topic = getTopic(event.topicId);
|
|
30069
30132
|
const admissible = topic && isParticipant(topic, userId) && (!surface || topic.surface === surface);
|
|
@@ -30073,12 +30136,15 @@ function createEventStream(req, userId, after, surface) {
|
|
|
30073
30136
|
allowedTopics.delete(event.topicId);
|
|
30074
30137
|
}
|
|
30075
30138
|
const visible = allowedTopics.has(event.topicId);
|
|
30076
|
-
if (visible)
|
|
30077
|
-
|
|
30139
|
+
if (visible && !send("runtime", runtimeEvent(event), event.seq))
|
|
30140
|
+
return;
|
|
30141
|
+
cursor = event.seq;
|
|
30078
30142
|
if (event.type === "topic-deleted")
|
|
30079
30143
|
allowedTopics.delete(event.topicId);
|
|
30080
30144
|
}
|
|
30081
|
-
send("cursor", { cursor }, cursor)
|
|
30145
|
+
if (!send("cursor", { cursor }, cursor))
|
|
30146
|
+
return;
|
|
30147
|
+
reportedCursor = cursor;
|
|
30082
30148
|
if (events.length < 500)
|
|
30083
30149
|
break;
|
|
30084
30150
|
}
|
|
@@ -32830,6 +32896,19 @@ function startNode(opts = {}) {
|
|
|
32830
32896
|
setRuntimeMcpPort(port);
|
|
32831
32897
|
const stopTurnRequests = startDurableTurnRequestWorker();
|
|
32832
32898
|
const stopInbox = startSessionInboxWorker();
|
|
32899
|
+
const pruneEventLog = () => {
|
|
32900
|
+
try {
|
|
32901
|
+
const result = pruneRuntimeEvents();
|
|
32902
|
+
if (result.deleted > 0) {
|
|
32903
|
+
logger.info(result, "runtime event log pruned");
|
|
32904
|
+
}
|
|
32905
|
+
} catch (err2) {
|
|
32906
|
+
logger.warn({ err: err2 }, "runtime event log prune failed");
|
|
32907
|
+
}
|
|
32908
|
+
};
|
|
32909
|
+
pruneEventLog();
|
|
32910
|
+
const eventPruneTimer = setInterval(pruneEventLog, 5 * 60000);
|
|
32911
|
+
eventPruneTimer.unref?.();
|
|
32833
32912
|
const stopBashrsCompletions = startBashrsCompletionsWorker();
|
|
32834
32913
|
let modules;
|
|
32835
32914
|
try {
|
|
@@ -32844,6 +32923,7 @@ function startNode(opts = {}) {
|
|
|
32844
32923
|
} catch (error2) {
|
|
32845
32924
|
stopTurnRequests();
|
|
32846
32925
|
stopInbox();
|
|
32926
|
+
clearInterval(eventPruneTimer);
|
|
32847
32927
|
stopBashrsCompletions();
|
|
32848
32928
|
server.stop(true);
|
|
32849
32929
|
processLease?.stop();
|
|
@@ -32870,6 +32950,7 @@ function startNode(opts = {}) {
|
|
|
32870
32950
|
});
|
|
32871
32951
|
stopTurnRequests();
|
|
32872
32952
|
stopInbox();
|
|
32953
|
+
clearInterval(eventPruneTimer);
|
|
32873
32954
|
stopBashrsCompletions();
|
|
32874
32955
|
server.stop(true);
|
|
32875
32956
|
processLease?.stop();
|
|
@@ -32882,6 +32963,7 @@ function startNode(opts = {}) {
|
|
|
32882
32963
|
onShutdown("node-server", 130, () => {
|
|
32883
32964
|
stopTurnRequests();
|
|
32884
32965
|
stopInbox();
|
|
32966
|
+
clearInterval(eventPruneTimer);
|
|
32885
32967
|
stopBashrsCompletions();
|
|
32886
32968
|
server.stop(true);
|
|
32887
32969
|
});
|
|
@@ -40800,6 +40882,11 @@ function createTables(db4) {
|
|
|
40800
40882
|
key TEXT PRIMARY KEY,
|
|
40801
40883
|
value TEXT NOT NULL
|
|
40802
40884
|
)`);
|
|
40885
|
+
db4.run(`CREATE TABLE IF NOT EXISTS runtime_inbox (
|
|
40886
|
+
seq INTEGER PRIMARY KEY,
|
|
40887
|
+
runtime_message_id TEXT,
|
|
40888
|
+
event_json TEXT NOT NULL
|
|
40889
|
+
)`);
|
|
40803
40890
|
}
|
|
40804
40891
|
function migrateOutboxSchema(db4) {
|
|
40805
40892
|
try {
|
|
@@ -40810,6 +40897,13 @@ function migrateOutboxSchema(db4) {
|
|
|
40810
40897
|
} catch {}
|
|
40811
40898
|
db4.run("CREATE INDEX IF NOT EXISTS idx_telegram_outbox_runtime_message ON outbox(runtime_message_id)");
|
|
40812
40899
|
}
|
|
40900
|
+
function migrateRuntimeInboxSchema(db4) {
|
|
40901
|
+
try {
|
|
40902
|
+
db4.run("ALTER TABLE runtime_inbox ADD COLUMN runtime_message_id TEXT");
|
|
40903
|
+
} catch {}
|
|
40904
|
+
db4.run(`CREATE UNIQUE INDEX IF NOT EXISTS idx_telegram_runtime_inbox_message
|
|
40905
|
+
ON runtime_inbox(runtime_message_id) WHERE runtime_message_id IS NOT NULL`);
|
|
40906
|
+
}
|
|
40813
40907
|
function openMappingStore(path) {
|
|
40814
40908
|
const dbPath = path ?? join45(DATA_DIR, "adapter-telegram.db");
|
|
40815
40909
|
if (dbPath !== ":memory:")
|
|
@@ -40818,6 +40912,7 @@ function openMappingStore(path) {
|
|
|
40818
40912
|
migrateLegacySchema(db4);
|
|
40819
40913
|
createTables(db4);
|
|
40820
40914
|
migrateOutboxSchema(db4);
|
|
40915
|
+
migrateRuntimeInboxSchema(db4);
|
|
40821
40916
|
return {
|
|
40822
40917
|
load() {
|
|
40823
40918
|
const rows = db4.query("SELECT chat_id, thread_id, topic_id FROM mappings").all();
|
|
@@ -40891,6 +40986,40 @@ function openMappingStore(path) {
|
|
|
40891
40986
|
entry.lastError ?? null
|
|
40892
40987
|
]);
|
|
40893
40988
|
},
|
|
40989
|
+
runtimeEventCursor() {
|
|
40990
|
+
const row = db4.query("SELECT value FROM settings WHERE key = 'runtime_event_cursor'").get();
|
|
40991
|
+
if (!row)
|
|
40992
|
+
return;
|
|
40993
|
+
const value = Number.parseInt(row.value, 10);
|
|
40994
|
+
return Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
40995
|
+
},
|
|
40996
|
+
captureRuntimeEvent(event) {
|
|
40997
|
+
const messageId = event.payload && typeof event.payload === "object" && "id" in event.payload && typeof event.payload.id === "string" ? event.payload.id : null;
|
|
40998
|
+
db4.transaction(() => {
|
|
40999
|
+
db4.run(`INSERT OR IGNORE INTO runtime_inbox (seq, runtime_message_id, event_json)
|
|
41000
|
+
VALUES (?, ?, ?)`, [event.seq, messageId, JSON.stringify(event)]);
|
|
41001
|
+
db4.run(`INSERT INTO settings (key, value) VALUES ('runtime_event_cursor', ?)
|
|
41002
|
+
ON CONFLICT(key) DO UPDATE SET value = MAX(CAST(value AS INTEGER), CAST(excluded.value AS INTEGER))`, [String(event.seq)]);
|
|
41003
|
+
})();
|
|
41004
|
+
},
|
|
41005
|
+
advanceRuntimeEventCursor(seq) {
|
|
41006
|
+
db4.run(`INSERT INTO settings (key, value) VALUES ('runtime_event_cursor', ?)
|
|
41007
|
+
ON CONFLICT(key) DO UPDATE SET value = MAX(CAST(value AS INTEGER), CAST(excluded.value AS INTEGER))`, [String(seq)]);
|
|
41008
|
+
},
|
|
41009
|
+
pendingRuntimeEvents() {
|
|
41010
|
+
const rows = db4.query("SELECT seq, event_json FROM runtime_inbox ORDER BY seq ASC").all();
|
|
41011
|
+
return rows.flatMap((row) => {
|
|
41012
|
+
try {
|
|
41013
|
+
return [{ seq: row.seq, event: JSON.parse(row.event_json) }];
|
|
41014
|
+
} catch {
|
|
41015
|
+
db4.run("DELETE FROM runtime_inbox WHERE seq = ?", [row.seq]);
|
|
41016
|
+
return [];
|
|
41017
|
+
}
|
|
41018
|
+
});
|
|
41019
|
+
},
|
|
41020
|
+
acknowledgeRuntimeEvent(seq) {
|
|
41021
|
+
db4.run("DELETE FROM runtime_inbox WHERE seq = ?", [seq]);
|
|
41022
|
+
},
|
|
40894
41023
|
outboxDue(now) {
|
|
40895
41024
|
const rows = db4.query("SELECT * FROM outbox WHERE dead = 0 AND next_try_at <= ? ORDER BY id ASC").all(now);
|
|
40896
41025
|
return rows.map(outboxRowToEntry);
|
|
@@ -41768,15 +41897,29 @@ function startTelegramAdapter(opts) {
|
|
|
41768
41897
|
}
|
|
41769
41898
|
const sendQueues = new Map;
|
|
41770
41899
|
function enqueueSend(topicId, task) {
|
|
41771
|
-
const prev = sendQueues.get(topicId) ?? Promise.resolve();
|
|
41900
|
+
const prev = sendQueues.get(topicId) ?? Promise.resolve(true);
|
|
41772
41901
|
const next = prev.then(() => new Promise((resolve24) => {
|
|
41902
|
+
let settled = false;
|
|
41773
41903
|
const timer = setTimeout(() => {
|
|
41904
|
+
if (settled)
|
|
41905
|
+
return;
|
|
41906
|
+
settled = true;
|
|
41774
41907
|
logger.warn({ topicId, sendTimeoutMs }, "telegram adapter: send timed out \u2014 abandoning it and continuing the queue");
|
|
41775
|
-
resolve24();
|
|
41908
|
+
resolve24(false);
|
|
41776
41909
|
}, sendTimeoutMs);
|
|
41777
|
-
task().
|
|
41910
|
+
task().then(() => {
|
|
41911
|
+
if (settled)
|
|
41912
|
+
return;
|
|
41913
|
+
settled = true;
|
|
41914
|
+
clearTimeout(timer);
|
|
41915
|
+
resolve24(true);
|
|
41916
|
+
}).catch((err2) => {
|
|
41917
|
+
logger.warn({ err: err2, topicId }, "telegram adapter: send task failed");
|
|
41918
|
+
if (settled)
|
|
41919
|
+
return;
|
|
41920
|
+
settled = true;
|
|
41778
41921
|
clearTimeout(timer);
|
|
41779
|
-
resolve24();
|
|
41922
|
+
resolve24(false);
|
|
41780
41923
|
});
|
|
41781
41924
|
}));
|
|
41782
41925
|
sendQueues.set(topicId, next);
|
|
@@ -41784,13 +41927,14 @@ function startTelegramAdapter(opts) {
|
|
|
41784
41927
|
if (sendQueues.get(topicId) === next)
|
|
41785
41928
|
sendQueues.delete(topicId);
|
|
41786
41929
|
});
|
|
41930
|
+
return next;
|
|
41787
41931
|
}
|
|
41788
41932
|
function enqueueFanout(topicId, mappings, payload) {
|
|
41789
41933
|
const targets = [...mappings];
|
|
41790
|
-
enqueueSend(topicId, () => deliverToTargets(topicId, targets, payload));
|
|
41934
|
+
enqueueSend(topicId, () => deliverToTargets(topicId, targets, payload)).then(payload.onSettled);
|
|
41791
41935
|
}
|
|
41792
41936
|
function enqueueTarget(topicId, target, payload) {
|
|
41793
|
-
enqueueSend(topicId, () => deliverToTargets(topicId, [target], payload));
|
|
41937
|
+
enqueueSend(topicId, () => deliverToTargets(topicId, [target], payload)).then(payload.onSettled);
|
|
41794
41938
|
}
|
|
41795
41939
|
const pendingByTopic = new Map;
|
|
41796
41940
|
const permissionBlockedTopics = new Map;
|
|
@@ -41808,8 +41952,9 @@ function startTelegramAdapter(opts) {
|
|
|
41808
41952
|
});
|
|
41809
41953
|
}
|
|
41810
41954
|
function flushBuffered(topicId, buffer, send) {
|
|
41811
|
-
for (const payload of buffer)
|
|
41812
|
-
enqueueSend(topicId, () => send(payload));
|
|
41955
|
+
for (const payload of buffer) {
|
|
41956
|
+
enqueueSend(topicId, () => send(payload)).then(payload.onSettled);
|
|
41957
|
+
}
|
|
41813
41958
|
}
|
|
41814
41959
|
function materializeTopic(topic) {
|
|
41815
41960
|
if (!forumManageTopicsAvailable || suppressMaterialize > 0 || byTopic.has(topic.id) || pendingByTopic.has(topic.id) || permissionBlockedTopics.has(topic.id) || materializeTombstones.has(topic.id)) {
|
|
@@ -41871,8 +42016,12 @@ function startTelegramAdapter(opts) {
|
|
|
41871
42016
|
if (materializeTombstones.delete(topicId))
|
|
41872
42017
|
store.deleteTombstone(topicId);
|
|
41873
42018
|
const pending2 = pendingByTopic.get(topicId);
|
|
41874
|
-
if (pending2)
|
|
42019
|
+
if (pending2) {
|
|
41875
42020
|
pending2.cancelled = true;
|
|
42021
|
+
for (const payload of pending2.buffer)
|
|
42022
|
+
payload.onSettled?.(true);
|
|
42023
|
+
pending2.buffer = [];
|
|
42024
|
+
}
|
|
41876
42025
|
for (const [messageId, message] of runtimeMessages) {
|
|
41877
42026
|
if (message.topicId === topicId)
|
|
41878
42027
|
deleteDeliveredRuntimeMessage(topicId, messageId);
|
|
@@ -41919,7 +42068,7 @@ function startTelegramAdapter(opts) {
|
|
|
41919
42068
|
}
|
|
41920
42069
|
const tombstoneTitle = materializeTombstones.get(topicId);
|
|
41921
42070
|
if (tombstoneTitle !== undefined) {
|
|
41922
|
-
enqueueSend(topicId, () => deliverFallback(topicId, tombstoneTitle, payload));
|
|
42071
|
+
enqueueSend(topicId, () => deliverFallback(topicId, tombstoneTitle, payload)).then(payload.onSettled);
|
|
41923
42072
|
return true;
|
|
41924
42073
|
}
|
|
41925
42074
|
const topic = getTopic(topicId);
|
|
@@ -41927,7 +42076,7 @@ function startTelegramAdapter(opts) {
|
|
|
41927
42076
|
return false;
|
|
41928
42077
|
if (forumMode) {
|
|
41929
42078
|
if (!forumManageTopicsAvailable || permissionBlockedTopics.has(topicId)) {
|
|
41930
|
-
enqueueSend(topicId, () => deliverFallback(topicId, topic.title, payload));
|
|
42079
|
+
enqueueSend(topicId, () => deliverFallback(topicId, topic.title, payload)).then(payload.onSettled);
|
|
41931
42080
|
return true;
|
|
41932
42081
|
}
|
|
41933
42082
|
if (!materializeTopic(topic))
|
|
@@ -42375,6 +42524,113 @@ Warning: enable the bot administrator permission "Manage Topics" before creating
|
|
|
42375
42524
|
}
|
|
42376
42525
|
linkForumAndAnnounce(update.from.id, update.chat, update.new_chat_member).catch((err2) => logger.warn({ err: err2, groupId: update.chat.id }, "telegram adapter: forum auto-connect failed"));
|
|
42377
42526
|
});
|
|
42527
|
+
async function deliverPersistedRuntimeMessage(event) {
|
|
42528
|
+
const msg = event.payload;
|
|
42529
|
+
if (msg.authorId === userId && msg.sourceAdapter === "telegram")
|
|
42530
|
+
return true;
|
|
42531
|
+
if (msg.kind === "tool")
|
|
42532
|
+
return true;
|
|
42533
|
+
const hasAttachments = Boolean(msg.attachments && msg.attachments.length > 0);
|
|
42534
|
+
if (!msg.text && !hasAttachments)
|
|
42535
|
+
return true;
|
|
42536
|
+
const runtimeMessageId = msg.authorId === "ai" ? msg.id : undefined;
|
|
42537
|
+
if (runtimeMessageId) {
|
|
42538
|
+
runtimeMessages.set(runtimeMessageId, msg);
|
|
42539
|
+
if (!msg.queryId) {
|
|
42540
|
+
const timer = setTimeout(() => {
|
|
42541
|
+
runtimeMessages.delete(runtimeMessageId);
|
|
42542
|
+
deliveredByRuntimeMessageId.delete(runtimeMessageId);
|
|
42543
|
+
}, 5 * 60000);
|
|
42544
|
+
timer.unref?.();
|
|
42545
|
+
}
|
|
42546
|
+
}
|
|
42547
|
+
const tagFiles = msg.text ? extractFileTagPaths(msg.text).map((path) => ({ path, filename: basename12(path) })) : [];
|
|
42548
|
+
const attachmentFiles = hasAttachments ? (msg.attachments ?? []).map((attachment) => {
|
|
42549
|
+
const path = resolveUploadedFilePathByFileId(attachment.id);
|
|
42550
|
+
if (!path)
|
|
42551
|
+
return null;
|
|
42552
|
+
return {
|
|
42553
|
+
path,
|
|
42554
|
+
filename: basename12(attachment.filename) || basename12(path),
|
|
42555
|
+
...attachment.mimeType ? { mimeType: attachment.mimeType } : {}
|
|
42556
|
+
};
|
|
42557
|
+
}).filter((file) => file !== null) : [];
|
|
42558
|
+
const files = [...tagFiles, ...attachmentFiles];
|
|
42559
|
+
const rawText = tagFiles.length > 0 && msg.text ? stripFileTags(msg.text) : msg.text ?? "";
|
|
42560
|
+
const text2 = msg.authorId === userId && rawText ? `[From: User] ${rawText}` : rawText;
|
|
42561
|
+
if (!text2 && files.length === 0)
|
|
42562
|
+
return true;
|
|
42563
|
+
let settle;
|
|
42564
|
+
const settled = new Promise((resolve24) => {
|
|
42565
|
+
settle = resolve24;
|
|
42566
|
+
});
|
|
42567
|
+
const payload = {
|
|
42568
|
+
text: text2,
|
|
42569
|
+
files,
|
|
42570
|
+
runtimeMessageId,
|
|
42571
|
+
deliveryAckRequested: msg.deliveryAckRequested === true,
|
|
42572
|
+
onSettled: settle
|
|
42573
|
+
};
|
|
42574
|
+
const routed = routeMessage(event.topicId, payload, msg.queryId);
|
|
42575
|
+
if (routed && payload.deliveryAckRequested)
|
|
42576
|
+
claimDeliveryAck(event.topicId, msg.id);
|
|
42577
|
+
return routed ? settled : true;
|
|
42578
|
+
}
|
|
42579
|
+
const savedRuntimeEventCursor = store.runtimeEventCursor();
|
|
42580
|
+
let runtimeEventCursor = savedRuntimeEventCursor ?? latestRuntimeEventSeq();
|
|
42581
|
+
if (savedRuntimeEventCursor === undefined) {
|
|
42582
|
+
store.advanceRuntimeEventCursor(runtimeEventCursor);
|
|
42583
|
+
}
|
|
42584
|
+
const runtimeEventConsumerId = `telegram:${userId}:${opts.mappingDbPath ?? "default"}`;
|
|
42585
|
+
heartbeatRuntimeEventConsumer(runtimeEventConsumerId, runtimeEventCursor);
|
|
42586
|
+
let pollingRuntimeEvents = false;
|
|
42587
|
+
let drainingRuntimeInbox = false;
|
|
42588
|
+
const drainRuntimeInbox = async () => {
|
|
42589
|
+
if (drainingRuntimeInbox || stopped)
|
|
42590
|
+
return;
|
|
42591
|
+
drainingRuntimeInbox = true;
|
|
42592
|
+
try {
|
|
42593
|
+
while (!stopped) {
|
|
42594
|
+
const pending2 = store.pendingRuntimeEvents()[0];
|
|
42595
|
+
if (!pending2)
|
|
42596
|
+
break;
|
|
42597
|
+
const delivered = await deliverPersistedRuntimeMessage(pending2.event);
|
|
42598
|
+
if (!delivered || stopped)
|
|
42599
|
+
break;
|
|
42600
|
+
store.acknowledgeRuntimeEvent(pending2.seq);
|
|
42601
|
+
}
|
|
42602
|
+
} catch (err2) {
|
|
42603
|
+
if (!stopped)
|
|
42604
|
+
logger.warn({ err: err2 }, "telegram adapter: durable runtime inbox drain failed");
|
|
42605
|
+
} finally {
|
|
42606
|
+
drainingRuntimeInbox = false;
|
|
42607
|
+
}
|
|
42608
|
+
};
|
|
42609
|
+
const pollRuntimeEvents = () => {
|
|
42610
|
+
if (pollingRuntimeEvents || stopped)
|
|
42611
|
+
return;
|
|
42612
|
+
pollingRuntimeEvents = true;
|
|
42613
|
+
try {
|
|
42614
|
+
for (let batch = 0;batch < 5; batch += 1) {
|
|
42615
|
+
const events = listRuntimeEventsAfter(runtimeEventCursor, 500);
|
|
42616
|
+
if (events.length === 0)
|
|
42617
|
+
break;
|
|
42618
|
+
for (const event of events) {
|
|
42619
|
+
if (event.type === "message")
|
|
42620
|
+
store.captureRuntimeEvent({ ...event, seq: event.seq });
|
|
42621
|
+
else
|
|
42622
|
+
store.advanceRuntimeEventCursor(event.seq);
|
|
42623
|
+
runtimeEventCursor = event.seq;
|
|
42624
|
+
}
|
|
42625
|
+
if (events.length < 500)
|
|
42626
|
+
break;
|
|
42627
|
+
}
|
|
42628
|
+
drainRuntimeInbox();
|
|
42629
|
+
heartbeatRuntimeEventConsumer(runtimeEventConsumerId, runtimeEventCursor);
|
|
42630
|
+
} finally {
|
|
42631
|
+
pollingRuntimeEvents = false;
|
|
42632
|
+
}
|
|
42633
|
+
};
|
|
42378
42634
|
const unsubscribe = runtimeBus().subscribe((event) => {
|
|
42379
42635
|
if (stopped)
|
|
42380
42636
|
return;
|
|
@@ -42387,22 +42643,22 @@ Warning: enable the bot administrator permission "Manage Topics" before creating
|
|
|
42387
42643
|
return;
|
|
42388
42644
|
}
|
|
42389
42645
|
if (event.type === "message-updated") {
|
|
42390
|
-
const
|
|
42391
|
-
if (!
|
|
42646
|
+
const payload = event.payload;
|
|
42647
|
+
if (!payload.messageId || !payload.patch)
|
|
42392
42648
|
return;
|
|
42393
|
-
if (
|
|
42394
|
-
deleteDeliveredRuntimeMessage(event.topicId,
|
|
42649
|
+
if (payload.patch.deleted) {
|
|
42650
|
+
deleteDeliveredRuntimeMessage(event.topicId, payload.messageId);
|
|
42395
42651
|
return;
|
|
42396
42652
|
}
|
|
42397
|
-
const current3 = runtimeMessages.get(
|
|
42653
|
+
const current3 = runtimeMessages.get(payload.messageId);
|
|
42398
42654
|
if (!current3)
|
|
42399
42655
|
return;
|
|
42400
|
-
const updated = { ...current3, ...
|
|
42401
|
-
runtimeMessages.set(
|
|
42402
|
-
if (footerEnabled &&
|
|
42656
|
+
const updated = { ...current3, ...payload.patch };
|
|
42657
|
+
runtimeMessages.set(payload.messageId, updated);
|
|
42658
|
+
if (footerEnabled && payload.patch.usage && updated.authorId === "ai") {
|
|
42403
42659
|
const footer = renderTurnFooter(updated);
|
|
42404
42660
|
if (footer)
|
|
42405
|
-
attachUpdatedFooter(event.topicId,
|
|
42661
|
+
attachUpdatedFooter(event.topicId, payload.messageId, footer);
|
|
42406
42662
|
}
|
|
42407
42663
|
return;
|
|
42408
42664
|
}
|
|
@@ -42425,53 +42681,10 @@ Warning: enable the bot administrator permission "Manage Topics" before creating
|
|
|
42425
42681
|
}
|
|
42426
42682
|
return;
|
|
42427
42683
|
}
|
|
42428
|
-
if (event.type !== "message")
|
|
42429
|
-
return;
|
|
42430
|
-
const msg = event.payload;
|
|
42431
|
-
if (msg.authorId === userId && msg.sourceAdapter === "telegram")
|
|
42432
|
-
return;
|
|
42433
|
-
if (msg.kind === "tool")
|
|
42434
|
-
return;
|
|
42435
|
-
const hasAttachments = Boolean(msg.attachments && msg.attachments.length > 0);
|
|
42436
|
-
if (!msg.text && !hasAttachments)
|
|
42437
|
-
return;
|
|
42438
|
-
const runtimeMessageId = msg.authorId === "ai" ? msg.id : undefined;
|
|
42439
|
-
if (runtimeMessageId) {
|
|
42440
|
-
runtimeMessages.set(runtimeMessageId, msg);
|
|
42441
|
-
if (!msg.queryId) {
|
|
42442
|
-
const timer = setTimeout(() => {
|
|
42443
|
-
runtimeMessages.delete(runtimeMessageId);
|
|
42444
|
-
deliveredByRuntimeMessageId.delete(runtimeMessageId);
|
|
42445
|
-
}, 5 * 60000);
|
|
42446
|
-
timer.unref?.();
|
|
42447
|
-
}
|
|
42448
|
-
}
|
|
42449
|
-
const tagFiles = msg.text ? extractFileTagPaths(msg.text).map((path) => ({ path, filename: basename12(path) })) : [];
|
|
42450
|
-
const attachmentFiles = hasAttachments ? (msg.attachments ?? []).map((attachment) => {
|
|
42451
|
-
const path = resolveUploadedFilePathByFileId(attachment.id);
|
|
42452
|
-
if (!path)
|
|
42453
|
-
return null;
|
|
42454
|
-
return {
|
|
42455
|
-
path,
|
|
42456
|
-
filename: basename12(attachment.filename) || basename12(path),
|
|
42457
|
-
...attachment.mimeType ? { mimeType: attachment.mimeType } : {}
|
|
42458
|
-
};
|
|
42459
|
-
}).filter((file) => file !== null) : [];
|
|
42460
|
-
const files = [...tagFiles, ...attachmentFiles];
|
|
42461
|
-
const rawText = tagFiles.length > 0 && msg.text ? stripFileTags(msg.text) : msg.text ?? "";
|
|
42462
|
-
const text2 = msg.authorId === userId && rawText ? `[From: User] ${rawText}` : rawText;
|
|
42463
|
-
if (!text2 && files.length === 0)
|
|
42464
|
-
return;
|
|
42465
|
-
const payload = {
|
|
42466
|
-
text: text2,
|
|
42467
|
-
files,
|
|
42468
|
-
runtimeMessageId,
|
|
42469
|
-
deliveryAckRequested: msg.deliveryAckRequested === true
|
|
42470
|
-
};
|
|
42471
|
-
if (routeMessage(event.topicId, payload, msg.queryId) && payload.deliveryAckRequested) {
|
|
42472
|
-
claimDeliveryAck(event.topicId, msg.id);
|
|
42473
|
-
}
|
|
42474
42684
|
});
|
|
42685
|
+
pollRuntimeEvents();
|
|
42686
|
+
const runtimeEventPollTimer = setInterval(pollRuntimeEvents, 100);
|
|
42687
|
+
runtimeEventPollTimer.unref?.();
|
|
42475
42688
|
if (forumMode) {
|
|
42476
42689
|
bindMapping(forumChat, undefined, personalGeneral.id);
|
|
42477
42690
|
materializeVisibleTopics();
|
|
@@ -42491,6 +42704,7 @@ Warning: enable the bot administrator permission "Manage Topics" before creating
|
|
|
42491
42704
|
for (const queryId of toolStatusByQueryId.keys())
|
|
42492
42705
|
closeToolStatus(queryId);
|
|
42493
42706
|
mediaIntake.stop();
|
|
42707
|
+
clearInterval(runtimeEventPollTimer);
|
|
42494
42708
|
unsubscribe();
|
|
42495
42709
|
store.close();
|
|
42496
42710
|
}
|
|
@@ -44802,8 +45016,18 @@ class TunnelClient {
|
|
|
44802
45016
|
this.bridgedSockets.clear();
|
|
44803
45017
|
}
|
|
44804
45018
|
send(frame) {
|
|
44805
|
-
|
|
44806
|
-
|
|
45019
|
+
const ws = this.ws;
|
|
45020
|
+
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
45021
|
+
return;
|
|
45022
|
+
if (Number(ws.bufferedAmount ?? 0) > MAX_TUNNEL_BUFFERED_AMOUNT) {
|
|
45023
|
+
this.disconnectActiveConnection(ws, this.connectionGeneration, { reason: "relay outbound buffer limit exceeded" }, true);
|
|
45024
|
+
return;
|
|
45025
|
+
}
|
|
45026
|
+
try {
|
|
45027
|
+
ws.send(encodeFrame(frame));
|
|
45028
|
+
} catch {
|
|
45029
|
+
this.disconnectActiveConnection(ws, this.connectionGeneration, { reason: "relay send failed" }, true);
|
|
45030
|
+
}
|
|
44807
45031
|
}
|
|
44808
45032
|
handleFrame(frame) {
|
|
44809
45033
|
switch (frame.type) {
|
|
@@ -44838,11 +45062,23 @@ class TunnelClient {
|
|
|
44838
45062
|
break;
|
|
44839
45063
|
case "http_req_chunk": {
|
|
44840
45064
|
const pending2 = this.pendingHttp.get(frame.id);
|
|
45065
|
+
if (!pending2)
|
|
45066
|
+
break;
|
|
44841
45067
|
try {
|
|
44842
|
-
pending2
|
|
44843
|
-
|
|
44844
|
-
|
|
44845
|
-
|
|
45068
|
+
if (!pending2.body)
|
|
45069
|
+
throw new Error("body chunk received for bodyless request");
|
|
45070
|
+
const chunk = fromB64(frame.dataB64);
|
|
45071
|
+
pending2.receivedBytes += chunk.byteLength;
|
|
45072
|
+
if (pending2.receivedBytes > MAX_HTTP_REQUEST_BODY_BYTES) {
|
|
45073
|
+
throw new Error("relay HTTP request body limit exceeded");
|
|
45074
|
+
}
|
|
45075
|
+
pending2.bodyController?.enqueue(chunk);
|
|
45076
|
+
this.startPendingHttp(frame.id, pending2);
|
|
45077
|
+
} catch {
|
|
45078
|
+
pending2.abort.abort();
|
|
45079
|
+
this.pendingHttp.delete(frame.id);
|
|
45080
|
+
throw new Error("invalid or oversized relay HTTP request body");
|
|
45081
|
+
}
|
|
44846
45082
|
break;
|
|
44847
45083
|
}
|
|
44848
45084
|
case "http_req_end": {
|
|
@@ -44873,6 +45109,12 @@ class TunnelClient {
|
|
|
44873
45109
|
if (!bridged)
|
|
44874
45110
|
break;
|
|
44875
45111
|
if (!bridged.opened) {
|
|
45112
|
+
bridged.bufferedBytes += frame.text === undefined ? Math.floor((frame.dataB64 ?? "").length * 3 / 4) : Buffer.byteLength(frame.text, "utf8");
|
|
45113
|
+
if (bridged.bufferedBytes > MAX_PREOPEN_WEBSOCKET_BYTES) {
|
|
45114
|
+
this.bridgedSockets.delete(frame.id);
|
|
45115
|
+
bridged.ws.close(1009, "pre-open buffer limit exceeded");
|
|
45116
|
+
throw new Error("bridged WebSocket pre-open buffer limit exceeded");
|
|
45117
|
+
}
|
|
44876
45118
|
bridged.buffer.push(frame);
|
|
44877
45119
|
break;
|
|
44878
45120
|
}
|
|
@@ -44892,6 +45134,11 @@ class TunnelClient {
|
|
|
44892
45134
|
}
|
|
44893
45135
|
}
|
|
44894
45136
|
startHttpRequest(frame) {
|
|
45137
|
+
if (this.pendingHttp.has(frame.id))
|
|
45138
|
+
throw new Error("duplicate relay HTTP request id");
|
|
45139
|
+
if (this.pendingHttp.size >= MAX_IN_FLIGHT_HTTP_REQUESTS) {
|
|
45140
|
+
throw new Error("too many in-flight relay HTTP requests");
|
|
45141
|
+
}
|
|
44895
45142
|
const abort = new AbortController;
|
|
44896
45143
|
const headers = new Headers;
|
|
44897
45144
|
for (const [name, value] of frame.headers)
|
|
@@ -44903,7 +45150,8 @@ class TunnelClient {
|
|
|
44903
45150
|
method: frame.method,
|
|
44904
45151
|
path: frame.path,
|
|
44905
45152
|
headers,
|
|
44906
|
-
started: false
|
|
45153
|
+
started: false,
|
|
45154
|
+
receivedBytes: 0
|
|
44907
45155
|
};
|
|
44908
45156
|
if (frame.hasBody) {
|
|
44909
45157
|
pending2.body = new ReadableStream({
|
|
@@ -44964,6 +45212,11 @@ class TunnelClient {
|
|
|
44964
45212
|
}
|
|
44965
45213
|
}
|
|
44966
45214
|
openBridgedSocket(id, path, headers) {
|
|
45215
|
+
if (this.bridgedSockets.has(id))
|
|
45216
|
+
throw new Error("duplicate bridged WebSocket id");
|
|
45217
|
+
if (this.bridgedSockets.size >= MAX_BRIDGED_SOCKETS) {
|
|
45218
|
+
throw new Error("too many bridged WebSockets");
|
|
45219
|
+
}
|
|
44967
45220
|
const wsOrigin = this.opts.targetOrigin.replace(/^http/, "ws");
|
|
44968
45221
|
let local;
|
|
44969
45222
|
try {
|
|
@@ -44980,7 +45233,7 @@ class TunnelClient {
|
|
|
44980
45233
|
});
|
|
44981
45234
|
return;
|
|
44982
45235
|
}
|
|
44983
|
-
const bridged = { ws: local, opened: false, buffer: [] };
|
|
45236
|
+
const bridged = { ws: local, opened: false, buffer: [], bufferedBytes: 0 };
|
|
44984
45237
|
this.bridgedSockets.set(id, bridged);
|
|
44985
45238
|
local.onopen = () => {
|
|
44986
45239
|
bridged.opened = true;
|
|
@@ -44988,6 +45241,7 @@ class TunnelClient {
|
|
|
44988
45241
|
for (const frame of bridged.buffer)
|
|
44989
45242
|
this.deliverToLocal(local, frame);
|
|
44990
45243
|
bridged.buffer = [];
|
|
45244
|
+
bridged.bufferedBytes = 0;
|
|
44991
45245
|
};
|
|
44992
45246
|
local.onmessage = (event) => {
|
|
44993
45247
|
if (typeof event.data === "string") {
|
|
@@ -45019,11 +45273,14 @@ class TunnelClient {
|
|
|
45019
45273
|
local.send(fromB64(frame.dataB64));
|
|
45020
45274
|
}
|
|
45021
45275
|
}
|
|
45022
|
-
var MAX_WS_UPGRADE_HEADER_BYTES, WS_PROTOCOL_TOKEN, DEFAULT_MIN_RECONNECT_MS = 1000, DEFAULT_MAX_RECONNECT_MS = 30000, RECONNECT_JITTER_RATIO = 0.2, LIVENESS_INTERVALS = 3, noop = () => {}, silentLogger;
|
|
45276
|
+
var MAX_WS_UPGRADE_HEADER_BYTES, WS_PROTOCOL_TOKEN, DEFAULT_MIN_RECONNECT_MS = 1000, DEFAULT_MAX_RECONNECT_MS = 30000, MAX_IN_FLIGHT_HTTP_REQUESTS = 128, MAX_BRIDGED_SOCKETS = 128, MAX_HTTP_REQUEST_BODY_BYTES, MAX_PREOPEN_WEBSOCKET_BYTES, MAX_TUNNEL_BUFFERED_AMOUNT, RECONNECT_JITTER_RATIO = 0.2, LIVENESS_INTERVALS = 3, noop = () => {}, silentLogger;
|
|
45023
45277
|
var init_tunnel_client = __esm(() => {
|
|
45024
45278
|
init_relay_protocol();
|
|
45025
45279
|
MAX_WS_UPGRADE_HEADER_BYTES = 32 * 1024;
|
|
45026
45280
|
WS_PROTOCOL_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
45281
|
+
MAX_HTTP_REQUEST_BODY_BYTES = 16 * 1024 * 1024;
|
|
45282
|
+
MAX_PREOPEN_WEBSOCKET_BYTES = 1024 * 1024;
|
|
45283
|
+
MAX_TUNNEL_BUFFERED_AMOUNT = 8 * 1024 * 1024;
|
|
45027
45284
|
silentLogger = { info: noop, warn: noop, error: noop };
|
|
45028
45285
|
});
|
|
45029
45286
|
|
|
@@ -47332,4 +47589,4 @@ switch (command) {
|
|
|
47332
47589
|
}
|
|
47333
47590
|
}
|
|
47334
47591
|
|
|
47335
|
-
//# debugId=
|
|
47592
|
+
//# debugId=A95E28BED5799E3A64756E2164756E21
|