instar 1.3.166 → 1.3.168

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsSH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqwDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA6xPtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuSH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA+wDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqzPtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -61,6 +61,7 @@ import { SessionMonitor } from '../monitoring/SessionMonitor.js';
61
61
  import { SessionRecovery } from '../monitoring/SessionRecovery.js';
62
62
  import { MultiMachineCoordinator } from '../core/MultiMachineCoordinator.js';
63
63
  import { isRemotelyHandled } from '../core/SessionRouter.js';
64
+ import { formatForwardedTopicContext } from '../core/ForwardedTopicContext.js';
64
65
  import { resolveAdvertisedMeshUrl, advertiseSelfMeshUrl } from '../core/MeshUrlAdvertiser.js';
65
66
  import { GitSyncManager } from '../core/GitSync.js';
66
67
  import { RegistrySyncDebouncer } from '../core/RegistrySyncDebouncer.js';
@@ -315,6 +316,11 @@ let _sessionPoolStage = () => 'dark';
315
316
  * (forward/spawn on another machine → must NOT also dispatch locally) from a
316
317
  * self placement. Set once in startServer()'s mesh block. */
317
318
  let _meshSelfId = null;
319
+ /** Resolve the current router (Telegram-owning lease holder)'s base URL, or null if
320
+ * this machine IS the router / none is known. Used by the owner-side resume to fetch
321
+ * a moved topic's prior history from the router (bug #2). Set in the mesh block where
322
+ * the peer-URL resolver + coordinator are in scope. */
323
+ let _resolveRouterUrl = null;
318
324
  /** Multi-Machine Session Pool §L4: per-topic placement pin store ("move this to <nickname>"). */
319
325
  let _topicPinStore = null;
320
326
  /** Recognize + apply a "move/run this on <nickname>" relocation on inbound; returns handled=true when the message WAS a relocation command (so it must not also be dispatched). */
@@ -350,7 +356,7 @@ let _slackAdapter = null;
350
356
  // Null until startServer constructs it; the Telegram /restart handler falls
351
357
  // back to the inline kill+respawn path when null (e.g. early in boot).
352
358
  let _sessionRefresh = null;
353
- async function spawnSessionForTopic(sessionManager, telegram, sessionName, topicId, latestMessage, topicMemory, userProfile) {
359
+ async function spawnSessionForTopic(sessionManager, telegram, sessionName, topicId, latestMessage, topicMemory, userProfile, precomputedContext) {
354
360
  const msg = latestMessage || 'Session started — send a message to continue.';
355
361
  // If memory is elevated/critical and we have the reaper, try to free memory
356
362
  // by cleaning orphans before spawning. Interactive sessions are NEVER blocked
@@ -367,10 +373,14 @@ async function spawnSessionForTopic(sessionManager, telegram, sessionName, topic
367
373
  }
368
374
  }
369
375
  }
370
- let contextContent = '';
376
+ // bug #2: a session MOVED here by the session pool has no local history (this
377
+ // machine never polled the topic; its TopicMemory has no rows). The router relays
378
+ // the prior conversation as precomputedContext — use it verbatim and skip the
379
+ // (empty) local sources, so a moved session continues instead of starting blank.
380
+ let contextContent = precomputedContext ?? '';
371
381
  // Prefer TopicMemory (SQLite-backed, with summaries) over raw JSONL scan
372
382
  let usedFallback = false;
373
- if (topicMemory?.isReady()) {
383
+ if (!contextContent && topicMemory?.isReady()) {
374
384
  try {
375
385
  contextContent = topicMemory.formatContextForSession(topicId, 50);
376
386
  }
@@ -8687,7 +8697,28 @@ export async function startServer(options) {
8687
8697
  ? String(cmd.payload.text)
8688
8698
  : undefined;
8689
8699
  const sessionName = tg.getSessionForTopic(topicId) ?? `topic-${topicId}`;
8690
- void spawnSessionForTopic(sessionManager, tg, sessionName, topicId, text, undefined, undefined)
8700
+ // bug #2: fetch the prior conversation from the router (this machine's local
8701
+ // history for the topic is empty) so the moved session continues with context
8702
+ // instead of starting blank. Best-effort — on any failure we spawn without it.
8703
+ void (async () => {
8704
+ let movedContext;
8705
+ try {
8706
+ const url = _resolveRouterUrl?.() ?? null;
8707
+ if (url) {
8708
+ const resp = await fetch(`${url}/telegram/topics/${topicId}/messages?limit=50`, {
8709
+ headers: { 'Authorization': `Bearer ${config.authToken}` },
8710
+ });
8711
+ if (resp.ok) {
8712
+ const j = (await resp.json());
8713
+ movedContext = formatForwardedTopicContext(j.messages, tg.getTopicName?.(topicId) ?? undefined) || undefined;
8714
+ }
8715
+ }
8716
+ }
8717
+ catch {
8718
+ // @silent-fallback-ok — cross-machine context relay is best-effort
8719
+ }
8720
+ return spawnSessionForTopic(sessionManager, tg, sessionName, topicId, text, undefined, undefined, movedContext);
8721
+ })()
8691
8722
  .then((name) => {
8692
8723
  tg.registerTopicSession(topicId, name, sessionName);
8693
8724
  console.log(pc.green(` [session-pool] owner-side resume for forwarded topic ${topicId} → ${name}`));
@@ -8757,6 +8788,10 @@ export async function startServer(options) {
8757
8788
  });
8758
8789
  const peerUrl = (machineId) => meshIdMgr.getActiveMachines().find((m) => m.machineId === machineId)?.entry.lastKnownUrl ?? null;
8759
8790
  _meshSelfId = meshSelfId;
8791
+ _resolveRouterUrl = () => {
8792
+ const h = coordinator.getSyncStatus().leaseHolder;
8793
+ return h && h !== meshSelfId ? peerUrl(h) : null;
8794
+ };
8760
8795
  // This machine participates in the session pool, so a read-only standby may
8761
8796
  // persist the PER-SESSION state of sessions it's handed (the pool's owner-side
8762
8797
  // resume only fires for CAS-confirmed owned sessions, and only past 'dark').