instar 1.3.207 → 1.3.209

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 (54) hide show
  1. package/dist/commands/init.js +4 -0
  2. package/dist/commands/init.js.map +1 -1
  3. package/dist/commands/server.d.ts.map +1 -1
  4. package/dist/commands/server.js +48 -0
  5. package/dist/commands/server.js.map +1 -1
  6. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  7. package/dist/config/ConfigDefaults.js +13 -0
  8. package/dist/config/ConfigDefaults.js.map +1 -1
  9. package/dist/core/PostUpdateMigrator.d.ts +23 -1
  10. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  11. package/dist/core/PostUpdateMigrator.js +138 -0
  12. package/dist/core/PostUpdateMigrator.js.map +1 -1
  13. package/dist/core/SessionManager.d.ts.map +1 -1
  14. package/dist/core/SessionManager.js +7 -3
  15. package/dist/core/SessionManager.js.map +1 -1
  16. package/dist/core/frameworkSessionLaunch.d.ts.map +1 -1
  17. package/dist/core/frameworkSessionLaunch.js +15 -0
  18. package/dist/core/frameworkSessionLaunch.js.map +1 -1
  19. package/dist/core/types.d.ts +10 -0
  20. package/dist/core/types.d.ts.map +1 -1
  21. package/dist/core/types.js.map +1 -1
  22. package/dist/monitoring/sentinelWiring.d.ts +13 -0
  23. package/dist/monitoring/sentinelWiring.d.ts.map +1 -1
  24. package/dist/monitoring/sentinelWiring.js +44 -1
  25. package/dist/monitoring/sentinelWiring.js.map +1 -1
  26. package/dist/scaffold/templates.d.ts.map +1 -1
  27. package/dist/scaffold/templates.js +6 -0
  28. package/dist/scaffold/templates.js.map +1 -1
  29. package/dist/server/routes.d.ts.map +1 -1
  30. package/dist/server/routes.js +76 -0
  31. package/dist/server/routes.js.map +1 -1
  32. package/dist/threadline/A2ACheckInPolicy.d.ts +50 -0
  33. package/dist/threadline/A2ACheckInPolicy.d.ts.map +1 -0
  34. package/dist/threadline/A2ACheckInPolicy.js +51 -0
  35. package/dist/threadline/A2ACheckInPolicy.js.map +1 -0
  36. package/dist/threadline/A2ACheckInProxy.d.ts +56 -0
  37. package/dist/threadline/A2ACheckInProxy.d.ts.map +1 -0
  38. package/dist/threadline/A2ACheckInProxy.js +53 -0
  39. package/dist/threadline/A2ACheckInProxy.js.map +1 -0
  40. package/dist/threadline/A2ACheckInScheduler.d.ts +77 -0
  41. package/dist/threadline/A2ACheckInScheduler.d.ts.map +1 -0
  42. package/dist/threadline/A2ACheckInScheduler.js +90 -0
  43. package/dist/threadline/A2ACheckInScheduler.js.map +1 -0
  44. package/dist/threadline/A2ACheckInSummarizer.d.ts +48 -0
  45. package/dist/threadline/A2ACheckInSummarizer.d.ts.map +1 -0
  46. package/dist/threadline/A2ACheckInSummarizer.js +64 -0
  47. package/dist/threadline/A2ACheckInSummarizer.js.map +1 -0
  48. package/package.json +1 -1
  49. package/src/data/builtin-manifest.json +64 -64
  50. package/src/scaffold/templates.ts +6 -0
  51. package/upgrades/1.3.208.md +54 -0
  52. package/upgrades/1.3.209.md +66 -0
  53. package/upgrades/side-effects/iris-audit-session-lifecycle.md +146 -0
  54. package/upgrades/side-effects/spinner-immune-liveness.md +122 -0
@@ -3733,6 +3733,82 @@ export function createRoutes(ctx) {
3733
3733
  });
3734
3734
  }, 500);
3735
3735
  });
