instar 0.28.77 → 0.28.78

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.
Files changed (46) hide show
  1. package/dashboard/index.html +184 -4
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +46 -2
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/monitoring/TokenLedger.d.ts +39 -0
  6. package/dist/monitoring/TokenLedger.d.ts.map +1 -1
  7. package/dist/monitoring/TokenLedger.js +110 -13
  8. package/dist/monitoring/TokenLedger.js.map +1 -1
  9. package/dist/monitoring/TokenLedgerPoller.d.ts.map +1 -1
  10. package/dist/monitoring/TokenLedgerPoller.js +8 -8
  11. package/dist/monitoring/TokenLedgerPoller.js.map +1 -1
  12. package/dist/server/AgentServer.d.ts +4 -0
  13. package/dist/server/AgentServer.d.ts.map +1 -1
  14. package/dist/server/AgentServer.js +14 -1
  15. package/dist/server/AgentServer.js.map +1 -1
  16. package/dist/server/routes.d.ts +8 -1
  17. package/dist/server/routes.d.ts.map +1 -1
  18. package/dist/server/routes.js +98 -0
  19. package/dist/server/routes.js.map +1 -1
  20. package/dist/threadline/BackfillCore.d.ts +70 -0
  21. package/dist/threadline/BackfillCore.d.ts.map +1 -0
  22. package/dist/threadline/BackfillCore.js +117 -0
  23. package/dist/threadline/BackfillCore.js.map +1 -0
  24. package/dist/threadline/ListenerSessionManager.d.ts +35 -0
  25. package/dist/threadline/ListenerSessionManager.d.ts.map +1 -1
  26. package/dist/threadline/ListenerSessionManager.js +41 -0
  27. package/dist/threadline/ListenerSessionManager.js.map +1 -1
  28. package/dist/threadline/TelegramBridge.d.ts +140 -0
  29. package/dist/threadline/TelegramBridge.d.ts.map +1 -0
  30. package/dist/threadline/TelegramBridge.js +224 -0
  31. package/dist/threadline/TelegramBridge.js.map +1 -0
  32. package/dist/threadline/ThreadlineMCPServer.d.ts.map +1 -1
  33. package/dist/threadline/ThreadlineMCPServer.js +5 -0
  34. package/dist/threadline/ThreadlineMCPServer.js.map +1 -1
  35. package/dist/threadline/ThreadlineObservability.d.ts +95 -0
  36. package/dist/threadline/ThreadlineObservability.d.ts.map +1 -0
  37. package/dist/threadline/ThreadlineObservability.js +310 -0
  38. package/dist/threadline/ThreadlineObservability.js.map +1 -0
  39. package/package.json +1 -1
  40. package/scripts/threadline-bridge-backfill.mjs +379 -0
  41. package/src/data/builtin-manifest.json +47 -47
  42. package/upgrades/0.28.78.md +90 -0
  43. package/upgrades/side-effects/threadline-bridge-backfill.md +203 -0
  44. package/upgrades/side-effects/threadline-observability-tab.md +206 -0
  45. package/upgrades/side-effects/threadline-tg-bridge-module.md +196 -0
  46. package/upgrades/side-effects/token-ledger-bounded-scan.md +230 -0
@@ -4365,6 +4365,43 @@ export function createRoutes(ctx) {
4365
4365
  }
4366
4366
  res.json(ctx.telegramBridgeConfig.getSettings());
4367
4367
  });
