@adminforth/agent 1.22.1 → 1.23.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.
package/apiBasedTools.ts CHANGED
@@ -94,6 +94,8 @@ type GetResourceDataToolResponse = {
94
94
  options?: Record<string, unknown>;
95
95
  };
96
96
 
97
+ type DateTimeColumnType = AdminForthDataTypes.DATETIME | AdminForthDataTypes.TIME;
98
+
97
99
  const DEFAULT_USER_TIME_ZONE = 'UTC';
98
100
 
99
101
  const TOOL_OVERRIDES: Record<string, ToolOverride> = {
@@ -373,6 +375,7 @@ async function applyToolOverride(params: {
373
375
  adminUser,
374
376
  inputs: nestedInputs,
375
377
  httpExtra: nestedHttpExtra,
378
+ userTimeZone: nestedUserTimeZone,
376
379
  });
377
380
 
378
381
  return applyToolOverride({
@@ -488,20 +491,104 @@ function createRawExpressResponse(response: ToolHttpResponse) {
488
491
  return rawResponse;
489
492
  }
490
493
 
494
+ function normalizeDateTimeInputsToUtc(
495
+ body: Record<string, unknown>,
496
+ adminforth: IAdminForth,
497
+ userTimeZone?: string,
498
+ ): Record<string, unknown> {
499
+ if (!userTimeZone || typeof body.resourceId !== 'string') {
500
+ return body;
501
+ }
502
+
503
+ const resource = adminforth.config.resources.find((res) => res.resourceId === body.resourceId);
504
+
505
+ if (!resource) {
506
+ return body;
507
+ }
508
+
509
+ const columnsByName = new Map(resource.dataSourceColumns.map((column) => [column.name, column]));
510
+
511
+ const normalizeColumnValue = (
512
+ value: unknown,
513
+ columnType: DateTimeColumnType,
514
+ ): unknown => {
515
+ if (Array.isArray(value)) {
516
+ return value.map((item) => normalizeColumnValue(item, columnType));
517
+ }
518
+
519
+ if (typeof value !== 'string' || value === '') {
520
+ return value;
521
+ }
522
+
523
+ if (columnType === AdminForthDataTypes.DATETIME) {
524
+ return dayjs.tz(value, userTimeZone).utc().toISOString();
525
+ }
526
+
527
+ if (columnType === AdminForthDataTypes.TIME) {
528
+ const userDate = dayjs().tz(userTimeZone).format('YYYY-MM-DD');
529
+ return dayjs.tz(`${userDate}T${value}`, userTimeZone).utc().format('HH:mm:ss');
530
+ }
531
+ };
532
+
533
+ const normalizeValue = (value: unknown, key?: string): unknown => {
534
+ const column = key ? columnsByName.get(key) : undefined;
535
+
536
+ if (column?.type === AdminForthDataTypes.DATETIME || column?.type === AdminForthDataTypes.TIME) {
537
+ return normalizeColumnValue(value, column.type);
538
+ }
539
+
540
+ if (Array.isArray(value)) {
541
+ return value.map((item) => normalizeValue(item));
542
+ }
543
+
544
+ if (!value || typeof value !== 'object') {
545
+ return value;
546
+ }
547
+
548
+ const record = value as Record<string, unknown>;
549
+ const filterColumn = typeof record.field === 'string' ? columnsByName.get(record.field) : undefined;
550
+
551
+ if (
552
+ 'value' in record &&
553
+ (filterColumn?.type === AdminForthDataTypes.DATETIME || filterColumn?.type === AdminForthDataTypes.TIME)
554
+ ) {
555
+ return {
556
+ ...record,
557
+ value: normalizeColumnValue(record.value, filterColumn.type),
558
+ };
559
+ }
560
+
561
+ return Object.fromEntries(
562
+ Object.entries(record).map(([nestedKey, nestedValue]) => [
563
+ nestedKey,
564
+ normalizeValue(nestedValue, nestedKey),
565
+ ]),
566
+ );
567
+ };
568
+
569
+ return normalizeValue(body) as Record<string, unknown>;
570
+ }
571
+
491
572
  async function callCapturedEndpoint(params: {
492
573
  adminforth: IAdminForth;
493
574
  adminUser?: AdminUser;
494
575
  endpoint: CapturedEndpoint;
495
576
  httpExtra?: Partial<HttpExtra>;
496
577
  inputs?: Record<string, unknown>;
578
+ userTimeZone?: string;
497
579
  }) {
498
- const { adminforth, adminUser, endpoint, httpExtra, inputs } = params;
580
+ const { adminforth, adminUser, endpoint, httpExtra, inputs, userTimeZone } = params;
499
581
  const response = createToolResponse(httpExtra?.response);
500
582
  const headers = {
501
583
  'content-type': 'application/json',
584
+ 'X-TimeZone': userTimeZone,
502
585
  ...(httpExtra?.headers ?? {}),
503
586
  };
504
- const body = (inputs ?? httpExtra?.body ?? {}) as Record<string, unknown>;
587
+ const body = normalizeDateTimeInputsToUtc(
588
+ (inputs ?? httpExtra?.body ?? {}) as Record<string, unknown>,
589
+ adminforth,
590
+ headers['X-TimeZone'],
591
+ );
505
592
  const query = httpExtra?.query ?? {};
506
593
  const cookies = normalizeCookies(httpExtra?.cookies);
507
594
  const requestUrl = httpExtra?.requestUrl ?? `${adminforth.config.baseUrl}/adminapi/v1${endpoint.path}`;
@@ -596,6 +683,7 @@ export function prepareApiBasedTools(adminforth: IAdminForth): Record<string, Ap
596
683
  adminUser: adminUser ?? adminuser,
597
684
  inputs,
598
685
  httpExtra,
686
+ userTimeZone,
599
687
  });
600
688
 
601
689
  const processedOutput = await applyToolOverride({
@@ -629,4 +717,4 @@ export function serializeApiBasedTool(tool: ApiBasedTool | undefined) {
629
717
  output_schema: tool.output_schema,
630
718
  call: '[Function]',
631
719
  };
632
- }
720
+ }
package/build.log CHANGED
@@ -38,5 +38,5 @@ custom/skills/fetch_data/SKILL.md
38
38
  custom/skills/mutate_data/
39
39
  custom/skills/mutate_data/SKILL.md
40
40
 
41
- sent 199,157 bytes received 562 bytes 399,438.00 bytes/sec
42
- total size is 196,887 speedup is 0.99
41
+ sent 199,973 bytes received 562 bytes 401,070.00 bytes/sec
42
+ total size is 197,669 speedup is 0.99
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <template v-if="ToolOrReasoningParts.length > 0 || isResponseInProgress || showFakeThinkingMessage">
3
3
  <div
4
- class="ml-2 px-4 flex items-center gap-1 cursor-pointer select-none hover:opacity-80 tracking-wide font-medium text-sm"
4
+ class="ml-2 px-4 flex items-center gap-1 cursor-pointer select-none hover:opacity-80 tracking-wide font-medium text-sm text-listTableHeadingText dark:text-darkListTableHeadingText"
5
5
  @click="isExpanded = !isExpanded"
6
6
  >
7
7
  Thoughts
@@ -20,7 +20,7 @@
20
20
  v-show="isExpanded"
21
21
  class="mask-y"
22
22
  >
23
- <ol class="ml-8 relative border-l border-l-2 border-black border-default">
23
+ <ol class="ml-8 relative border-l border-l-2 border-black border-default border-listTableHeadingText dark:border-darkListTableHeadingText">
24
24
  <li class="mb-6 ms-2 z-50" v-for="(part, index) in ToolOrReasoningParts" :key="index">
25
25
  <ReasoningRenderer v-if="part.type === 'reasoning'" :state="part.state" :text="part.text" />
26
26
  <ToolsGroup v-else :toolGroup="groupToolCallParts(message, part)" />
@@ -1,11 +1,11 @@
1
1
  <template>
2
- <span class="bg-lightNavbar absolute flex items-center justify-center w-5 h-5 bg-brand-softer rounded-full -start-[0.68rem] ring-4 ring-lightNavbar ring-default">
2
+ <span class="bg-lightNavbar dark:bg-darkNavbar absolute flex items-center text-listTableHeadingText dark:text-darkListTableHeadingText justify-center w-5 h-5 bg-brand-softer rounded-full -start-[0.68rem] ring-4 ring-lightNavbar dark:ring-darkNavbar ring-default">
3
3
  <div class="w-5 h-5 rounded-full flex items-center justify-center">
4
4
  <IconBrainOutline class="w-4 h-4" />
5
5
  </div>
6
6
  </span>
7
7
  <h3
8
- class="flex items-center mb-1 text-sm my-2 ml-3 gap-1 cursor-pointer select-none hover:opacity-80"
8
+ class="flex items-center mb-1 text-sm my-2 ml-3 gap-1 cursor-pointer select-none hover:opacity-80 text-listTableHeadingText dark:text-darkListTableHeadingText"
9
9
  @click="isExpanded = !isExpanded"
10
10
  >
11
11
  <span class="font-semibold">{{ reasoningTitle }}</span>
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <span class="bounce-dot1 rounded-full w-2 h-2 bg-lightPrimary"></span>
3
- <span class="bounce-dot2 rounded-full w-2 h-2 bg-lightPrimary"></span>
4
- <span class="bounce-dot3 rounded-full w-2 h-2 bg-lightPrimary"></span>
2
+ <span class="bounce-dot1 rounded-full w-2 h-2 bg-lightPrimary dark:bg-darkPrimary"></span>
3
+ <span class="bounce-dot2 rounded-full w-2 h-2 bg-lightPrimary dark:bg-darkPrimary"></span>
4
+ <span class="bounce-dot3 rounded-full w-2 h-2 bg-lightPrimary dark:bg-darkPrimary"></span>
5
5
  </template>
6
6
 
7
7
  <style scoped>
@@ -19,7 +19,7 @@
19
19
  class="flex items-center gap-1 cursor-pointer"
20
20
  @click="toggleInputOutput()"
21
21
  >
22
- <div class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-white/70 dark:bg-blue-700/20">
22
+ <div class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-lightNavbar dark:bg-darkNavbar">
23
23
  <Spinner v-if="isRunning" class="h-4 w-4" />
24
24
  <IconCheckOutline v-else class="h-4 w-4 text-lightPrimary dark:text-darkPrimary" />
25
25
  </div>
@@ -1,12 +1,12 @@
1
1
  <template >
2
2
  <template v-if="toolGroup.length > 0">
3
- <span class="bg-lightNavbar absolute flex items-center justify-center w-5 h-5 bg-brand-softer rounded-full -start-[0.68rem] ring-4 ring-lightNavbar ring-default">
3
+ <span class="text-listTableHeadingText dark:text-darkListTableHeadingText bg-lightNavbar dark:bg-darkNavbar absolute flex items-center justify-center w-5 h-5 bg-brand-softer rounded-full -start-[0.68rem] ring-4 ring-lightNavbar dark:ring-darkNavbar ring-default">
4
4
  <div class="w-5 h-5 rounded-full flex items-center justify-center">
5
5
  <IconWrenchSolid class="w-4 h-4" />
6
6
  </div>
7
7
  </span>
8
8
  <h3
9
- class="flex items-center mb-1 text-sm my-2 ml-3 gap-1"
9
+ class="flex items-center mb-1 text-sm my-2 ml-3 gap-1 text-listTableHeadingText dark:text-darkListTableHeadingText"
10
10
  >
11
11
  <span class="font-semibold select-none ">Call tools</span>
12
12
  </h3>
@@ -73,8 +73,7 @@ Are you sure?
73
73
  ## Updating
74
74
 
75
75
  You can use tool `update_record` tool it updates fields of record. To update `allowedActions.edit` should be set to true and
76
- `updated` column `showIn.edit` should be true at the same time. If one of this condition is not met, explain to user that is
77
- not allowed to edit
76
+ `updated` column `showIn.edit` should be true at the same time. If one of this condition is not met, explain to user that is not allowed to edit
78
77
 
79
78
  In addition to instructions above show user the table of edits (old value/new value)
80
79
 
@@ -126,6 +125,10 @@ After creation of new record also show user a link to this record. If several re
126
125
 
127
126
  Omit any pictures or file paths, you are not capable of doing it. If they are not required all is good, if they are required, explain to user that you are not able to create record because of this reason.
128
127
 
128
+ ### Working with dates
129
+
130
+ When you create or update date or datetime fields, please use ISO format for this. For example, "2024-01-01" for date and "2024-01-01T12:00:00Z" for datetime. If user provides date in different format, try to parse it and convert to ISO format.
131
+
129
132
  ### Example
130
133
 
131
134
 
@@ -212,6 +212,7 @@ function applyToolOverride(params) {
212
212
  adminUser,
213
213
  inputs: nestedInputs,
214
214
  httpExtra: nestedHttpExtra,
215
+ userTimeZone: nestedUserTimeZone,
215
216
  });
216
217
  return applyToolOverride({
217
218
  adminforth,
@@ -306,13 +307,61 @@ function createRawExpressResponse(response) {
306
307
  };
307
308
  return rawResponse;
308
309
  }
310
+ function normalizeDateTimeInputsToUtc(body, adminforth, userTimeZone) {
311
+ if (!userTimeZone || typeof body.resourceId !== 'string') {
312
+ return body;
313
+ }
314
+ const resource = adminforth.config.resources.find((res) => res.resourceId === body.resourceId);
315
+ if (!resource) {
316
+ return body;
317
+ }
318
+ const columnsByName = new Map(resource.dataSourceColumns.map((column) => [column.name, column]));
319
+ const normalizeColumnValue = (value, columnType) => {
320
+ if (Array.isArray(value)) {
321
+ return value.map((item) => normalizeColumnValue(item, columnType));
322
+ }
323
+ if (typeof value !== 'string' || value === '') {
324
+ return value;
325
+ }
326
+ if (columnType === AdminForthDataTypes.DATETIME) {
327
+ return dayjs.tz(value, userTimeZone).utc().toISOString();
328
+ }
329
+ if (columnType === AdminForthDataTypes.TIME) {
330
+ const userDate = dayjs().tz(userTimeZone).format('YYYY-MM-DD');
331
+ return dayjs.tz(`${userDate}T${value}`, userTimeZone).utc().format('HH:mm:ss');
332
+ }
333
+ };
334
+ const normalizeValue = (value, key) => {
335
+ const column = key ? columnsByName.get(key) : undefined;
336
+ if ((column === null || column === void 0 ? void 0 : column.type) === AdminForthDataTypes.DATETIME || (column === null || column === void 0 ? void 0 : column.type) === AdminForthDataTypes.TIME) {
337
+ return normalizeColumnValue(value, column.type);
338
+ }
339
+ if (Array.isArray(value)) {
340
+ return value.map((item) => normalizeValue(item));
341
+ }
342
+ if (!value || typeof value !== 'object') {
343
+ return value;
344
+ }
345
+ const record = value;
346
+ const filterColumn = typeof record.field === 'string' ? columnsByName.get(record.field) : undefined;
347
+ if ('value' in record &&
348
+ ((filterColumn === null || filterColumn === void 0 ? void 0 : filterColumn.type) === AdminForthDataTypes.DATETIME || (filterColumn === null || filterColumn === void 0 ? void 0 : filterColumn.type) === AdminForthDataTypes.TIME)) {
349
+ return Object.assign(Object.assign({}, record), { value: normalizeColumnValue(record.value, filterColumn.type) });
350
+ }
351
+ return Object.fromEntries(Object.entries(record).map(([nestedKey, nestedValue]) => [
352
+ nestedKey,
353
+ normalizeValue(nestedValue, nestedKey),
354
+ ]));
355
+ };
356
+ return normalizeValue(body);
357
+ }
309
358
  function callCapturedEndpoint(params) {
310
359
  return __awaiter(this, void 0, void 0, function* () {
311
360
  var _a, _b, _c, _d;
312
- const { adminforth, adminUser, endpoint, httpExtra, inputs } = params;
361
+ const { adminforth, adminUser, endpoint, httpExtra, inputs, userTimeZone } = params;
313
362
  const response = createToolResponse(httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.response);
314
- const headers = Object.assign({ 'content-type': 'application/json' }, ((_a = httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.headers) !== null && _a !== void 0 ? _a : {}));
315
- const body = ((_b = inputs !== null && inputs !== void 0 ? inputs : httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.body) !== null && _b !== void 0 ? _b : {});
363
+ const headers = Object.assign({ 'content-type': 'application/json', 'X-TimeZone': userTimeZone }, ((_a = httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.headers) !== null && _a !== void 0 ? _a : {}));
364
+ const body = normalizeDateTimeInputsToUtc(((_b = inputs !== null && inputs !== void 0 ? inputs : httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.body) !== null && _b !== void 0 ? _b : {}), adminforth, headers['X-TimeZone']);
316
365
  const query = (_c = httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.query) !== null && _c !== void 0 ? _c : {};
317
366
  const cookies = normalizeCookies(httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.cookies);
318
367
  const requestUrl = (_d = httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.requestUrl) !== null && _d !== void 0 ? _d : `${adminforth.config.baseUrl}/adminapi/v1${endpoint.path}`;
@@ -387,6 +436,7 @@ export function prepareApiBasedTools(adminforth) {
387
436
  adminUser: adminUser !== null && adminUser !== void 0 ? adminUser : adminuser,
388
437
  inputs,
389
438
  httpExtra,
439
+ userTimeZone,
390
440
  });
391
441
  const processedOutput = yield applyToolOverride({
392
442
  adminforth,
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <template v-if="ToolOrReasoningParts.length > 0 || isResponseInProgress || showFakeThinkingMessage">
3
3
  <div
4
- class="ml-2 px-4 flex items-center gap-1 cursor-pointer select-none hover:opacity-80 tracking-wide font-medium text-sm"
4
+ class="ml-2 px-4 flex items-center gap-1 cursor-pointer select-none hover:opacity-80 tracking-wide font-medium text-sm text-listTableHeadingText dark:text-darkListTableHeadingText"
5
5
  @click="isExpanded = !isExpanded"
6
6
  >
7
7
  Thoughts
@@ -20,7 +20,7 @@
20
20
  v-show="isExpanded"
21
21
  class="mask-y"
22
22
  >
23
- <ol class="ml-8 relative border-l border-l-2 border-black border-default">
23
+ <ol class="ml-8 relative border-l border-l-2 border-black border-default border-listTableHeadingText dark:border-darkListTableHeadingText">
24
24
  <li class="mb-6 ms-2 z-50" v-for="(part, index) in ToolOrReasoningParts" :key="index">
25
25
  <ReasoningRenderer v-if="part.type === 'reasoning'" :state="part.state" :text="part.text" />
26
26
  <ToolsGroup v-else :toolGroup="groupToolCallParts(message, part)" />
@@ -1,11 +1,11 @@
1
1
  <template>
2
- <span class="bg-lightNavbar absolute flex items-center justify-center w-5 h-5 bg-brand-softer rounded-full -start-[0.68rem] ring-4 ring-lightNavbar ring-default">
2
+ <span class="bg-lightNavbar dark:bg-darkNavbar absolute flex items-center text-listTableHeadingText dark:text-darkListTableHeadingText justify-center w-5 h-5 bg-brand-softer rounded-full -start-[0.68rem] ring-4 ring-lightNavbar dark:ring-darkNavbar ring-default">
3
3
  <div class="w-5 h-5 rounded-full flex items-center justify-center">
4
4
  <IconBrainOutline class="w-4 h-4" />
5
5
  </div>
6
6
  </span>
7
7
  <h3
8
- class="flex items-center mb-1 text-sm my-2 ml-3 gap-1 cursor-pointer select-none hover:opacity-80"
8
+ class="flex items-center mb-1 text-sm my-2 ml-3 gap-1 cursor-pointer select-none hover:opacity-80 text-listTableHeadingText dark:text-darkListTableHeadingText"
9
9
  @click="isExpanded = !isExpanded"
10
10
  >
11
11
  <span class="font-semibold">{{ reasoningTitle }}</span>
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <span class="bounce-dot1 rounded-full w-2 h-2 bg-lightPrimary"></span>
3
- <span class="bounce-dot2 rounded-full w-2 h-2 bg-lightPrimary"></span>
4
- <span class="bounce-dot3 rounded-full w-2 h-2 bg-lightPrimary"></span>
2
+ <span class="bounce-dot1 rounded-full w-2 h-2 bg-lightPrimary dark:bg-darkPrimary"></span>
3
+ <span class="bounce-dot2 rounded-full w-2 h-2 bg-lightPrimary dark:bg-darkPrimary"></span>
4
+ <span class="bounce-dot3 rounded-full w-2 h-2 bg-lightPrimary dark:bg-darkPrimary"></span>
5
5
  </template>
6
6
 
7
7
  <style scoped>
@@ -19,7 +19,7 @@
19
19
  class="flex items-center gap-1 cursor-pointer"
20
20
  @click="toggleInputOutput()"
21
21
  >
22
- <div class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-white/70 dark:bg-blue-700/20">
22
+ <div class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-lightNavbar dark:bg-darkNavbar">
23
23
  <Spinner v-if="isRunning" class="h-4 w-4" />
24
24
  <IconCheckOutline v-else class="h-4 w-4 text-lightPrimary dark:text-darkPrimary" />
25
25
  </div>
@@ -1,12 +1,12 @@
1
1
  <template >
2
2
  <template v-if="toolGroup.length > 0">
3
- <span class="bg-lightNavbar absolute flex items-center justify-center w-5 h-5 bg-brand-softer rounded-full -start-[0.68rem] ring-4 ring-lightNavbar ring-default">
3
+ <span class="text-listTableHeadingText dark:text-darkListTableHeadingText bg-lightNavbar dark:bg-darkNavbar absolute flex items-center justify-center w-5 h-5 bg-brand-softer rounded-full -start-[0.68rem] ring-4 ring-lightNavbar dark:ring-darkNavbar ring-default">
4
4
  <div class="w-5 h-5 rounded-full flex items-center justify-center">
5
5
  <IconWrenchSolid class="w-4 h-4" />
6
6
  </div>
7
7
  </span>
8
8
  <h3
9
- class="flex items-center mb-1 text-sm my-2 ml-3 gap-1"
9
+ class="flex items-center mb-1 text-sm my-2 ml-3 gap-1 text-listTableHeadingText dark:text-darkListTableHeadingText"
10
10
  >
11
11
  <span class="font-semibold select-none ">Call tools</span>
12
12
  </h3>
@@ -73,8 +73,7 @@ Are you sure?
73
73
  ## Updating
74
74
 
75
75
  You can use tool `update_record` tool it updates fields of record. To update `allowedActions.edit` should be set to true and
76
- `updated` column `showIn.edit` should be true at the same time. If one of this condition is not met, explain to user that is
77
- not allowed to edit
76
+ `updated` column `showIn.edit` should be true at the same time. If one of this condition is not met, explain to user that is not allowed to edit
78
77
 
79
78
  In addition to instructions above show user the table of edits (old value/new value)
80
79
 
@@ -126,6 +125,10 @@ After creation of new record also show user a link to this record. If several re
126
125
 
127
126
  Omit any pictures or file paths, you are not capable of doing it. If they are not required all is good, if they are required, explain to user that you are not able to create record because of this reason.
128
127
 
128
+ ### Working with dates
129
+
130
+ When you create or update date or datetime fields, please use ISO format for this. For example, "2024-01-01" for date and "2024-01-01T12:00:00Z" for datetime. If user provides date in different format, try to parse it and convert to ISO format.
131
+
129
132
  ### Example
130
133
 
131
134
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/agent",
3
- "version": "1.22.1",
3
+ "version": "1.23.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",