instar 0.28.88 → 0.28.90

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/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +91 -17
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/SessionRefresh.d.ts +108 -0
  5. package/dist/core/SessionRefresh.d.ts.map +1 -0
  6. package/dist/core/SessionRefresh.js +157 -0
  7. package/dist/core/SessionRefresh.js.map +1 -0
  8. package/dist/monitoring/CommitmentTracker.d.ts +65 -2
  9. package/dist/monitoring/CommitmentTracker.d.ts.map +1 -1
  10. package/dist/monitoring/CommitmentTracker.js +113 -0
  11. package/dist/monitoring/CommitmentTracker.js.map +1 -1
  12. package/dist/server/AgentServer.d.ts +6 -0
  13. package/dist/server/AgentServer.d.ts.map +1 -1
  14. package/dist/server/AgentServer.js +3 -0
  15. package/dist/server/AgentServer.js.map +1 -1
  16. package/dist/server/routes.d.ts +10 -0
  17. package/dist/server/routes.d.ts.map +1 -1
  18. package/dist/server/routes.js +92 -1
  19. package/dist/server/routes.js.map +1 -1
  20. package/dist/threadline/SalienceGate.d.ts +87 -0
  21. package/dist/threadline/SalienceGate.d.ts.map +1 -0
  22. package/dist/threadline/SalienceGate.js +100 -0
  23. package/dist/threadline/SalienceGate.js.map +1 -0
  24. package/dist/threadline/ThreadResumeMap.d.ts +14 -0
  25. package/dist/threadline/ThreadResumeMap.d.ts.map +1 -1
  26. package/dist/threadline/ThreadResumeMap.js.map +1 -1
  27. package/dist/threadline/ThreadlineMCPServer.d.ts +4 -0
  28. package/dist/threadline/ThreadlineMCPServer.d.ts.map +1 -1
  29. package/dist/threadline/ThreadlineMCPServer.js +10 -0
  30. package/dist/threadline/ThreadlineMCPServer.js.map +1 -1
  31. package/dist/threadline/ThreadlineRouter.d.ts +13 -0
  32. package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
  33. package/dist/threadline/ThreadlineRouter.js +47 -0
  34. package/dist/threadline/ThreadlineRouter.js.map +1 -1
  35. package/dist/threadline/TopicLinkageHandler.d.ts +161 -0
  36. package/dist/threadline/TopicLinkageHandler.d.ts.map +1 -0
  37. package/dist/threadline/TopicLinkageHandler.js +518 -0
  38. package/dist/threadline/TopicLinkageHandler.js.map +1 -0
  39. package/dist/threadline/mcp-stdio-entry.js +5 -0
  40. package/dist/threadline/mcp-stdio-entry.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/data/builtin-manifest.json +47 -47
  43. package/upgrades/0.28.89.md +68 -0
  44. package/upgrades/0.28.90.md +52 -0
  45. package/upgrades/side-effects/session-self-refresh.md +382 -0
  46. package/upgrades/side-effects/thread-topic-linkage.md +243 -0
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiQH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAg4CD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAi5JtE;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;AAiQH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAw4CD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA68JtE;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"}
@@ -270,6 +270,11 @@ let _projectDir = process.cwd();
270
270
  let _sharedIntelligence = null;
271
271
  let _selfKnowledgeTree = null;
272
272
  let _slackAdapter = null;
273
+ // SessionRefresh — agent-initiated respawn. Module-scope so onRestartSession
274
+ // (defined outside startServer) can delegate to it once startServer wires it.
275
+ // Null until startServer constructs it; the Telegram /restart handler falls
276
+ // back to the inline kill+respawn path when null (e.g. early in boot).
277
+ let _sessionRefresh = null;
273
278
  async function spawnSessionForTopic(sessionManager, telegram, sessionName, topicId, latestMessage, topicMemory, userProfile) {
274
279
  const msg = latestMessage || 'Session started — send a message to continue.';
275
280
  // If memory is elevated/critical and we have the reaper, try to free memory
@@ -538,25 +543,28 @@ function wireTelegramCallbacks(telegram, sessionManager, state, quotaTracker, ac
538
543
  return false;
539
544
  }
540
545
  };
