@adminforth/agent 1.22.2 → 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 = (
|
|
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,
|
|
42
|
-
total size is 197,
|
|
41
|
+
sent 199,973 bytes received 562 bytes 401,070.00 bytes/sec
|
|
42
|
+
total size is 197,669 speedup is 0.99
|
|
@@ -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/dist/apiBasedTools.js
CHANGED
|
@@ -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,
|
|
@@ -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
|
|