@rsconcept/rstool 0.7.1 → 0.8.0

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 (35) hide show
  1. package/README.md +1 -1
  2. package/docs/CONSTITUENTA.md +1 -1
  3. package/docs/DIAGNOSTICS.md +3 -0
  4. package/docs/MODEL-TESTING.md +1 -1
  5. package/examples/README.md +52 -29
  6. package/examples/build-chocolate-nim-rsform.ts +311 -0
  7. package/examples/chocolate-nim/build-rsform.ts +311 -0
  8. package/examples/chocolate-nim/build-rsmodel.ts +100 -0
  9. package/examples/chocolate-nim/constants.ts +10 -0
  10. package/examples/chocolate-nim/rsform-session.json +778 -0
  11. package/examples/chocolate-nim/rsmodel-session.json +802 -0
  12. package/examples/expression-bank/bank-constituents.ts +370 -0
  13. package/examples/expression-bank/build-rsform.ts +59 -0
  14. package/examples/expression-bank/constants.ts +1 -0
  15. package/examples/expression-bank/rsform-session.json +4006 -0
  16. package/examples/{build-kinship-rsform.ts → kinship/build-rsform.ts} +276 -54
  17. package/examples/{build-kinship-rsmodel.ts → kinship/build-rsmodel.ts} +18 -7
  18. package/examples/kinship/constants.ts +5 -3
  19. package/examples/{kinship-rsmodel-session.json → kinship/rsform-session.json} +614 -92
  20. package/examples/{kinship-rsform-session.json → kinship/rsmodel-session.json} +704 -50
  21. package/examples/kinship/x1-actions.test.ts +2 -1
  22. package/examples/movd/build-rsform.ts +325 -0
  23. package/examples/movd/build-rsmodel.ts +159 -0
  24. package/examples/movd/constants.ts +18 -0
  25. package/examples/movd/rsform-session.json +738 -0
  26. package/examples/movd/rsmodel-session.json +832 -0
  27. package/examples/{build-sample-rsform.ts → sample/build-rsform.ts} +2 -2
  28. package/examples/{build-sample-rsmodel.ts → sample/build-rsmodel.ts} +3 -4
  29. package/examples/template-apply/build-rsform.ts +236 -0
  30. package/examples/template-apply/constants.ts +13 -0
  31. package/examples/template-apply/rsform-session.json +333 -0
  32. package/package.json +14 -8
  33. package/skills/rstool-helper/EXAMPLES.md +2 -2
  34. /package/examples/{sample-rsform-session.json → sample/rsform-session.json} +0 -0
  35. /package/examples/{sample-rsmodel-session.json → sample/rsmodel-session.json} +0 -0