3736
+ // POST /sessions/restart-all — bulk config-apply restart.
3737
+ //
3738
+ // After a config change (default model, disabled features, a newly-added
3739
+ // hook), running sessions keep their OLD config until they restart — and
3740
+ // Claude Code only loads hooks/settings at session START, so a hook added
3741
+ // mid-session never engages on the live session. Previously the only way to
3742
+ // push every session onto the new config was to wait for the reaper or
3743
+ // refresh each session by hand. This refreshes every running, Telegram-bound
3744
+ // session through SessionRefresh (kill + `claude --resume`, preserving each
3745
+ // conversation), staggered so we don't kill+respawn the whole fleet at once.
3746
+ //
3747
+ // Non-Telegram-bound sessions (Slack, iMessage, headless) are skipped — the
3748
+ // respawn path is topic-routed, the same v1 limitation as /sessions/refresh.
3749
+ router.post('/sessions/restart-all', spawnLimiter, (req, res) => {
3750
+ if (!ctx.sessionRefresh) {
3751
+ res.status(503).json({ error: 'Session refresh not enabled (no Telegram adapter wired)' });
3752
+ return;
3753
+ }
3754
+ const { reason, excludeSession, followUpPrompt } = req.body || {};
3755
+ if (reason !== undefined && (typeof reason !== 'string' || reason.length > 1000)) {
3756
+ res.status(400).json({ error: '"reason" must be a string under 1000 chars' });
3757
+ return;
3758
+ }
3759
+ if (excludeSession !== undefined && (typeof excludeSession !== 'string' || !SESSION_NAME_RE.test(excludeSession))) {
3760
+ res.status(400).json({ error: '"excludeSession" must contain only letters, numbers, hyphens, underscores (max 200)' });
3761
+ return;
3762
+ }
3763
+ if (followUpPrompt !== undefined && (typeof followUpPrompt !== 'string' || followUpPrompt.length > 500_000)) {
3764
+ res.status(400).json({ error: '"followUpPrompt" must be a string under 500KB' });
3765
+ return;
3766
+ }
3767
+ // Snapshot running sessions NOW, before any kills. Filter to Telegram-bound
3768
+ // up front (checking in-memory AND disk, mirroring SessionRefresh's own
3769
+ // resolution) so the "scheduled" list we return is honest — the rest would
3770
+ // only come back not_telegram_bound.
3771
+ const running = ctx.state.listSessions({ status: 'running' });
3772
+ const targets = running
3773
+ .map(s => s.tmuxSession)
3774
+ .filter((name) => !!name && name !== excludeSession)
3775
+ .filter(name => {
3776
+ const topic = ctx.telegram?.getTopicForSession?.(name)
3777
+ ?? ctx.telegram?.resolveTopicForSessionFromDisk?.(name)
3778
+ ?? null;
3779
+ return topic !== null;
3780
+ });
3781
+ res.status(202).json({
3782
+ ok: true,
3783
+ message: 'Bulk restart scheduled',
3784
+ scheduled: targets,
3785
+ count: targets.length,
3786
+ skipped: running.length - targets.length,
3787
+ });
3788
+ // Stagger the refreshes so we don't kill+respawn the whole fleet in one
3789
+ // burst (a tmux storm + a model-load CPU spike). Each refresh is
3790
+ // independent and self-rate-limited inside SessionRefresh, so a repeated
3791
+ // restart-all inside the rate window is harmlessly refused per session.
3792
+ const sessionRefresh = ctx.sessionRefresh;
3793
+ const STAGGER_MS = 750;
3794
+ targets.forEach((sessionName, i) => {
3795
+ setTimeout(() => {
3796
+ sessionRefresh
3797
+ .refreshSession({ sessionName, followUpPrompt, reason: reason ?? 'bulk restart-all (config apply)' })
3798
+ .then(result => {
3799
+ if (!result.ok) {
3800
+ console.warn(`[sessions/restart-all] refused sessionName=${sessionName} code=${result.code} message="${result.message}"`);
3801
+ }
3802
+ else {
3803
+ console.log(`[sessions/restart-all] refreshed sessionName=${sessionName} -> ${result.newSessionName} (topic ${result.topicId})`);
3804
+ }
3805
+ })
3806
+ .catch(err => {
3807
+ console.error(`[sessions/restart-all] unexpected error for sessionName=${sessionName}:`, err);
3808
+ });
3809
+ }, 500 + i * STAGGER_MS);
3810
+ });
3811
+ });
3736
3812
  router.delete('/sessions/:id', async (req, res) => {
3737
3813
  if (!SESSION_NAME_RE.test(req.params.id)) {
3738
3814
  res.status(400).json({ error: 'Invalid session ID format' });