541
- // /restart — kill session and respawn
546
+ // /restart — kill session and respawn. Delegates to SessionRefresh, the
547
+ // consolidated lifecycle owner: it routes the kill through
548
+ // sessionManager.killSession (which fires the kill hook so the UUID
549
+ // listener persists session.claudeSessionId), then spawns a fresh tmux
550
+ // running `claude --resume <uuid>`. Includes the rate guard against
551
+ // infinite-respawn loops.
552
+ //
553
+ // If SessionRefresh isn't wired yet (very narrow early-boot window
554
+ // before startServer reaches the construction point), we no-op with a
555
+ // warning instead of falling back to a broken inline path — the
556
+ // pre-PR inline kill bypassed sessionManager.killSession and so the
557
+ // kill hook never fired, meaning resume UUIDs were silently dropped.
558
+ // Routing exclusively through SessionRefresh fixes that latent issue.
542
559
  telegram.onRestartSession = async (sessionName, topicId) => {
543
- // Save resume UUID before killing so the new session can --resume
544
- if (_topicResumeMap) {
545
- try {
546
- const uuid = _topicResumeMap.findUuidForSession(sessionName);
547
- if (uuid) {
548
- _topicResumeMap.save(topicId, uuid, sessionName);
549
- }
550
- }
551
- catch { /* best effort */ }
560
+ if (!_sessionRefresh) {
561
+ console.warn(`[telegram /restart] SessionRefresh not yet wired; deferring restart for sessionName=${sessionName} topicId=${topicId}`);
562
+ return;
552
563
  }
553
- // Kill existing session
554
- try {
555
- execFileSync(detectTmuxPath(), ['kill-session', '-t', `=${sessionName}`], { stdio: 'ignore' });
564
+ const result = await _sessionRefresh.refreshSession({ sessionName, reason: 'telegram-/restart' });
565
+ if (!result.ok) {
566
+ console.warn(`[telegram /restart] SessionRefresh refused sessionName=${sessionName} code=${result.code}`);
556
567
  }
557
- catch { /* may already be dead */ }
558
- // Respawn with thread history
559
- await respawnSessionForTopic(sessionManager, telegram, sessionName, topicId, undefined, topicMemory);
560
568
  };
561
569
  // /sessions — list running sessions
562
570
  telegram.onListSessions = () => {
@@ -5132,6 +5140,50 @@ export async function startServer(options) {
5132
5140
  // Threadline Router — handles threaded cross-agent conversations via relay
5133
5141
  const threadlineRouter = new ThreadlineRouter(messageRouter, spawnManager, threadResumeMap, messageStore, { localAgent: config.projectName, localMachine: os.hostname() }, null, // autonomyGate
5134
5142
  messageDelivery);
5143
+ // Topic linkage handler — Per THREAD-TOPIC-LINKAGE-SPEC.md.
5144
+ // Ties threadline conversations to the originating Telegram topic so
5145
+ // replies route back to the topic session instead of a sibling worker.
5146
+ // commitmentTracker + telegram are constructed earlier in this file and
5147
+ // are guaranteed in scope by this point; the handler is wired into the
5148
+ // router immediately.
5149
+ const { SalienceGate } = await import('../threadline/SalienceGate.js');
5150
+ const { TopicLinkageHandler } = await import('../threadline/TopicLinkageHandler.js');
5151
+ const salienceGate = new SalienceGate(); // fallback-only for v1; spec §5.4
5152
+ let topicLinkageHandler = null;
5153
+ if (commitmentTracker) {
5154
+ topicLinkageHandler = new TopicLinkageHandler({
5155
+ topicResumeMap: _topicResumeMap,
5156
+ threadResumeMap,
5157
+ commitmentTracker,
5158
+ salienceGate,
5159
+ messageStore,
5160
+ localAgent: config.projectName,
5161
+ injectIntoSession: (sessionName, text) => {
5162
+ try {
5163
+ sessionManager.injectPasteNotification(sessionName, text);
5164
+ return true;
5165
+ }
5166
+ catch {
5167
+ return false;
5168
+ }
5169
+ },
5170
+ isSessionAlive: (sessionName) => {
5171
+ try {
5172
+ return sessionManager.isSessionAlive(sessionName);
5173
+ }
5174
+ catch {
5175
+ return false;
5176
+ }
5177
+ },
5178
+ sendTelegramToTopic: telegram
5179
+ ? (topicId, text) => telegram.sendToTopic(topicId, text)
5180
+ : null,
5181
+ getSessionForTopic: telegram
5182
+ ? (topicId) => telegram.getSessionForTopic(topicId)
5183
+ : undefined,
5184
+ });
5185
+ threadlineRouter.setTopicLinkageHandler(topicLinkageHandler);
5186
+ }
5135
5187
  // Listener Session Manager — warm session for fast relay responses (Phase 2)
5136
5188
  const listenerManager = config.threadline?.relayEnabled
5137
5189
  ? new ListenerSessionManager(config.stateDir, config.authToken ?? '', config.threadline)
@@ -5809,7 +5861,29 @@ export async function startServer(options) {
5809
5861
  divergenceChecker = undefined;
5810
5862
  }
5811
5863
  }
5812
- const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, semanticMemory, activitySentinel, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, proxyCoordinator, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, workingMemory, taskFlowRegistry, threadlineFlowBridge });
5864
+ // SessionRefresh — agent-initiated session respawn. Requires a Telegram
5865
+ // adapter (v1 scope: Telegram-bound sessions only). The respawner closure
5866
+ // captures `topicMemory` by reference, so even if topicMemory is wired up
5867
+ // after this point it will be resolved at refresh-time.
5868
+ if (telegram) {
5869
+ const { SessionRefresh } = await import('../core/SessionRefresh.js');
5870
+ const telegramRef = telegram; // narrow for closure
5871
+ _sessionRefresh = new SessionRefresh({
5872
+ sessionManager,
5873
+ state,
5874
+ telegram: telegramRef,
5875
+ topicResumeMap: _topicResumeMap,
5876
+ respawner: async (sessionName, topicId, followUpPrompt) => {
5877
+ // killSession (called inside SessionRefresh) has already fired
5878
+ // beforeSessionKill (UUID persisted) and destroyed the tmux
5879
+ // session. respawnSessionForTopic spawns the new tmux running
5880
+ // `claude --resume <uuid>` and registers the topic mapping.
5881
+ await respawnSessionForTopic(sessionManager, telegramRef, sessionName, topicId, followUpPrompt, topicMemory);
5882
+ return telegramRef.getSessionForTopic(topicId) ?? sessionName;
5883
+ },
5884
+ });
5885
+ }
5886
+ const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, semanticMemory, activitySentinel, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, proxyCoordinator, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, workingMemory, taskFlowRegistry, threadlineFlowBridge });
5813
5887
  await server.start();
5814
5888
  void taskFlowSweeper;
5815
5889
  void taskFlowDueWaker;