4368
+ // ── Threadline observability — read-only views over inbox/outbox/bindings ──
4369
+ router.get('/threadline/observability/threads', (req, res) => {
4370
+ if (!ctx.threadlineObservability) {
4371
+ res.status(503).json({ error: 'Threadline observability not initialized' });
4372
+ return;
4373
+ }
4374
+ const remoteAgent = typeof req.query.remoteAgent === 'string' ? req.query.remoteAgent : undefined;
4375
+ const sinceIso = typeof req.query.since === 'string' ? req.query.since : undefined;
4376
+ const untilIso = typeof req.query.until === 'string' ? req.query.until : undefined;
4377
+ const hasTopicRaw = typeof req.query.hasTopic === 'string' ? req.query.hasTopic : undefined;
4378
+ const hasTopic = hasTopicRaw === 'yes' || hasTopicRaw === 'no' ? hasTopicRaw : undefined;
4379
+ const threads = ctx.threadlineObservability.listThreads({ remoteAgent, sinceIso, untilIso, hasTopic });
4380
+ res.json({ threads, count: threads.length });
4381
+ });
4382
+ router.get('/threadline/observability/threads/:threadId', (req, res) => {
4383
+ if (!ctx.threadlineObservability) {
4384
+ res.status(503).json({ error: 'Threadline observability not initialized' });
4385
+ return;
4386
+ }
4387
+ const detail = ctx.threadlineObservability.getThread(req.params.threadId);
4388
+ if (!detail) {
4389
+ res.status(404).json({ error: 'Thread not found' });
4390
+ return;
4391
+ }
4392
+ res.json(detail);
4393
+ });
4394
+ router.get('/threadline/observability/search', (req, res) => {
4395
+ if (!ctx.threadlineObservability) {
4396
+ res.status(503).json({ error: 'Threadline observability not initialized' });
4397
+ return;
4398
+ }
4399
+ const q = typeof req.query.q === 'string' ? req.query.q : '';
4400
+ const limitRaw = typeof req.query.limit === 'string' ? parseInt(req.query.limit, 10) : 50;
4401
+ const limit = Number.isFinite(limitRaw) && limitRaw > 0 ? Math.min(limitRaw, 200) : 50;
4402
+ const hits = ctx.threadlineObservability.searchMessages(q, limit);
4403
+ res.json({ hits, count: hits.length });
4404
+ });
4368
4405
  router.patch('/threadline/telegram-bridge/config', (req, res) => {
4369
4406
  if (!ctx.telegramBridgeConfig) {
4370
4407
  res.status(503).json({ error: 'Telegram bridge config not initialized' });
@@ -9774,6 +9811,37 @@ export function createRoutes(ctx) {
9774
9811
  : tl?.handled === false ? 'queued (no live session)'
9775
9812
  : 'accepted';
9776
9813
  console.log(`[relay-send] Local delivery to ${localTarget.name}:${localTarget.port} (thread: ${effectiveThreadId}) — ${outcome}`);
9814
+ // Canonical outbox write — single source of truth for outbound messages
9815
+ // across BOTH delivery paths (local + relay). Powers the dashboard
9816
+ // observability tab. Mirrors the inbound canonical write from PR #113.
9817
+ if (ctx.listenerManager) {
9818
+ try {
9819
+ ctx.listenerManager.appendCanonicalOutboxEntry({
9820
+ from: ctx.config.projectName ?? 'self',
9821
+ senderName: ctx.config.projectName ?? 'self',
9822
+ to: localTarget.name,
9823
+ recipientName: localTarget.name,
9824
+ threadId: effectiveThreadId,
9825
+ text: message,
9826
+ messageId: msgId,
9827
+ outcome,
9828
+ });
9829
+ }
9830
+ catch (err) {
9831
+ console.warn(`[relay-send] Canonical outbox append failed (non-fatal): ${err instanceof Error ? err.message : err}`);
9832
+ }
9833
+ }
9834
+ // Mirror outbound into Telegram bridge (relay-only — best effort).
9835
+ if (ctx.telegramBridge) {
9836
+ ctx.telegramBridge.mirrorOutbound({
9837
+ threadId: effectiveThreadId,
9838
+ remoteAgent: localTarget.name,
9839
+ remoteAgentName: localTarget.name,
9840
+ text: message,
9841
+ messageId: msgId,
9842
+ outcome,
9843
+ }).catch(() => { });
9844
+ }
9777
9845
  if (waitForReply) {
9778
9846
  const reply = await waitForThreadlineReply(ctx, localTarget.name, effectiveThreadId, timeoutSeconds);
9779
9847
  res.json({
@@ -9831,6 +9899,36 @@ export function createRoutes(ctx) {
9831
9899
  }
9832
9900
  const relayMsgId = relayClient.sendAuto(resolvedId, message, threadId);
9833
9901
  const effectiveRelayThreadId = threadId ?? relayMsgId;
9902
+ // Canonical outbox write for the relay-delivery path — same shape as the
9903
+ // local-delivery path above, so the observability tab sees both paths.
9904
+ if (ctx.listenerManager) {
9905
+ try {
9906
+ ctx.listenerManager.appendCanonicalOutboxEntry({
9907
+ from: ctx.config.projectName ?? 'self',
9908
+ senderName: ctx.config.projectName ?? 'self',
9909
+ to: resolvedId,
9910
+ recipientName: targetAgent,
9911
+ threadId: effectiveRelayThreadId,
9912
+ text: message,
9913
+ messageId: relayMsgId,
9914
+ outcome: 'relay-sent',
9915
+ });
9916
+ }
9917
+ catch (err) {
9918
+ console.warn(`[relay-send] Canonical outbox append failed (non-fatal): ${err instanceof Error ? err.message : err}`);
9919
+ }
9920
+ }
9921
+ // Mirror outbound into Telegram bridge (relay-only — best effort).
9922
+ if (ctx.telegramBridge) {
9923
+ ctx.telegramBridge.mirrorOutbound({
9924
+ threadId: effectiveRelayThreadId,
9925
+ remoteAgent: resolvedId,
9926
+ remoteAgentName: targetAgent,
9927
+ text: message,
9928
+ messageId: relayMsgId,
9929
+ outcome: 'relay-sent',
9930
+ }).catch(() => { });
9931
+ }
9834
9932
  if (waitForReply) {
9835
9933
  const reply = await waitForThreadlineReply(ctx, resolvedId, effectiveRelayThreadId, timeoutSeconds);
9836
9934
  res.json({