instar 0.28.1 → 0.28.2

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 (32) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +42 -3
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/lifeline/ServerSupervisor.d.ts.map +1 -1
  6. package/dist/lifeline/ServerSupervisor.js +31 -0
  7. package/dist/lifeline/ServerSupervisor.js.map +1 -1
  8. package/dist/lifeline/TelegramLifeline.d.ts +8 -0
  9. package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
  10. package/dist/lifeline/TelegramLifeline.js +115 -6
  11. package/dist/lifeline/TelegramLifeline.js.map +1 -1
  12. package/dist/messaging/SpawnRequestManager.d.ts +16 -0
  13. package/dist/messaging/SpawnRequestManager.d.ts.map +1 -1
  14. package/dist/messaging/SpawnRequestManager.js +63 -5
  15. package/dist/messaging/SpawnRequestManager.js.map +1 -1
  16. package/dist/server/AgentServer.d.ts +5 -0
  17. package/dist/server/AgentServer.d.ts.map +1 -1
  18. package/dist/server/AgentServer.js +1 -0
  19. package/dist/server/AgentServer.js.map +1 -1
  20. package/dist/server/routes.d.ts +7 -0
  21. package/dist/server/routes.d.ts.map +1 -1
  22. package/dist/server/routes.js +85 -15
  23. package/dist/server/routes.js.map +1 -1
  24. package/dist/threadline/AgentTrustManager.d.ts +2 -0
  25. package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
  26. package/dist/threadline/AgentTrustManager.js +5 -3
  27. package/dist/threadline/AgentTrustManager.js.map +1 -1
  28. package/dist/threadline/mcp-stdio-entry.js +3 -2
  29. package/dist/threadline/mcp-stdio-entry.js.map +1 -1
  30. package/package.json +1 -1
  31. package/src/data/builtin-manifest.json +48 -48
  32. package/upgrades/0.28.2.md +29 -0
@@ -7124,6 +7124,28 @@ export function createRoutes(ctx) {
7124
7124
  }
7125
7125
  const accepted = await ctx.messageRouter.relay(envelope, 'agent');
7126
7126
  if (accepted) {
7127
+ const senderAgent = envelope.message?.from?.agent;
7128
+ console.log(`[relay-agent] Accepted message from ${senderAgent ?? 'unknown'} (thread: ${envelope.message?.threadId ?? 'none'}, id: ${envelope.message?.id ?? 'none'})`);
7129
+ // Check if this message resolves a pending waitForReply request.
7130
+ // Local delivery bypasses the relay client's gate-passed event, so we
7131
+ // must check reply waiters here directly.
7132
+ if (senderAgent && ctx.threadlineReplyWaiters.size > 0) {
7133
+ let textContent;
7134
+ const body = envelope.message?.body;
7135
+ if (typeof body === 'string')
7136
+ textContent = body;
7137
+ else if (typeof body === 'object' && body !== null) {
7138
+ textContent = String(body.content ?? body.text ?? JSON.stringify(body));
7139
+ }
7140
+ if (textContent) {
7141
+ const isAutoAck = textContent.startsWith('Message received.') || textContent.startsWith('Message received,');
7142
+ const waiter = ctx.threadlineReplyWaiters.get(senderAgent);
7143
+ if (waiter && !isAutoAck) {
7144
+ console.log(`[relay-agent] Resolved reply waiter for ${senderAgent}`);
7145
+ waiter.resolve(textContent);
7146
+ }
7147
+ }
7148
+ }
7127
7149
  // If the message has a threadId and we have a ThreadlineRouter,
7128
7150
  // route it through the threadline pipeline for session resume/spawn.
7129
7151
  if (ctx.threadlineRouter && envelope.message?.threadId) {
@@ -7584,6 +7606,27 @@ export function createRoutes(ctx) {
7584
7606
  },
7585
7607
  });
7586
7608
  });
