@michengai/dsh-archive-manager 1.1.6 → 1.1.8

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@
4
4
 
5
5
  Published release notes are retained below; new versions are added without removing earlier entries.
6
6
 
7
+ ## 1.1.8 - 2026-10-23
8
+
9
+ - Added primary sidebar navigation entry and dedicated workspace panel: users can now access Archive Manager directly from the first-level sidebar, opening a 960px centered workspace view. The entry can be toggled on or off at any time via the `sidebarEntry` switch in plugin configuration (`plugins.bundle.config` slot).
10
+ - Added toggleable online updates and host-level security locking: added an `onlineUpdate` switch in plugin configuration. Disabling it immediately hides the "Check for updates" button and version badge in the header, and rejects update requests at the endpoint level. Environments requiring security compliance or curated catalog distribution can enforce `updater: false` (or `onlineUpdate: false`) in Cordis patch configuration to disable the updater at startup and lock the UI toggle.
11
+ - Added baseURI dynamic endpoint resolution for reverse proxies: API requests now resolve against document `baseURI` to preserve path prefixes when DSH is hosted under a reverse proxy or subdirectory, preventing 404 errors on update and settings routes.
12
+ - Unified the online feedback button icon to use the host's native `IconEditOutlineRegular`.
13
+
14
+ ## 1.1.7 - 2026-10-22
15
+
16
+ - Fixed session titles or blank-session visibility changing after disabling Archive Manager (#71). The plugin no longer replaces the official projection-cache table; ordinary cache reads and writes remain host-owned.
17
+ - On activation, hand historical plugin checkpoints back to the official cache after checking session identity. Keep newer same-version official projections and official rows with different projection versions. Failed handoffs can retry on later activation; source cache files are retained.
18
+ - Archive and restore now use the official workspace APIs. Archiving an unknown session reports the official error instead of being skipped, and restore no longer reattaches a session that the workspace no longer lists. The plugin no longer blocks the official workspace update from dropping a member that has no path index.
19
+ - Preserve restore wrappers and validation installed before Archive Manager is enabled, and restore the original method and property descriptor on disable.
20
+ - Batch archive and restore share one serial loop. When one session gets an official error, the list or confirmation card keeps that reason and the rest continue. Successful items are not repeated. Batch delete still uses the official scoped call.
21
+ - Batch results no longer show a permanent zero for unprocessed items. The retry count is the failed items, so the organizer summary matches the retry button.
22
+ - Keep only the tombstones and in-flight write barrier needed for permanent deletion. Disabling removes those guards without closing the official cache service. The barrier tracks only tasks that entered through the guards; official cache writes started before activation cannot be reliably drained and may leave an orphan cache row after disabling in an exceptional interleaving. Closing this gap requires host-side write-drain support.
23
+ - Session repair parses individual Zstandard frames using an explicit boundary scanner, ensuring reliable single-frame header extraction and verification across Node 24.22+ and earlier versions.
24
+ - Upgrade note: users who disabled an older version must activate the fixed version at least once to hand off old records. Keys rejected by the official backend, such as IDs containing colons, remain in the legacy domain and return to native host behavior instead of receiving a replacement cache.
25
+
7
26
  ## 1.1.6 - 2026-10-19
8
27
 
9
28
  - Fixed the "Archive all conversations" action appearing in a single session's action menu. The workspace menu context is now recorded only from workspace rows and cleared by session rows, other rows, or empty areas, so a stale workspace binding can no longer leak into a session menu.
@@ -4,6 +4,25 @@
4
4
 
5
5
  以下发布说明会持续保留;新增版本时不再删除较早记录。
6
6
 
7
+ ## 1.1.8 - 2026-10-23
8
+
9
+ - 新增主侧边栏直接导航入口与工作区主面板:支持在主界面一级侧边栏展示归档管理器图标入口,点击可直接切换至专属工作区主面板(960px 居中版心与独立滚动容器);可在插件详情页(`plugins.bundle.config` 槽位)随时开启或关闭 `sidebarEntry` 开关。
10
+ - 新增在线更新控制开关与宿主安全锁定:详情页新增「在线更新」原生开关,关闭后即时隐藏标题区「检查更新」按钮与版本提示徽标,并阻断更新请求;支持面向精选索引或企业合规环境在 Cordis 配置文件中声明 `updater: false`(或 `onlineUpdate: false`)硬锁定,启动时强制禁用且界面开关自动置灰。
11
+ - 支持反向代理与带路径前缀部署:前端 API 请求统一基于页面 `baseURI` 解析动态基准地址,完美适配反向代理路径前缀与二级目录部署,避免反代环境下更新与设置接口 404。
12
+ - 设置页标题栏的在线反馈按钮统一对齐宿主原生 `IconEditOutlineRegular` 图标。
13
+
14
+ ## 1.1.7 - 2026-10-22
15
+
16
+ - 修复停用归档插件后会话标题或空白会话显示异常的问题(#71):插件不再替换官方投影缓存表,日常读写始终由宿主负责。
17
+ - 启用修复版时,将历史插件缓存按会话身份核验后交接至官方缓存;保留官方更新的同版本投影,不覆盖不同投影版本,失败可在后续启用时重试,旧缓存原文件不删除。
18
+ - 归档和恢复改走官方工作区接口。未知会话归档会按官方结果报错,不再静默跳过;恢复不再把已不在工作区记账里的会话按目录挂回去。官方改工作区时丢掉没有路径索引的成员,插件不再拦截。
19
+ - 恢复会话保留启用归档插件前已有的包装和校验,停用后还原原方法及属性描述符。
20
+ - 批量归档和恢复共用同一条串行循环。某一条遇到官方报错时,列表或确认卡片留下这条原因,并继续处理后面的会话;已成功的不会重做。批量删除仍走官方一次作用域接口。
21
+ - 批量结果不再显示恒为零的「未处理」。失败项用重试数量表示,整理面板的计数与重试按钮一致。
22
+ - 保留永久删除所需的墓碑和在途写入屏障,停用只撤回这些守护,不关闭官方缓存服务。屏障仅跟踪经过守护入口的任务;启用前已启动的官方缓存写入无法被可靠排空,极端时序下停用后仍可能留下孤儿缓存行,该缺口需要宿主提供写入排空能力。
23
+ - 会话修复使用显式帧边界扫描解析单帧 Zstandard 数据,确保在 Node 24.22+ 及更早版本下均能可靠提取首帧头部并完成工件校验。
24
+ - 升级说明:曾停用旧版的用户需要至少启用一次修复版以完成交接。官方后端不接受的缓存 key(如含冒号的 ID)保留在旧域,恢复宿主原生行为,不再额外接管。
25
+
7
26
  ## 1.1.6 - 2026-10-19
8
27
 
9
28
  - 修复单条会话的操作菜单错误出现「归档全部会话」的问题:工作区菜单上下文现在只从工作区行记录,点击会话行、其他行或空白区域会立即清空,避免复用上一次的工作区绑定。
package/README.md CHANGED
@@ -95,6 +95,39 @@ dsh plugin --profile web add @michengai/dsh-archive-manager@latest --registry=ht
95
95
 
96
96
  Restart DSH Web, then hard-refresh your browser with `Ctrl+Shift+R`. Open **Settings → Archived sessions** to get started.
97
97
 
98
+ - **Reverse proxy deployment**: Supports hosting DSH behind prefix-stripping reverse proxies (e.g. `/app/dsh/`). API and update endpoints automatically resolve against the page base URI (`document.baseURI`), preventing 404 errors caused by lost prefix segments.
99
+
100
+ ## Plugin Configuration & Toggles
101
+
102
+ The plugin follows standard DSH bundle configuration conventions. Options are located at:
103
+ > **Sidebar → Plugins → Click `@michengai/dsh-archive-manager`** (the host's `plugins.bundle.config` slot).
104
+
105
+ Two native switches are available. Their values are persisted in `archive-manager/settings.json` under your local configuration directory and survive restarts; they are not two equivalent Cordis YAML options. `sidebarEntry` is managed through this UI, while `onlineUpdate` is also subject to the host lock described below:
106
+
107
+ ### 1. Sidebar Entry (`sidebarEntry`)
108
+ - **Default**: Disabled (`false`)
109
+ - **Description**: Displays a persistent **Archived sessions** navigation icon in the host's left primary sidebar.
110
+ - **Effect**:
111
+ - When enabled, clicking the sidebar icon opens the Archive Manager directly in the primary workspace with a **960px centered container** (matching host plugin manager conventions). This eliminates vertical scrolling constraints in narrow settings dialogs;
112
+ - When disabled, unregisters the sidebar entry cleanly (and resets active panel gracefully if currently viewing the panel, preventing blank views);
113
+ - The standard **Settings → Archived sessions** view remains active either way, and state is synchronized live across both entry points.
114
+
115
+ ### 2. Online Updates (`onlineUpdate` / `updater`)
116
+ - **Default**: Enabled (`true`)
117
+ - **Description**: Controls whether the plugin checks for and installs updates from npm.
118
+ - **Effect**:
119
+ - **Dynamic UI Sync**: Disabling the toggle hides the **Check for updates** button and version badge in the header immediately without requiring a full page reload;
120
+ - **Endpoint Guard**: When disabled, the update API route returns `HTTP 403` for all check and install requests, preventing unreviewed updates;
121
+ - **Host / Platform Lock**: For curated plugin indexes (such as VibeDev) or restricted enterprise environments, this can be locked directly via Cordis configuration (bundle patch) without needing UI interaction:
122
+ ```yaml
123
+ - insert:
124
+ - id: ui-workspace-archive-manager
125
+ name: '@michengai/dsh-archive-manager'
126
+ config:
127
+ updater: false # or onlineUpdate: false
128
+ ```
129
+ Once configured, the updater is disabled at startup, the update action stays hidden, and the online-update switch is disabled. The host lock takes precedence over the user's choice in settings.json and cannot be lifted through the UI. Removing the host lock restores the saved user preference.
130
+
98
131
  ## Usage
99
132
 
100
133
  | Goal | Action |
@@ -125,7 +158,7 @@ Compact project groups can be collapsed. Stars and restore/archive icons appear
125
158
 
126
159
  - Use the star on either tab and the **Favorites only** dropdown to find important chats. Favorites persist on the host across archive, restore, and browser changes. Reopen management to see changes made in other pages. Unknown or unreadable sessions retain their stored favorite IDs; cleanup requires confirmed artifact absence.
127
160
  - On Unarchived, enter 1–36,500 whole idle days and preview candidates under the current filters. Deselect individual candidates before confirmation. Favorites, the current chat, running sessions (including subagents), and pending interactions are protected; sessions without a valid activity time are excluded.
128
- - Archive rechecks favorites and activity. Batch archive, restore, and delete report successful, skipped, failed, and remaining items; the first failure stops the batch. Retry only the remainder. Delete retries still require confirmation.
161
+ - Archive rechecks favorites and activity. Batch archive, restore, and delete report progress plus successful, skipped, and failed counts. A failure does not stop the rest; retry only the failed items. Delete retries still require confirmation.
129
162
  - **Undo this archive** restores sessions archived by the current batch, including successful retries. It is available only while the current management page remains open; refreshing or closing clears it. Permanent deletion cannot be undone.
130
163
  - Favorites can still be archived manually. Protection applies to idle cleanup only. There is no scheduled or automatic background cleanup.
131
164
 
@@ -161,6 +194,12 @@ dsh --profile web --dump-config
161
194
 
162
195
  The configuration should include `ui-workspace-archive-manager` and must not disable official `workspace` or `session-projection-cache`. A leftover `archive-manager-host` override can be removed. On current DSH hosts the official `ui-settings-unarchive-sessions` entry is gone, so this plugin no longer disables it (doing so only warned that the patch entry was missing). If your profile's `cordis.patch.yml` still disables `workspace`, `session-projection-cache`, or `ui-workspace`, remove those overrides and restart.
163
196
 
197
+ ### Does disabling the fixed version lose session titles?
198
+
199
+ The fixed version no longer takes over the official projection-cache table. On activation it checks session identity and hands compatible historical plugin checkpoints back to the official cache, retaining the original cache files. **If you disabled an older version, activate the fixed version at least once to perform this handoff**; replacing the package while it stays disabled cannot run the migration.
200
+
201
+ Failed handoffs can retry on later activation. Keys rejected by the official backend, such as session IDs containing colons, remain in the old plugin domain rather than being forced into the official cache. Those sessions return to native host cache behavior; their conversation logs are not deleted. See the [changelog](CHANGELOG.md) for details.
202
+
164
203
  ### How is archiving different from deletion?
165
204
 
166
205
  Archiving puts a conversation away so you can restore it later. **Permanent deletion cannot be undone** and may also remove that session's attachments. It does not delete your project working directory. Deletion requires confirmation.
package/README.ru.md CHANGED
@@ -125,7 +125,7 @@ dsh plugin --profile web add @michengai/dsh-archive-manager@latest --registry=ht
125
125
 
126
126
  - Используйте звезду на любой вкладке и выпадающий список **Только избранное**, чтобы найти важные чаты. Избранное сохраняется на хосте при архивировании, восстановлении и смене браузера. Переоткройте управление, чтобы увидеть изменения, сделанные на других страницах. Неизвестные или нечитаемые сессии сохраняют свои сохранённые ID избранного; очистка требует подтверждённого отсутствия артефакта.
127
127
  - На вкладке **Незаархивированные** введите 1–36 500 целых дней в поле **Дни простоя** и просмотрите кандидатов при текущих фильтрах. Снимите отдельных кандидатов перед подтверждением. Избранное, текущий чат, запущенные сессии (включая субагентов) и ожидающие взаимодействия защищены; сессии без корректного времени активности исключаются.
128
- - Архив повторно проверяет избранное и активность. Пакетное архивирование, восстановление и удаление сообщают об успешных, пропущенных, неудачных и оставшихся элементах; первый сбой останавливает пакет. Повторяйте только оставшиеся элементы. Повторное удаление всё равно требует подтверждения.
128
+ - Архив повторно проверяет избранное и активность. Пакетное архивирование, восстановление и удаление показывают ход и число успешных, пропущенных и неудачных элементов. Ошибка одной записи не останавливает остальные; повтор затрагивает только неудачные. Повторное удаление всё равно требует подтверждения.
129
129
  - **Отменить эту архивацию** восстанавливает сессии, архивированные текущим пакетом, включая успешные повторы. Доступно, пока открыта текущая страница управления; обновление или закрытие очищает его. Постоянное удаление отменить нельзя.
130
130
  - Избранное всё ещё можно архивировать вручную. Защита относится только к очистке неактивных. Плановой или автоматической фоновой очистки нет.
131
131
 
@@ -161,6 +161,12 @@ dsh --profile web --dump-config
161
161
 
162
162
  В конфигурации должен присутствовать `ui-workspace-archive-manager`, и он не должен отключать официальные `workspace` или `session-projection-cache`. Оставшийся override `archive-manager-host` можно удалить. В текущих хостах DSH официальной записи `ui-settings-unarchive-sessions` уже нет, поэтому плагин больше её не отключает (иначе dump-config предупреждает, что запись патча не найдена). Если `cordis.patch.yml` вашего профиля всё ещё отключает `workspace`, `session-projection-cache` или `ui-workspace`, удалите эти override и перезапустите.
163
163
 
164
+ ### Сохраняются ли названия после отключения исправленной версии?
165
+
166
+ Исправленная версия больше не заменяет официальную таблицу кэша проекций. При включении она проверяет идентичность сессии и переносит совместимые старые записи плагина в официальный кэш, сохраняя исходные файлы. **Если старая версия была отключена, исправленную версию нужно включить хотя бы один раз для переноса**; замена пакета в отключённом состоянии не запускает миграцию.
167
+
168
+ Неудачный перенос можно повторить при следующем включении. Ключи, которые официальный backend не принимает (например, ID с двоеточием), остаются в старом домене плагина. Для этих сессий восстанавливается штатное поведение кэша хоста; журналы разговоров не удаляются. Подробности — в [журнале изменений](CHANGELOG.md).
169
+
164
170
  ### Чем архивирование отличается от удаления?
165
171
 
166
172
  Архивирование убирает беседу, чтобы позже её можно было восстановить. **Постоянное удаление отменить нельзя** и оно может также удалить вложения этой сессии. Оно не удаляет рабочую директорию вашего проекта. Удаление требует подтверждения.
package/README.zh-CN.md CHANGED
@@ -99,6 +99,39 @@ dsh plugin --profile web add @michengai/dsh-archive-manager@latest --registry=ht
99
99
 
100
100
  安装后重启 DSH Web,并按 `Ctrl+Shift+R` 硬刷新浏览器。打开「设置 → 归档会话」即可使用。
101
101
 
102
+ - **反向代理部署**:支持将 DSH 部署在带路径前缀的反向代理后面(如 `/app/dsh/`),插件 API 与更新检查端点统一自动按页面基址(`document.baseURI`)相对解析,避免丢失代理路径前缀导致 404。
103
+
104
+ ## 插件配置与可选开关
105
+
106
+ 插件遵循 DSH 官方扩展配置规范,配置项位于:
107
+ > **主界面侧边栏「插件」→ 点击 `@michengai/dsh-archive-manager` 详情页**(对应宿主 `plugins.bundle.config` 槽位)。
108
+
109
+ 此处提供两个原生扁平行开关。界面开关值保存在本地配置 `archive-manager/settings.json` 中,重启后保留;它们不是两个等价的 Cordis YAML 配置项。`sidebarEntry` 只通过此界面管理,`onlineUpdate` 另受下述宿主锁定规则约束:
110
+
111
+ ### 1. 侧边栏入口 (`sidebarEntry`)
112
+ - **默认状态**:关闭(`false`)
113
+ - **功能说明**:在宿主左侧主导航栏增加常驻的 **「归档会话」** 图标入口。
114
+ - **生效效果**:
115
+ - 开启后,在侧边栏点击即可直达归档中心,并在主工作区以 **960px 居中版心**(对齐官方插件管理规范)展开完整大面板,彻底告别在设置弹窗狭窄视口内滚动的局限;
116
+ - 关闭后安全注销侧栏槽位(若当前正停留在归档大面板,会自动安全切回默认视图,防止悬空和白屏);
117
+ - 无论是否开启侧栏入口,DSH 原有的「设置 → 归档会话」入口始终保留,两处界面数据与操作 100% 实时同步。
118
+
119
+ ### 2. 在线更新 (`onlineUpdate` / `updater`)
120
+ - **默认状态**:开启(`true`)
121
+ - **功能说明**:控制是否允许在线检查并安装归档管理器的新版本。
122
+ - **生效效果**:
123
+ - **界面联动**:关闭开关后,归档管理面板标题旁的「检查更新」按钮与版本提示徽标将即时隐藏,无需刷新页面;开启后自动恢复展示;
124
+ - **接口安全拦截**:关闭后,服务端的更新路由对任何版本检查和安装请求均返回 `HTTP 403` 禁用状态,彻底杜绝在插件内安装未审核版本;
125
+ - **宿主/平台级锁定**:面向精选插件索引(如 VibeDev)或企业安全合规环境,支持直接在 Cordis 配置文件(bundle patch)中声明,无需进入界面手动配置:
126
+ ```yaml
127
+ - insert:
128
+ - id: ui-workspace-archive-manager
129
+ name: '@michengai/dsh-archive-manager'
130
+ config:
131
+ updater: false # 或 onlineUpdate: false
132
+ ```
133
+ 配置生效后,更新器在启动时即被禁用,更新入口隐藏,详情页在线更新开关置灰。宿主锁定优先于本地配置中的用户选择,界面不能解除锁定;宿主移除锁定后,重新按已保存的用户选择生效。
134
+
102
135
  ## 使用
103
136
 
104
137
  | 你想做什么 | 操作 |
@@ -125,7 +158,7 @@ dsh plugin --profile web add @michengai/dsh-archive-manager@latest --registry=ht
125
158
 
126
159
  - 在已归档或未归档会话行右侧点击星标,通过收藏下拉菜单中的「只看收藏」找回重要会话。收藏保存在宿主数据中,归档、恢复或更换浏览器不会清除;其他页面修改的收藏可在重新打开管理页后读取。
127
160
  - 在「未归档」设置 1~36500 的整数闲置天数,结合当前项目、搜索、日期和收藏筛选,点击「预览闲置归档」。确认清单允许逐条取消,默认排除收藏、当前打开、正在执行(含子代理)以及等待交互的会话;缺少有效最后活动时间的会话不参与。
128
- - 归档前再次检查收藏和活动状态。批量归档、恢复、删除显示进度与成功/跳过/失败/未处理数量;首个失败后停止,支持只重试剩余项。删除重试仍需确认。
161
+ - 归档前再次检查收藏和活动状态。批量归档、恢复、删除显示进度与成功、跳过、失败数量;某一条失败后继续处理后续,只重试失败项。删除重试仍需确认。
129
162
  - 「撤回本次归档」只恢复最近一批实际归档成功的会话,包括该批重试成功的部分。仅在本次打开管理页期间有效,关闭页面或刷新会清除记录;不会撤回原有归档,也不能恢复永久删除的会话。
130
163
  - 收藏会话仍可手动归档;收藏保护只针对闲置整理。没有定时自动归档,不会在后台自行整理。
131
164
 
@@ -165,6 +198,12 @@ dsh --profile web --dump-config
165
198
 
166
199
  配置中应包含 `ui-workspace-archive-manager`,且不应再禁用官方 `workspace` 或 `session-projection-cache`。若还留着 `archive-manager-host` 的禁用覆盖,可以删掉。当前 DSH 宿主已无官方 `ui-settings-unarchive-sessions` 入口,本插件不再对其 disable(否则 dump-config 会告警条目不存在)。若 profile 的 `cordis.patch.yml` 仍禁用 `workspace`、`session-projection-cache` 或 `ui-workspace`,请移除这些覆盖,再重启。
167
200
 
201
+ ### 从旧版升级后,停用时标题还会丢吗?
202
+
203
+ 修复版不再接管官方投影缓存表。启用时会核验历史插件缓存对应的会话身份,并将可接受的记录交接给官方缓存;旧缓存文件保留,不会自动删除。**之前已停用旧版的用户,需要至少启用一次修复版完成交接**,不能只在禁用状态下替换安装包。
204
+
205
+ 交接失败可在后续启用时重试。官方后端不接受的 key(例如含冒号的会话 ID)不会强行迁入,仍保留在旧插件域;这些会话恢复宿主原生缓存行为,不代表其聊天日志被删除。完整边界见[更新日志](CHANGELOG.zh-CN.md)。
206
+
168
207
  ### 归档和删除有什么区别?
169
208
 
170
209
  归档只是收起会话,可以恢复。**永久删除无法撤销**,并可能一并清理该会话的附件;不会删除你的项目工作目录。删除前会要求确认。
@@ -0,0 +1,32 @@
1
+ function pageBaseHref() {
2
+ const doc = globalThis.document;
3
+ if (typeof doc === "undefined" || doc === null) return void 0;
4
+ const raw = doc.baseURI;
5
+ if (typeof raw !== "string" || raw === "") return void 0;
6
+ try {
7
+ const url = new URL(raw);
8
+ const lastSlash = url.pathname.lastIndexOf("/");
9
+ const lastSegment = url.pathname.slice(lastSlash + 1);
10
+ if (/\.(html?|php|aspx?|jsp)$/i.test(lastSegment)) {
11
+ url.pathname = url.pathname.slice(0, lastSlash + 1);
12
+ } else if (!url.pathname.endsWith("/")) {
13
+ url.pathname += "/";
14
+ }
15
+ return url.href;
16
+ } catch {
17
+ return void 0;
18
+ }
19
+ }
20
+ function resolveApiUrl(path) {
21
+ if (typeof path !== "string" || path.charAt(0) !== "/" || path.charAt(1) === "/") return path;
22
+ const base = pageBaseHref();
23
+ if (base === void 0) return path;
24
+ try {
25
+ return new URL(path.slice(1), base).href;
26
+ } catch {
27
+ return path;
28
+ }
29
+ }
30
+ export {
31
+ resolveApiUrl
32
+ };
@@ -46,18 +46,15 @@ function idleArchiveCandidate(session, { days, now = Date.now(), favorites = /*
46
46
  }
47
47
  async function runSessionBatch(ids, operate, { onProgress, refresh } = {}) {
48
48
  const requested = [...new Set(ids.map(checkedId))];
49
- const result = { requested, succeeded: [], skipped: [], failures: [], unprocessed: [], remaining: [], refreshError: null };
49
+ const result = { requested, succeeded: [], skipped: [], failures: [], remaining: [], refreshError: null };
50
50
  const report = () => onProgress?.({ total: requested.length, done: result.succeeded.length + result.skipped.length + result.failures.length, succeeded: result.succeeded.length, skipped: result.skipped.length, failed: result.failures.length });
51
51
  report();
52
- for (const [index, id] of requested.entries()) {
52
+ for (const id of requested) {
53
53
  try {
54
54
  (await operate(id) ? result.succeeded : result.skipped).push(id);
55
55
  } catch (error) {
56
56
  result.failures.push({ sessionId: id, message: error instanceof Error ? error.message : String(error) });
57
- result.unprocessed = requested.slice(index + 1);
58
- result.remaining = requested.slice(index);
59
- report();
60
- break;
57
+ result.remaining.push(id);
61
58
  }
62
59
  report();
63
60
  }