package/README.md CHANGED
@@ -78,7 +78,7 @@ From `rsconcept/rstool` (or run `powershell -File scripts/dev/LocalDevSetup.ps1`
78
78
  - `npm test`
79
79
  - `npm run build` — produce `dist/` via tsdown
80
80
  - `npm run wrapper` — dev stdio wrapper via `tsx`
81
- - `npm run example:client`, `npm run example:build-schema`, `npm run example:build-rsmodel` — see [`examples/README.md`](examples/README.md) for the full list (kinship scripts, session JSON)
81
+ - `npm run example:client`, `npm run example:build-schema`, `npm run example:build-rsmodel` — полный список `example:*` и `kinship:cli` в [`examples/README.md`](examples/README.md)
82
82
 
83
83
  ## Stdio protocol
84
84
 
@@ -42,7 +42,7 @@
42
42
  2. `S1` — `definitionFormal: 'ℬ(X1×X1)'`; конвенция объясняет порядок пары.
43
43
  3. `D#` — проекции и фильтры: `Pr1(S1)`, `Pr2(S1)`, `Fi1[D1](S1)`.
44
44
 
45
- Пример: `examples/build-kinship-rsform.ts`.
45
+ Пример: `examples/kinship/build-rsform.ts`.
46
46
 
47
47
  ## Валидация
48
48
 
@@ -64,8 +64,10 @@
64
64
  - `0x8840 globalNoValue` / `0x8103 calcGlobalMissing` — нет значения в модели.
65
65
  - `0x8841 invalidPropertyUsage` — `Property` использован как вычислимое значение.
66
66
  - `0x8101 setOverflow`, `0x8102 booleanBaseLimit`, `0x8104 iterationsLimit` — выражение слишком дорого вычислять.
67
+ - `0x8100 calcUnknownError` — непредвиденная ошибка вычисления (неверные данные для операции, внутренний сбой).
67
68
  - `0x8105 calcInvalidDebool` — `debool` получил не синглетон.
68
69
  - `0x8106 iterateInfinity`, `0x8107 calculationNotSupported` — конструкция не исполнима в конечной модели.
70
+ - `0x8108 calcInvalidData` — несовместимые значения в runtime (`params`: строковые представления операндов); типично сравнение множества с числом или смешение ступеней в данных модели. Диапазон `from`/`to` — узел операции, где сбой произошёл.
69
71
 
70
72
  ## Типичные ошибки агентов
71
73
 
@@ -75,6 +77,7 @@
75
77
  - Давать логическое тело `term` или нелогическое тело `axiom`/`statement`.
76
78
  - Использовать `R#` в теле результата.
77
79
  - Вычислять производные понятия до привязки данных для базовых.
80
+ - Сравнивать или комбинировать значения несовместимых ступеней в модели (ожидай `0x8108 calcInvalidData`).
78
81
 
79
82
  ## Цикл исправления
80
83
 
@@ -18,7 +18,7 @@
18
18
  Пример формы данных:
19
19
 
20
20
  ```ts
21
- const TUPLE_ID = -111;
21
+ import { TUPLE_ID } from '@rsconcept/domain';
22
22
 
23
23
  tool.setConstituentaValues(sessionId, {
24
24
  items: [
@@ -9,7 +9,7 @@
9
9
  ```bash
10
10
  npm install
11
11
  npm run build # обёртка для скриптов
12
- npm run example:client # и остальные example:* / kinship:cli — см. ниже
12
+ npm run example:client # минимальный цикл API; схемы — см. таблицу ниже
13
13
  ```
14
14
 
15
15
  **После `npm install @rsconcept/rstool`** (нужен `tsx` или аналог):
@@ -18,42 +18,65 @@ npm run example:client # и остальные example:* / kinship:cli — см.
18
18
  npx tsx node_modules/@rsconcept/rstool/examples/agent-client.ts
19
19
  ```
20
20
 
21
- Скрипты пишут JSON рядом с собой в `examples/`; запускайте из корня пакета (каталог, где лежит `package.json` rstool).
21
+ Скрипты пишут JSON в `examples/<topic>/`; запускайте из корня пакета (каталог с `package.json` rstool).
22
22
 
23
- ## Скрипты
23
+ ## Макет папки темы
24
24
 
25
- | Файл | npm-скрипт | Назначение |
26
- |------|------------|------------|
27
- | [`agent-client.ts`](agent-client.ts) | `example:client` | Минимальный цикл: сессия, upsert, анализ, значения, диагностики через stdio |
28
- | [`build-sample-rsform.ts`](build-sample-rsform.ts) | `example:build-schema` | Собрать учебную RSForm (X1, S1, D1) и сохранить сессию |
29
- | [`build-sample-rsmodel.ts`](build-sample-rsmodel.ts) | `example:build-rsmodel` | RSForm + привязки + вычисления → учебная RSModel |
30
- | [`build-kinship-rsform.ts`](build-kinship-rsform.ts) | `example:build-kinship-schema` | Полная концептуальная схема «родственные отношения» (много конституент) |
31
- | [`build-kinship-rsmodel.ts`](build-kinship-rsmodel.ts) | `example:build-kinship-rsmodel` | Загрузить kinship RSForm, задать семью, вычислить модель (в т.ч. D3) |
32
- | [`kinship/cli.ts`](kinship/cli.ts) | `kinship:cli` | Интерактивное редактирование людей (X1) и связей (S1) в kinship-модели |
25
+ У `sample/`, `chocolate-nim/` и `movd/` одинаковая структура:
33
26
 
34
- ## JSON-сессии
27
+ | Файл | Роль |
28
+ | ------------------ | ----------------------------------------------- |
29
+ | `constants.ts` | Id конституент и пути к JSON-сессиям |
30
+ | `build-rsform.ts` | Сборка RSForm → `rsform-session.json` |
31
+ | `build-rsmodel.ts` | Демо-модель и проверки → `rsmodel-session.json` |
35
32
 
36
- Готовые снимки `exportSession` для `importSession`, тестов и CLI:
33
+ Готовые `*-session.json` — снимки `exportSession` для `importSession` и тестов. Пересобрать: соответствующий `build-*.ts` перезапишет файл рядом с собой.
37
34
 
38
- | Файл | Содержимое |
39
- |------|------------|
40
- | [`sample-rsform-session.json`](sample-rsform-session.json) | Учебная RSForm (результат `build-sample-rsform`) |
41
- | [`sample-rsmodel-session.json`](sample-rsmodel-session.json) | Учебная RSModel с вычисленными значениями |
42
- | [`kinship-rsform-session.json`](kinship-rsform-session.json) | Схема родства без привязок |
43
- | [`kinship-rsmodel-session.json`](kinship-rsmodel-session.json) | Kinship-модель с примерной семьёй (по умолчанию для `kinship:cli`) |
35
+ ## Темы и npm-скрипты
44
36
 
45
- Пересобрать JSON: соответствующий `build-*.ts` перезапишет файл в `examples/`.
37
+ - **[`sample/`](sample/):**
38
+ - Минимальная учебная схема: `X1`, `C1`, `S1`, `D1`, `A1`
39
+ - `build-rsform` скрипт: `example:build-schema`
40
+ - `build-rsmodel` скрипт: `example:build-rsmodel`
41
+
42
+ - **[`kinship/`](kinship/):**
43
+ - «Родственные отношения» — развёрнутая предметная схема
44
+ - `build-rsform` скрипт: `example:build-kinship-schema`
45
+ - `build-rsmodel` скрипт: `example:build-kinship-rsmodel`
46
+
47
+ - **[`chocolate-nim/`](chocolate-nim/):**
48
+ - «Шоколадный Ним» — пример математической схемы без `X#`
49
+ - `build-rsform` скрипт: `example:build-chocolate-nim-schema`
50
+ - `build-rsmodel` скрипт: `example:build-chocolate-nim-rsmodel`
51
+
52
+ - **[`movd/`](movd/):**
53
+ - «МОВД» — пример предметной схемы со сложными `S#`, мультипроекциями и фильтрами
54
+ - `build-rsform` скрипт: `example:build-movd-schema`
55
+ - `build-rsmodel` скрипт: `example:build-movd-rsmodel`
56
+
57
+ - **[`expression-bank/`](expression-bank/):**
58
+ - «Банк выражений» (Portal rsforms/42) — шаблоны T1–T10 на радикалах `R1`–`R3` без `X#`
59
+ - `build-rsform` скрипт: `example:build-expression-bank-schema`
60
+ - только `rsform-session.json` (без модели)
61
+
62
+ - **[`template-apply/`](template-apply/):**
63
+ - Небольшая предметная схема: подстановка `R1→X1`, `R2→X2` для шаблонов БВ (F6, F20, P5)
64
+ - `build-rsform` скрипт: `example:build-template-apply-schema` (сборка + проверка на модели в скрипте)
65
+ - только `rsform-session.json`
66
+
67
+ В корне: [`agent-client.ts`](agent-client.ts) (`example:client`) — минимальный цикл через stdio без привязки к теме.
46
68
 
47
69
  ## Папка `kinship/`
48
70
 
49
- Вспомогательный код для сценария «родственные отношения», не отдельный пакет:
71
+ Тот же макет, плюс интерактивное редактирование модели:
72
+
73
+ | Файл | Роль |
74
+ | -------------------------------------------------- | ------------------------------------------------------------------------- |
75
+ | [`session.ts`](kinship/session.ts) | Обёртка: загрузка/сохранение, команды над `X1` и `S1` |
76
+ | [`x1-actions.ts`](kinship/x1-actions.ts) | Парсинг и применение изменений списка людей |
77
+ | [`x1-actions.test.ts`](kinship/x1-actions.test.ts) | Тесты логики `X1` (`npm test`) |
78
+ | [`cli.ts`](kinship/cli.ts) | REPL (`kinship:cli`): `list`, `add`, `remove`, `rename`, `set`, `save`, … |
50
79
 
51
- | Файл | Роль |
52
- |------|------|
53
- | [`constants.ts`](kinship/constants.ts) | Id конституент (X1, S1, D3, A1, …) и путь сессии по умолчанию |
54
- | [`session.ts`](kinship/session.ts) | Обёртка над сессией: загрузка/сохранение, команды над X1 и S1 |
55
- | [`x1-actions.ts`](kinship/x1-actions.ts) | Парсинг и применение изменений списка людей |
56
- | [`x1-actions.test.ts`](kinship/x1-actions.test.ts) | Тесты логики X1 (`npm test`) |
57
- | [`cli.ts`](kinship/cli.ts) | REPL: `list`, `add`, `remove`, `rename`, `set`, `save`, … |
80
+ По умолчанию CLI читает [`kinship/rsmodel-session.json`](kinship/rsmodel-session.json).
58
81
 
59
- См. также [`../docs/CONSTITUENTA.md`](../docs/CONSTITUENTA.md) (разбор kinship-схемы) и [`../docs/MODEL-TESTING.md`](../docs/MODEL-TESTING.md).
82
+ См. также [`../docs/CONSTITUENTA.md`](../docs/CONSTITUENTA.md) и [`../docs/MODEL-TESTING.md`](../docs/MODEL-TESTING.md).
@@ -0,0 +1,311 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+
4
+ import { CstType, RSToolWrapperClient, type AddOrUpdateConstituentaInput } from '../src';
5
+
6
+ import { DEFAULT_RSFORM_SESSION_PATH } from './chocolate-nim/constants';
7
+
8
+ /**
9
+ * Учебная RSForm «шоколадный Ним» (ОШК-НИМ) по Portal rsforms/825.
10
+ * Целочисленное представление без базисного множества: размеры и позиции — кортежи Z×Z.
11
+ */
12
+ async function run() {
13
+ const client = new RSToolWrapperClient({
14
+ cwd: resolve(process.cwd())
15
+ });
16
+
17
+ try {
18
+ await client.waitUntilReady();
19
+ const session = await client.call<{ sessionId: string; contractVersion: string }>('createSession');
20
+
21
+ const drafts: AddOrUpdateConstituentaInput[] = [
22
+ {
23
+ draft: {
24
+ id: 1,
25
+ alias: 'S1',
26
+ cstType: CstType.STRUCTURED,
27
+ definitionFormal: 'Z×Z',
28
+ term: 'шоколадка',
29
+ convention: 'Первая проекция — ширина, вторая — длина'
30
+ }
31
+ },
32
+ {
33
+ draft: {
34
+ id: 2,
35
+ alias: 'D1',
36
+ cstType: CstType.TERM,
37
+ definitionFormal: 'pr1(S1)',
38
+ term: 'ширина шоколадки'
39
+ }
40
+ },
41
+ {
42
+ draft: {
43
+ id: 3,
44
+ alias: 'D2',
45
+ cstType: CstType.TERM,
46
+ definitionFormal: 'pr2(S1)',
47
+ term: 'длина шоколадки'
48
+ }
49
+ },
50
+ {
51
+ draft: {
52
+ id: 4,
53
+ alias: 'S2',
54
+ cstType: CstType.STRUCTURED,
55
+ definitionFormal: 'Z×Z',
56
+ term: 'отравленная долька',
57
+ convention: 'Координаты отравленной дольки: первая проекция по ширине, вторая — по длине'
58
+ }
59
+ },
60
+ {
61
+ draft: {
62
+ id: 5,
63
+ alias: 'D3',
64
+ cstType: CstType.TERM,
65
+ definitionFormal: 'pr1(S2)',
66
+ term: 'расположение отравленной дольки по ширине'
67
+ }
68
+ },
69
+ {
70
+ draft: {
71
+ id: 6,
72
+ alias: 'D4',
73
+ cstType: CstType.TERM,
74
+ definitionFormal: 'pr2(S2)',
75
+ term: 'расположение отравленной дольки по длине'
76
+ }
77
+ },
78
+ {
79
+ draft: {
80
+ id: 7,
81
+ alias: 'A1',
82
+ cstType: CstType.AXIOM,
83
+ definitionFormal: '(1≤D3)&(D3≤D1)&(1≤D4)&(D4≤D2)',
84
+ term: 'отравленная долька в шоколадке',
85
+ definitionText: 'Координаты отравленной дольки лежат в пределах шоколадки'
86
+ }
87
+ },
88
+ {
89
+ draft: {
90
+ id: 8,
91
+ alias: 'P1',
92
+ cstType: CstType.PREDICATE,
93
+ definitionFormal: '[α∈Z] R{ξ:=α | ξ≥2 | ξ-2}=0',
94
+ term: 'чётное?',
95
+ convention: 'Для малых аргументов — прямое вычитание двойки; для больших нужно двоичное представление'
96
+ }
97
+ },
98
+ {
99
+ draft: {
100
+ id: 9,
101
+ alias: 'F1',
102
+ cstType: CstType.FUNCTION,
103
+ definitionFormal: '[α∈Z, σ∈ℬ(Z×R1)] debool(Pr2(Fi1[{α}](σ)))',
104
+ term: 'значение элемента последовательности с данным номером',
105
+ definitionText: 'Значение пары с заданным номером в последовательности пар'
106
+ }
107
+ },
108
+ {
109
+ draft: {
110
+ id: 10,
111
+ alias: 'F2',
112
+ cstType: CstType.FUNCTION,
113
+ definitionFormal: '[σ∈ℬ(Z)] debool(D{ξ∈σ | ∀α∈σ α≤ξ})',
114
+ term: 'максимум набора чисел'
115
+ }
116
+ },
117
+ {
118
+ draft: {
119
+ id: 11,
120
+ alias: 'F4',
121
+ cstType: CstType.FUNCTION,
122
+ definitionFormal: '[σ∈ℬ(Z)] D{ξ∈σ | ∀α∈σ α≤ξ}',
123
+ term: 'верхние границы набора чисел',
124
+ definitionText: 'Множество элементов набора, не меньших всех остальных'
125
+ }
126
+ },
127
+ {
128
+ draft: {
129
+ id: 12,
130
+ alias: 'F5',
131
+ cstType: CstType.FUNCTION,
132
+ definitionFormal: '[α∈Z, β∈Z] debool(I{(α,0) | α<β} ∪ I{(α-β,1) | α≥β})',
133
+ term: 'деление с остатком на степень двойки',
134
+ convention: 'Предполагается, что удвоенный делитель больше делимого'
135
+ }
136
+ },
137
+ {
138
+ draft: {
139
+ id: 13,
140
+ alias: 'F6',
141
+ cstType: CstType.FUNCTION,
142
+ definitionFormal: '[α∈Z, β∈Z] pr1(F5[α, β])',
143
+ term: 'остаток'
144
+ }
145
+ },
146
+ {
147
+ draft: {
148
+ id: 14,
149
+ alias: 'F7',
150
+ cstType: CstType.FUNCTION,
151
+ definitionFormal: '[α∈Z, β∈Z] pr2(F5[α, β])',
152
+ term: 'целая часть'
153
+ }
154
+ },
155
+ {
156
+ draft: {
157
+ id: 15,
158
+ alias: 'D5',
159
+ cstType: CstType.TERM,
160
+ definitionFormal: '{(0, D3-1), (1, D4-1), (2, D1-D3), (3, D2-D4)}',
161
+ term: 'шоколадка как кучки Ним',
162
+ definitionText: 'Четыре кучки камней после разреза по отравленной дольке: слева, сверху, справа и снизу'
163
+ }
164
+ },
165
+ {
166
+ draft: {
167
+ id: 16,
168
+ alias: 'D6',
169
+ cstType: CstType.TERM,
170
+ definitionFormal: 'card(D5)',
171
+ term: 'количество кучек'
172
+ }
173
+ },
174
+ {
175
+ draft: {
176
+ id: 17,
177
+ alias: 'D7',
178
+ cstType: CstType.TERM,
179
+ definitionFormal: 'Pr1(D5)',
180
+ term: 'номера кучек'
181
+ }
182
+ },
183
+ {
184
+ draft: {
185
+ id: 18,
186
+ alias: 'D8',
187
+ cstType: CstType.TERM,
188
+ definitionFormal: 'Pr2(D5)',
189
+ term: 'размеры кучек'
190
+ }
191
+ },
192
+ {
193
+ draft: {
194
+ id: 19,
195
+ alias: 'A2',
196
+ cstType: CstType.AXIOM,
197
+ definitionFormal: 'card(D5)=card(D7)',
198
+ term: 'однозначность количества камней в кучках',
199
+ definitionText: 'У каждой кучки ровно один номер'
200
+ }
201
+ },
202
+ {
203
+ draft: {
204
+ id: 20,
205
+ alias: 'A3',
206
+ cstType: CstType.AXIOM,
207
+ definitionFormal: '∀α∈D5 (pr1(α)<D6 & pr1(α)≥0)',
208
+ term: 'последовательная нумерация кучек',
209
+ definitionText: 'Номера кучек — целые от нуля до количества кучек минус один'
210
+ }
211
+ },
212
+ {
213
+ draft: {
214
+ id: 21,
215
+ alias: 'F8',
216
+ cstType: CstType.FUNCTION,
217
+ definitionFormal: '[α∈Z] F1[α,D5]',
218
+ term: 'количество камней в данной кучке'
219
+ }
220
+ },
221
+ {
222
+ draft: {
223
+ id: 22,
224
+ alias: 'D9',
225
+ cstType: CstType.TERM,
226
+ definitionFormal: 'Pr1(Fi2[{0}](D5))',
227
+ term: 'пустые кучки',
228
+ definitionText: 'Номера кучек с нулевым размером'
229
+ }
230
+ },
231
+ {
232
+ draft: {
233
+ id: 23,
234
+ alias: 'D10',
235
+ cstType: CstType.TERM,
236
+ definitionFormal: 'D7\\D9',
237
+ term: 'непустые кучки',
238
+ definitionText: 'Номера кучек с положительным размером'
239
+ }
240
+ },
241
+ {
242
+ draft: {
243
+ id: 24,
244
+ alias: 'T1',
245
+ cstType: CstType.STATEMENT,
246
+ definitionFormal: 'D8={0}',
247
+ term: 'игра закончена',
248
+ definitionText: 'Во всех кучках не осталось камней'
249
+ }
250
+ },
251
+ {
252
+ draft: {
253
+ id: 25,
254
+ alias: 'T2',
255
+ cstType: CstType.STATEMENT,
256
+ definitionFormal: 'card(D10)=1',
257
+ term: 'существует выигрышный ход',
258
+ definitionText: 'Осталась ровно одна непустая кучка'
259
+ }
260
+ },
261
+ {
262
+ draft: {
263
+ id: 26,
264
+ alias: 'F10',
265
+ cstType: CstType.FUNCTION,
266
+ definitionFormal: '[σ∈D7×Z] debool(I{ pr2(σ)*D2 | P1[pr1(σ)]} ∪ I{ pr2(σ)*D1 | ¬P1[pr1(σ)]})',
267
+ term: 'оценка хода Ним',
268
+ definitionText:
269
+ 'Стоимость хода в дольках шоколадки: для чётного номера кучки — размер, умноженный на длину, иначе — на ширину'
270
+ }
271
+ }
272
+ ];
273
+
274
+ for (const input of drafts) {
275
+ const result = await client.call<{
276
+ state: { alias: string; analysis: { success: boolean } };
277
+ diagnostics: unknown[];
278
+ }>('addOrUpdateConstituenta', {
279
+ sessionId: session.sessionId,
280
+ input
281
+ });
282
+ const ok = result.state.analysis.success;
283
+ const diagCount = result.diagnostics?.length ?? 0;
284
+ console.log(`${input.draft.alias}: ${ok ? 'OK' : 'FAIL'} (${diagCount} diagnostics)`);
285
+ if (!ok) {
286
+ const diags = await client.call('listDiagnostics', { sessionId: session.sessionId });
287
+ console.log(JSON.stringify(diags, null, 2));
288
+ throw new Error(`${input.draft.alias}: analysis failed (${diagCount} diagnostics)`);
289
+ }
290
+ }
291
+
292
+ await client.call('commitStep', {
293
+ sessionId: session.sessionId,
294
+ message: 'КС «шоколадный Ним» (rsforms/825): Z×Z, pr, P#, T#, арифметика, радикал R1'
295
+ });
296
+
297
+ const exported = await client.call<string>('exportSession', {
298
+ sessionId: session.sessionId
299
+ });
300
+ const outputPath = resolve(process.cwd(), DEFAULT_RSFORM_SESSION_PATH);
301
+ await writeFile(outputPath, exported, 'utf8');
302
+ console.log(`Exported: ${outputPath}`);
303
+ } finally {
304
+ await client.close();
305
+ }
306
+ }
307
+
308
+ run().catch(error => {
309
+ console.error(error);
310
+ process.exit(1);
311
+ });