7609
+ // ── Threadline Reply Waiter ─────────────────────────────────────────
7610
+ // Waits for an incoming reply from a specific agent on a specific thread.
7611
+ // Used by the relay-send endpoint when waitForReply is true.
7612
+ function waitForThreadlineReply(routeCtx, senderAgent, _threadId, timeoutSec) {
7613
+ const timeout = Math.min(Math.max(timeoutSec ?? 120, 5), 300) * 1000; // 5s–300s, default 120s
7614
+ return new Promise((resolve) => {
7615
+ const timer = setTimeout(() => {
7616
+ routeCtx.threadlineReplyWaiters.delete(senderAgent);
7617
+ resolve(null);
7618
+ }, timeout);
7619
+ routeCtx.threadlineReplyWaiters.set(senderAgent, {
7620
+ resolve: (reply) => {
7621
+ clearTimeout(timer);
7622
+ routeCtx.threadlineReplyWaiters.delete(senderAgent);
7623
+ resolve(reply);
7624
+ },
7625
+ threadId: _threadId,
7626
+ timer,
7627
+ });
7628
+ });
7629
+ }
7587
7630
  // ── Threadline Relay Send ────────────────────────────────────────────
7588
7631
  // Used by the MCP server's threadline_send tool to route messages through
7589
7632
  // the relay WebSocket. Tries local delivery first for co-located agents,
@@ -7592,7 +7635,7 @@ export function createRoutes(ctx) {
7592
7635
  // HTTP endpoint.
7593
7636
  router.post('/threadline/relay-send', async (req, res) => {
7594
7637
  const relayClient = ctx.threadlineRelayClient;
7595
- const { targetAgent, message, threadId } = req.body;
7638
+ const { targetAgent, message, threadId, waitForReply, timeoutSeconds } = req.body;
7596
7639
  if (!targetAgent || !message) {
7597
7640
  res.status(400).json({ success: false, error: 'Missing required fields: targetAgent, message' });
7598
7641
  return;
@@ -7673,13 +7716,26 @@ export function createRoutes(ctx) {
7673
7716
  });
7674
7717
  if (localResp.ok) {
7675
7718
  console.log(`[relay-send] Local delivery to ${localTarget.name}:${localTarget.port} (thread: ${effectiveThreadId})`);
7676
- res.json({
7677
- success: true,
7678
- messageId: msgId,
7679
- threadId: effectiveThreadId,
7680
- resolvedAgent: localTarget.name,
7681
- deliveryPath: 'local',
7682
- });
7719
+ if (waitForReply) {
7720
+ const reply = await waitForThreadlineReply(ctx, localTarget.name, effectiveThreadId, timeoutSeconds);
7721
+ res.json({
7722
+ success: true,
7723
+ messageId: msgId,
7724
+ threadId: effectiveThreadId,
7725
+ resolvedAgent: localTarget.name,
7726
+ deliveryPath: 'local',
7727
+ reply,
7728
+ });
7729
+ }
7730
+ else {
7731
+ res.json({
7732
+ success: true,
7733
+ messageId: msgId,
7734
+ threadId: effectiveThreadId,
7735
+ resolvedAgent: localTarget.name,
7736
+ deliveryPath: 'local',
7737
+ });
7738
+ }
7683
7739
  return;
7684
7740
  }
7685
7741
  // Local delivery failed — fall through to relay
@@ -7712,13 +7768,27 @@ export function createRoutes(ctx) {
7712
7768
  return;
7713
7769
  }
7714
7770
  const relayMsgId = relayClient.sendAuto(resolvedId, message, threadId);
7715
- res.json({
7716
- success: true,
7717
- messageId: relayMsgId,
7718
- threadId: threadId ?? relayMsgId,
7719
- resolvedAgent: resolvedId,
7720
- deliveryPath: 'relay',
7721
- });
7771
+ const effectiveRelayThreadId = threadId ?? relayMsgId;
7772
+ if (waitForReply) {
7773
+ const reply = await waitForThreadlineReply(ctx, resolvedId, effectiveRelayThreadId, timeoutSeconds);
7774
+ res.json({
7775
+ success: true,
7776
+ messageId: relayMsgId,
7777
+ threadId: effectiveRelayThreadId,
7778
+ resolvedAgent: resolvedId,
7779
+ deliveryPath: 'relay',
7780
+ reply,
7781
+ });
7782
+ }
7783
+ else {
7784
+ res.json({
7785
+ success: true,
7786
+ messageId: relayMsgId,
7787
+ threadId: effectiveRelayThreadId,
7788
+ resolvedAgent: resolvedId,
7789
+ deliveryPath: 'relay',
7790
+ });
7791
+ }
7722
7792
  }
7723
7793
  catch (err) {
7724
7794
  res.status(500).json({