@epam/ai-dial-chat-hooks 1.2.0-dev.99 → 1.3.0-dev.5
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/api-error/api-error.js +7 -4
- package/catalog/catalog-derivations.js +1 -1
- package/catalog/deployment-id.js +8 -2
- package/catalog/map-deployment-limits-to-catalog.js +16 -24
- package/catalog/map-deployment-limits-to-input.js +81 -9
- package/catalog/map-deployment-to-catalog-item.js +34 -34
- package/catalog/map-entity-details-to-catalog.js +237 -192
- package/catalog/map-skill-to-catalog-item.js +61 -54
- package/catalog/publish.js +4 -4
- package/catalog/useCatalogEditNavigation/useCatalogEditNavigation.js +122 -101
- package/catalog/useCatalogItemDetails.js +9 -8
- package/catalog/usePublishFolders/usePublishFolders.js +1 -1
- package/catalog.d.ts +171 -34
- package/catalog.js +23 -23
- package/conversation/conversation-transfer/export-conversation.js +24 -16
- package/conversation/conversation-transfer/import-conversation.js +80 -31
- package/conversation/create-chat-stream-api.js +89 -49
- package/conversation/get-model-id-from-conversation-id.js +15 -9
- package/conversation/message-utils.js +44 -2
- package/conversation/stage.js +6 -2
- package/conversation/useActiveConversationSync/useActiveConversationSync.js +7 -8
- package/conversation/useConversationExport/useConversationExport.js +9 -9
- package/conversation/useConversationHandlers/message-utils.js +8 -5
- package/conversation/useConversationHandlers/useConversationHandlers.js +181 -167
- package/conversation/useConversationImport/useConversationImport.js +123 -121
- package/conversation/useConversationPanelItems/useConversationPanelItems.js +49 -31
- package/conversation/useConversationStream/frame-scheduler.js +39 -0
- package/conversation/useConversationStream/generation-resume.js +122 -64
- package/conversation/useConversationStream/useConversationStream.js +298 -118
- package/conversation/useMessageSelectionReply/useMessageSelectionReply.js +189 -0
- package/conversation-sources/useConversationSources/useConversationSources.js +31 -24
- package/conversation-sources.d.ts +1 -1
- package/conversation-transfer.d.ts +2 -1
- package/conversation.d.ts +218 -22
- package/conversation.js +32 -31
- package/file-manager-canvas.d.ts +27 -7
- package/file-manager.d.ts +87 -32
- package/file-manager.js +25 -24
- package/files/attachment-canvas.js +67 -44
- package/files/dial-file-manager-copy-move.util.js +9 -8
- package/files/dial-file-manager-mapping.util.js +2 -1
- package/files/dial-file-manager-path.util.js +24 -2
- package/files/dial-file-manager.model.js +23 -19
- package/files/dial-file-manager.types.js +3 -3
- package/files/file-manager-variant.js +1 -1
- package/files/resolve-dial-file-api-path.js +11 -12
- package/files/useDialFileListing/useDialFileListing.js +140 -127
- package/files/useDialFileManager/useDialFileManager.js +139 -135
- package/files/useDialFileManagerSections/useDialFileManagerSections.js +155 -0
- package/files/useDialFileManagerTabConfig/useDialFileManagerTabConfig.js +20 -15
- package/files/useDialFileMutations/useDialFileMutations.js +65 -60
- package/files/useDialFileUploadBatch/useDialFileUploadBatch.js +117 -110
- package/files/useFileAttachmentPicker/useFileAttachmentPicker.js +28 -23
- package/index.d.ts +643 -128
- package/index.js +136 -134
- package/mcp-apps/useMcpAppTools/useMcpAppTools.js +1 -1
- package/oauth/authorize-url.js +3 -3
- package/oauth/toolset-id.js +5 -3
- package/oauth/useToolsetLogin/useToolsetLogin.js +8 -8
- package/oauth.d.ts +34 -2
- package/oauth.js +9 -9
- package/package.json +19 -23
- package/scheduled-task/scheduled-task-description.js +43 -39
- package/scheduled-task/scheduled-task-trigger.js +74 -71
- package/scheduled-task/use-scheduled-task-runs.js +162 -50
- package/scheduled-task/use-scheduled-tasks.js +52 -48
- package/scheduled-tasks.d.ts +27 -6
- package/scheduled-tasks.js +2 -2
- package/shared/application-schema.js +5 -2
- package/shared/cron-day-of-month.js +13 -0
- package/skill/skill-archive.js +19 -0
- package/skill/skill-types.js +8 -7
- package/skill/skill.js +52 -29
- package/skill/useSkillArchiveImport/useSkillArchiveImport.js +38 -34
- package/skill/useSkillEditorLoad.js +65 -59
- package/skill/useSkillEditorSubmit.js +105 -93
- package/skill/useSkillFileActions.js +70 -58
- package/skill-editor.d.ts +62 -13
- package/skill-editor.js +9 -9
- package/usage/map-user-usage-to-model-limits.js +137 -95
- package/usage.d.ts +8 -3
- package/usePageFileDrag/usePageFileDrag.js +3 -3
- package/utils.d.ts +26 -6
- package/utils.js +10 -10
package/skill-editor.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { SkillEditorFileActions } from '@epam/ai-dial-skill-editor';
|
|
|
7
7
|
import { SkillEditorValues } from '@epam/ai-dial-skill-editor';
|
|
8
8
|
import { SkillFileBatchError } from '@epam/ai-dial-skill-editor';
|
|
9
9
|
import { SkillFileListResponseDto } from '@epam/ai-dial-chat-api-client';
|
|
10
|
+
import { SkillFileSourceEntry } from '@epam/ai-dial-skill-editor';
|
|
10
11
|
import { SkillFileTreeNode } from '@epam/ai-dial-skill-editor';
|
|
11
12
|
import { SkillFileUploadCandidate } from '@epam/ai-dial-skill-editor';
|
|
12
13
|
import { SkillFileValidationResult } from '@epam/ai-dial-skill-editor';
|
|
@@ -15,7 +16,10 @@ import { SkillUploadResponseDto } from '@epam/ai-dial-chat-api-client';
|
|
|
15
16
|
/**
|
|
16
17
|
* Builds the ordered supporting-file paths and `Blob` payload
|
|
17
18
|
* `createSkill`/`updateSkill` expect from the editor's file tree and
|
|
18
|
-
* in-memory content map.
|
|
19
|
+
* in-memory content map. Every folder node with no descendant node gets a
|
|
20
|
+
* zero-byte `<folder>/.dial_folder` marker after the real files, so the
|
|
21
|
+
* empty folder survives the whole-skill write; a folder with content needs
|
|
22
|
+
* none, and a marker it had before is dropped by that same write.
|
|
19
23
|
*/
|
|
20
24
|
export declare const buildSkillFilesPayload: (files: SkillFileTreeNode[], filesContent: Map<string, SkillFileContent>) => SkillFilesPayload;
|
|
21
25
|
|
|
@@ -50,11 +54,20 @@ export declare const buildSkillManifestFromFrontmatter: (baseFrontmatter: Record
|
|
|
50
54
|
*/
|
|
51
55
|
export declare const classifySkillArchiveImportError: (status: number | undefined) => SkillArchiveImportErrorKind;
|
|
52
56
|
|
|
57
|
+
/** Returns the limit each over-long skill field exceeds, keyed by field; fields within their limit are omitted. */
|
|
58
|
+
export declare const getSkillFieldLengthViolations: (values: Record<SkillTextField, string>) => Partial<Record<SkillTextField, number>>;
|
|
59
|
+
|
|
60
|
+
/** Whether a skill-relative path is a folder marker (`<folder>/.dial_folder`, never a root-level `.dial_folder`). */
|
|
61
|
+
export declare const isSkillFolderMarkerPath: (path: string) => boolean;
|
|
62
|
+
|
|
53
63
|
/**
|
|
54
64
|
* Client-side mirror of the backend's `isValidSkillRelativePath`
|
|
55
65
|
* (`apps/chat-api/src/skills/utils/skill-path.util.ts`), used only for
|
|
56
66
|
* immediate inline feedback — the server remains authoritative and may still
|
|
57
|
-
* reject a path this function accepts.
|
|
67
|
+
* reject a path this function accepts. It additionally reserves the
|
|
68
|
+
* `.dial_folder` marker name so a user can never upload or name a folder
|
|
69
|
+
* after it; the save payload's generated markers never pass through here
|
|
70
|
+
* (the server accepts them only as a zero-byte final segment).
|
|
58
71
|
*/
|
|
59
72
|
export declare const isValidSkillRelativePath: (relativePath: string) => boolean;
|
|
60
73
|
|
|
@@ -102,9 +115,19 @@ export declare const parseSkillManifestDocument: (raw: string) => SkillManifestD
|
|
|
102
115
|
*/
|
|
103
116
|
export declare const SKILL_FILE_UPLOAD_MAX_BYTES = 1048576;
|
|
104
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Zero-byte object written at `<folder>/.dial_folder` so an otherwise empty
|
|
120
|
+
* skill folder survives a save — DIAL Core storage has no directory objects,
|
|
121
|
+
* so a folder only exists as a file's path prefix.
|
|
122
|
+
*/
|
|
123
|
+
export declare const SKILL_FOLDER_MARKER = ".dial_folder";
|
|
124
|
+
|
|
105
125
|
/** Root manifest filename required at the top of every skill archive (mirrors `SKILL_MANIFEST_FILE` in `apps/chat-api/src/skills/utils/skill-path.util.ts`). */
|
|
106
126
|
export declare const SKILL_MANIFEST_FILE = "SKILL.md";
|
|
107
127
|
|
|
128
|
+
/** Length limit of each skill editor text field. */
|
|
129
|
+
export declare const SKILL_TEXT_FIELD_MAX_LENGTHS: Record<SkillTextField, number>;
|
|
130
|
+
|
|
108
131
|
/**
|
|
109
132
|
* Client-side mirror of the backend's default `SKILL_UPLOAD_MAX_FILES`
|
|
110
133
|
* (`apps/chat-api/src/config/environment.config.ts`), used only for
|
|
@@ -192,6 +215,8 @@ export declare interface SkillEditorSubmitClient {
|
|
|
192
215
|
export declare interface SkillEditorSubmitMessages {
|
|
193
216
|
/** Shown when a required field is empty. */
|
|
194
217
|
required: string;
|
|
218
|
+
/** Shown when a name, description or instructions value exceeds its length limit, given that limit. */
|
|
219
|
+
tooLong: (maxLength: number) => string;
|
|
195
220
|
/**
|
|
196
221
|
* Shown when the Instructions value opens with its own YAML frontmatter
|
|
197
222
|
* block — pasting a whole `SKILL.md` in there would otherwise produce a
|
|
@@ -327,6 +352,9 @@ export declare interface SkillFilesPayload {
|
|
|
327
352
|
*/
|
|
328
353
|
export declare const skillFileToAttachment: (node: SkillFileTreeNode, content: SkillFileContent) => Attachment;
|
|
329
354
|
|
|
355
|
+
/** Returns the folder path a marker path stands for (`docs/.dial_folder` → `docs`). */
|
|
356
|
+
export declare const skillFolderMarkerParent: (markerPath: string) => string;
|
|
357
|
+
|
|
330
358
|
/** A `SKILL.md` split into its frontmatter fields and its prose body. */
|
|
331
359
|
export declare interface SkillManifestDocument {
|
|
332
360
|
/** `name` frontmatter field, when present and a string. */
|
|
@@ -363,6 +391,9 @@ export declare interface SkillManifestValues {
|
|
|
363
391
|
instructions: string;
|
|
364
392
|
}
|
|
365
393
|
|
|
394
|
+
/** Skill editor text fields with a length limit. */
|
|
395
|
+
export declare type SkillTextField = 'name' | 'description' | 'instructions';
|
|
396
|
+
|
|
366
397
|
/**
|
|
367
398
|
* Answers one question: would appending this text after the fence that
|
|
368
399
|
* `buildSkillManifest` writes produce a *second* frontmatter block?
|
|
@@ -391,21 +422,24 @@ declare type SubmitPhase = 'idle' | 'submitting' | 'success' | 'failure';
|
|
|
391
422
|
export declare interface UnpackedSkillArchive {
|
|
392
423
|
/** The root `SKILL.md` entry's decoded text content. */
|
|
393
424
|
manifestText: string;
|
|
394
|
-
/** Every non-manifest entry, keyed by relative path. */
|
|
425
|
+
/** Every non-manifest, non-marker entry, keyed by relative path. */
|
|
395
426
|
files: Map<string, Uint8Array>;
|
|
427
|
+
/** Folder paths restored from `<folder>/.dial_folder` marker entries. */
|
|
428
|
+
folders: string[];
|
|
396
429
|
}
|
|
397
430
|
|
|
398
431
|
/**
|
|
399
432
|
* Unpacks a whole-skill ZIP (as downloaded from `GET /api/v1/skills/download`
|
|
400
433
|
* — DIAL Core's whole-resource `GET` is the one place this contract still
|
|
401
|
-
* uses a ZIP, per design.md) into its manifest text
|
|
402
|
-
* bytes
|
|
434
|
+
* uses a ZIP, per `openspec/changes/archive/2026-10-05-persist-skill-empty-folders/design.md`) into its manifest text, every other entry's
|
|
435
|
+
* bytes, and the folders its empty-folder markers stand for. Throws if the
|
|
436
|
+
* archive has no root `SKILL.md` entry.
|
|
403
437
|
*/
|
|
404
438
|
export declare const unpackSkillArchive: (bytes: Uint8Array) => UnpackedSkillArchive;
|
|
405
439
|
|
|
406
440
|
/**
|
|
407
441
|
* Headless controller for the skill-archive upload flow: dialog visibility, the exact-filename
|
|
408
|
-
* precheck, in-flight exclusion, and import completion. The host supplies the configured request
|
|
442
|
+
* precheck, in-flight exclusion, abort-on-close, and import completion. The host supplies the configured request
|
|
409
443
|
* and observes completion/failure through the injected callbacks; the hook never imports app
|
|
410
444
|
* contexts, i18n, or a configured API client.
|
|
411
445
|
*/
|
|
@@ -413,8 +447,8 @@ export declare const useSkillArchiveImport: <TResult>({ importArchive, onImporte
|
|
|
413
447
|
|
|
414
448
|
/** Options accepted by {@link useSkillArchiveImport}. */
|
|
415
449
|
export declare interface UseSkillArchiveImportOptions<TResult> {
|
|
416
|
-
/** Submits the selected archive; the host owns
|
|
417
|
-
importArchive: (file: File) => Promise<TResult>;
|
|
450
|
+
/** Submits the selected archive; the host owns the client. `signal` aborts when the dialog closes or the hook unmounts mid-upload. */
|
|
451
|
+
importArchive: (file: File, signal: AbortSignal) => Promise<TResult>;
|
|
418
452
|
/** Called once after a successful import (and any awaited host follow-up) settles. */
|
|
419
453
|
onImported: (result: TResult) => void | Promise<void>;
|
|
420
454
|
/** Called once when the import request, or the host's follow-up in {@link onImported}, fails. */
|
|
@@ -429,13 +463,15 @@ export declare interface UseSkillArchiveImportResult {
|
|
|
429
463
|
isDialogOpen: boolean;
|
|
430
464
|
/** Current phase of the import. */
|
|
431
465
|
status: SkillArchiveImportStatus;
|
|
466
|
+
/** Whether an import request is in flight; the dialog stays open until it succeeds. */
|
|
467
|
+
isUploading: boolean;
|
|
432
468
|
/** Reason the current/last selection was rejected locally; `undefined` once cleared. */
|
|
433
469
|
selectionRejectionReason: SkillArchiveSelectionRejectionReason | undefined;
|
|
434
470
|
/** Classified failure of the last import request; `undefined` outside a request failure. */
|
|
435
471
|
errorKind: SkillArchiveImportErrorKind | undefined;
|
|
436
|
-
/** Opens the dialog
|
|
472
|
+
/** Opens the dialog and clears any previous rejection or request failure. */
|
|
437
473
|
openDialog: () => void;
|
|
438
|
-
/** Closes the dialog and clears any rejection reason. */
|
|
474
|
+
/** Closes the dialog, aborting an in-flight import, and clears any rejection reason. */
|
|
439
475
|
closeDialog: () => void;
|
|
440
476
|
/** Wire to the dialog drop zone's `onChange`. */
|
|
441
477
|
handleFilesSelected: (files: File[]) => void;
|
|
@@ -494,7 +530,7 @@ export declare interface UseSkillEditorLoadResult {
|
|
|
494
530
|
* `client.createSkill`/`client.updateSkill`, and mapping the resulting
|
|
495
531
|
* success/error/conflict outcomes to presentable state.
|
|
496
532
|
*/
|
|
497
|
-
export declare const useSkillEditorSubmit: ({ bucket, isEditMode, files, filesContentRef, frontmatterRef, loadedPathRef, etagRef, returnUrl, refetchSkills, client, messages, onNavigate, onNotify, }: UseSkillEditorSubmitParams) => UseSkillEditorSubmitResult;
|
|
533
|
+
export declare const useSkillEditorSubmit: ({ bucket, isEditMode, files, filesContentRef, frontmatterRef, loadedPathRef, etagRef, returnUrl, getCreateReturnUrl, refetchSkills, client, messages, onNavigate, onNotify, }: UseSkillEditorSubmitParams) => UseSkillEditorSubmitResult;
|
|
498
534
|
|
|
499
535
|
/** Parameters accepted by {@link useSkillEditorSubmit}. */
|
|
500
536
|
export declare interface UseSkillEditorSubmitParams {
|
|
@@ -514,6 +550,8 @@ export declare interface UseSkillEditorSubmitParams {
|
|
|
514
550
|
etagRef: React.MutableRefObject<string | undefined>;
|
|
515
551
|
/** Where to navigate on a successful save. */
|
|
516
552
|
returnUrl: string;
|
|
553
|
+
/** Resolves the destination after creation from the normalized skill path. Defaults to `returnUrl`. */
|
|
554
|
+
getCreateReturnUrl?: (path: string) => string;
|
|
517
555
|
/** Refetches the host's skill listing after a successful save. */
|
|
518
556
|
refetchSkills: () => Promise<void>;
|
|
519
557
|
/** Already-configured create/update operations. */
|
|
@@ -534,6 +572,10 @@ export declare interface UseSkillEditorSubmitResult {
|
|
|
534
572
|
errors: SkillEditorErrors;
|
|
535
573
|
/** General submit-time error, distinct from a stale-edit `conflict`. */
|
|
536
574
|
submitError: string | undefined;
|
|
575
|
+
/** Whether `submitError` was caused by something a plain re-send can clear, rather than by the submission itself. */
|
|
576
|
+
isSubmitErrorRetryable: boolean;
|
|
577
|
+
/** Re-submits the values of the attempt that produced `submitError`. No-op before the first submit. */
|
|
578
|
+
retrySubmit: () => void;
|
|
537
579
|
/** Present when the last save hit a stale-ETag conflict. */
|
|
538
580
|
conflict: {
|
|
539
581
|
message: string;
|
|
@@ -553,10 +595,11 @@ export declare interface UseSkillEditorSubmitResult {
|
|
|
553
595
|
/**
|
|
554
596
|
* Owns the Skill Editor's batch file upload workflow: validating a staged
|
|
555
597
|
* batch, committing it atomically (supporting files plus an optional
|
|
556
|
-
* `SKILL.md` manifest import, with a confirmation gate),
|
|
598
|
+
* `SKILL.md` manifest import, with a confirmation gate), creating empty
|
|
599
|
+
* folders, expanding `.zip` archives for staging, and removing
|
|
557
600
|
* already-committed nodes.
|
|
558
601
|
*/
|
|
559
|
-
export declare const useSkillFileActions: ({ files, setFiles, filesContentRef, frontmatterRef, loadedValues, setLoadedValues, isEditMode, isDirty, setSelectedPath, messages, }: UseSkillFileActionsParams) => UseSkillFileActionsResult;
|
|
602
|
+
export declare const useSkillFileActions: ({ files, setFiles, filesContentRef, frontmatterRef, loadedValues, setLoadedValues, isEditMode, isDirty, setSelectedPath, messages, pickFromFileSystem, }: UseSkillFileActionsParams) => UseSkillFileActionsResult;
|
|
560
603
|
|
|
561
604
|
/** Parameters accepted by {@link useSkillFileActions}. */
|
|
562
605
|
export declare interface UseSkillFileActionsParams {
|
|
@@ -580,6 +623,12 @@ export declare interface UseSkillFileActionsParams {
|
|
|
580
623
|
setSelectedPath: Dispatch<SetStateAction<string>>;
|
|
581
624
|
/** Localized messages, resolved by the host. */
|
|
582
625
|
messages: SkillFileActionsMessages;
|
|
626
|
+
/**
|
|
627
|
+
* Opens the host's file-system picker; passed through unchanged as
|
|
628
|
+
* `fileActions.pickFromFileSystem`. Omit to hide the editor's "Open DIAL
|
|
629
|
+
* file system" entry.
|
|
630
|
+
*/
|
|
631
|
+
pickFromFileSystem?: () => Promise<SkillFileSourceEntry[] | undefined>;
|
|
583
632
|
}
|
|
584
633
|
|
|
585
634
|
/** Return value of {@link useSkillFileActions}. */
|
package/skill-editor.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { SKILL_FILE_UPLOAD_MAX_BYTES as e,
|
|
2
|
-
import { parseSkillManifestDocument as
|
|
3
|
-
import { validateSkillFileBatch as
|
|
4
|
-
import { skillFileToAttachment as
|
|
5
|
-
import { SkillEditorLoadState as
|
|
6
|
-
import { useSkillEditorSubmit as
|
|
7
|
-
import { useSkillFileActions as
|
|
8
|
-
import { SkillArchiveImportErrorKind as
|
|
9
|
-
export { e as SKILL_FILE_UPLOAD_MAX_BYTES, t as
|
|
1
|
+
import { SKILL_FILE_UPLOAD_MAX_BYTES as e, SKILL_FOLDER_MARKER as t, SKILL_MANIFEST_FILE as n, SKILL_TEXT_FIELD_MAX_LENGTHS as r, SKILL_UPLOAD_MAX_FILES as i, SKILL_UPLOAD_MAX_TOTAL_BYTES as a, buildSkillFilesPayload as o, buildSkillManifest as s, buildSkillManifestForSubmit as c, buildSkillManifestFromFrontmatter as l, getSkillFieldLengthViolations as u, isSkillFolderMarkerPath as d, isValidSkillRelativePath as f, nameFromPath as p, normalizeSkillName as m, parseSkillManifest as h, skillFileBytesToBlob as g, skillFolderMarkerParent as _, startsWithFrontmatterBlock as v, unpackSkillArchive as y } from "./skill/skill.js";
|
|
2
|
+
import { parseSkillManifestDocument as b } from "./skill/skill-manifest.js";
|
|
3
|
+
import { validateSkillFileBatch as x } from "./skill/skill-file-batch-validation.js";
|
|
4
|
+
import { skillFileToAttachment as S } from "./skill/skill-file-preview.js";
|
|
5
|
+
import { SkillEditorLoadState as C, useSkillEditorLoad as w } from "./skill/useSkillEditorLoad.js";
|
|
6
|
+
import { useSkillEditorSubmit as T } from "./skill/useSkillEditorSubmit.js";
|
|
7
|
+
import { useSkillFileActions as E } from "./skill/useSkillFileActions.js";
|
|
8
|
+
import { SkillArchiveImportErrorKind as D, SkillArchiveImportStatus as O, SkillArchiveSelectionRejectionReason as k, classifySkillArchiveImportError as A, useSkillArchiveImport as j } from "./skill/useSkillArchiveImport/useSkillArchiveImport.js";
|
|
9
|
+
export { e as SKILL_FILE_UPLOAD_MAX_BYTES, t as SKILL_FOLDER_MARKER, n as SKILL_MANIFEST_FILE, r as SKILL_TEXT_FIELD_MAX_LENGTHS, i as SKILL_UPLOAD_MAX_FILES, a as SKILL_UPLOAD_MAX_TOTAL_BYTES, D as SkillArchiveImportErrorKind, O as SkillArchiveImportStatus, k as SkillArchiveSelectionRejectionReason, C as SkillEditorLoadState, o as buildSkillFilesPayload, s as buildSkillManifest, c as buildSkillManifestForSubmit, l as buildSkillManifestFromFrontmatter, A as classifySkillArchiveImportError, u as getSkillFieldLengthViolations, d as isSkillFolderMarkerPath, f as isValidSkillRelativePath, p as nameFromPath, m as normalizeSkillName, h as parseSkillManifest, b as parseSkillManifestDocument, g as skillFileBytesToBlob, S as skillFileToAttachment, _ as skillFolderMarkerParent, v as startsWithFrontmatterBlock, y as unpackSkillArchive, j as useSkillArchiveImport, w as useSkillEditorLoad, T as useSkillEditorSubmit, E as useSkillFileActions, x as validateSkillFileBatch };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { normalizeDeploymentId as e } from "../catalog/deployment-id.js";
|
|
2
|
+
import { formatCost as t } from "@epam/ai-dial-chat-shared";
|
|
3
|
+
import { DeploymentItemDtoTypeEnum as n } from "@epam/ai-dial-chat-api-client";
|
|
4
|
+
import { ModelLimitMetricKind as r, ModelLimitStatus as i } from "@epam/ai-dial-usage-dashboard";
|
|
4
5
|
//#region src/usage/map-user-usage-to-model-limits.ts
|
|
5
|
-
var
|
|
6
|
+
var a = 2 ** 53, o = 75, s = new Intl.NumberFormat(void 0, {
|
|
6
7
|
notation: "compact",
|
|
7
8
|
maximumFractionDigits: 1
|
|
8
|
-
}),
|
|
9
|
+
}), c = new Intl.NumberFormat(void 0, { maximumFractionDigits: 2 }), l = {
|
|
9
10
|
todayPeriodDescription: "usage.todayPeriodDescription",
|
|
10
11
|
thisWeekPeriodDescription: "usage.thisWeekPeriodDescription",
|
|
11
12
|
thisMonthPeriodDescription: "usage.thisMonthPeriodDescription",
|
|
@@ -17,8 +18,10 @@ var i = 2 ** 53, a = 75, o = new Intl.NumberFormat(void 0, {
|
|
|
17
18
|
followsCostLimitAriaLabel: "usage.followsCostLimitAriaLabel",
|
|
18
19
|
unlimitedProgressAriaLabel: "usage.unlimitedProgressAriaLabel",
|
|
19
20
|
progressAriaLabel: "usage.progressAriaLabel",
|
|
20
|
-
spentLabel: "usage.spentLabel"
|
|
21
|
-
|
|
21
|
+
spentLabel: "usage.spentLabel",
|
|
22
|
+
applicationTypeLabel: "usage.applicationTypeLabel",
|
|
23
|
+
includesCalledModelsLabel: "usage.includesCalledModelsLabel"
|
|
24
|
+
}, u = {
|
|
22
25
|
day: {
|
|
23
26
|
cost: "dayCostStats",
|
|
24
27
|
tokens: "dayTokenStats"
|
|
@@ -31,130 +34,169 @@ var i = 2 ** 53, a = 75, o = new Intl.NumberFormat(void 0, {
|
|
|
31
34
|
cost: "monthCostStats",
|
|
32
35
|
tokens: "monthTokenStats"
|
|
33
36
|
}
|
|
34
|
-
},
|
|
37
|
+
}, d = {
|
|
35
38
|
day: {
|
|
36
39
|
field: "dayCostStats",
|
|
37
|
-
labelKey:
|
|
40
|
+
labelKey: l.todayPeriodDescription
|
|
38
41
|
},
|
|
39
42
|
week: {
|
|
40
43
|
field: "weekCostStats",
|
|
41
|
-
labelKey:
|
|
44
|
+
labelKey: l.thisWeekPeriodDescription
|
|
42
45
|
},
|
|
43
46
|
month: {
|
|
44
47
|
field: "monthCostStats",
|
|
45
|
-
labelKey:
|
|
48
|
+
labelKey: l.thisMonthPeriodDescription
|
|
46
49
|
}
|
|
47
|
-
},
|
|
48
|
-
if (!
|
|
49
|
-
if (e.total >=
|
|
50
|
+
}, f = (e) => e != null && Number.isFinite(e.total) && Number.isFinite(e.used), p = (e) => e >= 100 ? i.LimitReached : e >= o ? i.RunningLow : i.WithinLimits, m = (e) => {
|
|
51
|
+
if (!f(e)) return i.Unavailable;
|
|
52
|
+
if (e.total >= a) return i.NoLimit;
|
|
50
53
|
let t = Math.max(0, e.used), n = Math.max(0, e.total);
|
|
51
|
-
return
|
|
52
|
-
},
|
|
53
|
-
let o = e?.[t.field], s =
|
|
54
|
+
return p(n > 0 ? t / n * 100 : 100);
|
|
55
|
+
}, h = (e) => e === i.WithinLimits || e === i.RunningLow || e === i.LimitReached, g = (e, t, n, r, a) => {
|
|
56
|
+
let o = e?.[t.field], s = m(o), c = a(o?.resetsAt), u = r(t.labelKey).toLocaleLowerCase(n);
|
|
54
57
|
return {
|
|
55
58
|
status: s,
|
|
56
|
-
tooltipLabel: s ===
|
|
57
|
-
...
|
|
58
|
-
resetLabel:
|
|
59
|
-
resetIsoValue:
|
|
60
|
-
resetAriaLabel:
|
|
59
|
+
tooltipLabel: s === i.LimitReached ? r(l.overallCostLimitReachedTooltip, { period: u }) : s === i.RunningLow ? r(l.overallCostLimitRunningLowTooltip, { period: u }) : void 0,
|
|
60
|
+
...c ? {
|
|
61
|
+
resetLabel: c.label,
|
|
62
|
+
resetIsoValue: c.isoValue,
|
|
63
|
+
resetAriaLabel: c.ariaLabel
|
|
61
64
|
} : {}
|
|
62
65
|
};
|
|
63
|
-
},
|
|
64
|
-
day:
|
|
65
|
-
week:
|
|
66
|
-
month:
|
|
67
|
-
}),
|
|
68
|
-
kind:
|
|
69
|
-
ariaLabel: e(
|
|
70
|
-
}),
|
|
71
|
-
if (!
|
|
72
|
-
let
|
|
73
|
-
if (e.total >=
|
|
74
|
-
let e =
|
|
66
|
+
}, _ = () => void 0, v = (e, t, n, r = _) => ({
|
|
67
|
+
day: g(e, d.day, t, n, r),
|
|
68
|
+
week: g(e, d.week, t, n, r),
|
|
69
|
+
month: g(e, d.month, t, n, r)
|
|
70
|
+
}), y = (e) => ({
|
|
71
|
+
kind: r.Unavailable,
|
|
72
|
+
ariaLabel: e(l.unavailableLabel)
|
|
73
|
+
}), b = (e, t, n) => {
|
|
74
|
+
if (!f(e)) return y(n);
|
|
75
|
+
let i = Math.max(0, e.used), o = s.format(i);
|
|
76
|
+
if (e.total >= a) {
|
|
77
|
+
let e = h(t);
|
|
75
78
|
return {
|
|
76
|
-
kind:
|
|
77
|
-
usedLabel:
|
|
78
|
-
supportingLabel:
|
|
79
|
-
ariaLabel:
|
|
79
|
+
kind: r.Unlimited,
|
|
80
|
+
usedLabel: o,
|
|
81
|
+
supportingLabel: n(e ? l.followsCostLimitLabel : l.noLimitLabel),
|
|
82
|
+
ariaLabel: n(e ? l.followsCostLimitAriaLabel : l.unlimitedProgressAriaLabel, { used: c.format(i) })
|
|
80
83
|
};
|
|
81
84
|
}
|
|
82
|
-
let u = Math.max(e.total, 0),
|
|
85
|
+
let u = Math.max(e.total, 0), d = s.format(u), m = u > 0 ? i / u * 100 : 100, g = p(m);
|
|
83
86
|
return {
|
|
84
|
-
kind:
|
|
85
|
-
usedLabel:
|
|
86
|
-
totalLabel:
|
|
87
|
-
usedPercent:
|
|
87
|
+
kind: r.Finite,
|
|
88
|
+
usedLabel: o,
|
|
89
|
+
totalLabel: d,
|
|
90
|
+
usedPercent: m,
|
|
88
91
|
status: g,
|
|
89
|
-
ariaLabel:
|
|
90
|
-
used:
|
|
91
|
-
total:
|
|
92
|
-
percent: Math.round(
|
|
92
|
+
ariaLabel: n(l.progressAriaLabel, {
|
|
93
|
+
used: c.format(i),
|
|
94
|
+
total: c.format(u),
|
|
95
|
+
percent: Math.round(m)
|
|
93
96
|
})
|
|
94
97
|
};
|
|
95
|
-
},
|
|
96
|
-
if (!
|
|
97
|
-
let
|
|
98
|
-
if (
|
|
99
|
-
kind:
|
|
98
|
+
}, x = (e, n) => {
|
|
99
|
+
if (!f(e)) return y(n);
|
|
100
|
+
let i = Math.max(0, e.used), o = n(l.spentLabel, { amount: t(i) });
|
|
101
|
+
if (e.total >= a) return {
|
|
102
|
+
kind: r.Unlimited,
|
|
100
103
|
usedLabel: o,
|
|
101
104
|
ariaLabel: o
|
|
102
105
|
};
|
|
103
|
-
let s = Math.max(
|
|
106
|
+
let s = Math.max(e.total, 0), c = s > 0 ? i / s * 100 : 100;
|
|
104
107
|
return {
|
|
105
|
-
kind:
|
|
108
|
+
kind: r.Finite,
|
|
106
109
|
usedLabel: o,
|
|
107
|
-
totalLabel:
|
|
108
|
-
usedPercent:
|
|
109
|
-
status:
|
|
110
|
-
ariaLabel:
|
|
111
|
-
used:
|
|
112
|
-
total:
|
|
113
|
-
percent: Math.round(
|
|
110
|
+
totalLabel: t(s),
|
|
111
|
+
usedPercent: c,
|
|
112
|
+
status: p(c),
|
|
113
|
+
ariaLabel: n(l.progressAriaLabel, {
|
|
114
|
+
used: t(i),
|
|
115
|
+
total: t(s),
|
|
116
|
+
percent: Math.round(c)
|
|
114
117
|
})
|
|
115
118
|
};
|
|
116
|
-
},
|
|
117
|
-
tokens:
|
|
118
|
-
cost:
|
|
119
|
-
}),
|
|
119
|
+
}, S = (e, t, n, r) => ({
|
|
120
|
+
tokens: b(e[t.tokens], n, r),
|
|
121
|
+
cost: x(e[t.cost], r)
|
|
122
|
+
}), C = (e) => e.filter((e) => e.kind === r.Finite).map((e) => e.status), w = (e, t, n) => {
|
|
120
123
|
let a = [
|
|
121
|
-
...
|
|
122
|
-
...
|
|
123
|
-
...
|
|
124
|
-
].filter((e) => e != null &&
|
|
125
|
-
return a.includes(
|
|
126
|
-
},
|
|
127
|
-
let
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
124
|
+
...C(e),
|
|
125
|
+
...C(t),
|
|
126
|
+
...n
|
|
127
|
+
].filter((e) => e != null && h(e));
|
|
128
|
+
return a.includes(i.LimitReached) ? i.LimitReached : a.includes(i.RunningLow) ? i.RunningLow : a.includes(i.WithinLimits) ? i.WithinLimits : e.some((e) => e.kind === r.Unlimited) || n.includes(i.NoLimit) ? i.NoLimit : i.Unavailable;
|
|
129
|
+
}, T = (e, t, n) => {
|
|
130
|
+
let i = x(e[t.cost], n);
|
|
131
|
+
return {
|
|
132
|
+
tokens: y(n),
|
|
133
|
+
cost: i.kind === r.Unlimited ? {
|
|
134
|
+
...i,
|
|
135
|
+
supportingLabel: n(l.includesCalledModelsLabel)
|
|
136
|
+
} : i
|
|
137
|
+
};
|
|
138
|
+
}, E = (e) => e.some((e) => f(e) && e.used > 0), D = (t, r, i, a, o, s) => {
|
|
139
|
+
let c = t?.deployments;
|
|
140
|
+
if (c == null) return [];
|
|
141
|
+
let d = new Map(r.filter((e) => e.type === n.Model || e.type === n.Application).map((t) => [e(t.id), t])), f = v(t, i, a);
|
|
142
|
+
return Object.keys(c).map((t) => {
|
|
143
|
+
let r = d.get(e(t)), p = r == null ? t : s(r.displayName, i) || r.id, m = c[t], h = o(r?.iconUrl);
|
|
144
|
+
if (r?.type === n.Application) {
|
|
145
|
+
let e = T(m, u.day, a), n = T(m, u.week, a), i = T(m, u.month, a);
|
|
146
|
+
return {
|
|
147
|
+
row: {
|
|
148
|
+
id: t,
|
|
149
|
+
name: p,
|
|
150
|
+
version: r.displayVersion,
|
|
151
|
+
avatarSrc: h,
|
|
152
|
+
typeLabel: a(l.applicationTypeLabel),
|
|
153
|
+
day: e,
|
|
154
|
+
week: n,
|
|
155
|
+
month: i,
|
|
156
|
+
status: w([
|
|
157
|
+
e.tokens,
|
|
158
|
+
n.tokens,
|
|
159
|
+
i.tokens
|
|
160
|
+
], [
|
|
161
|
+
e.cost,
|
|
162
|
+
n.cost,
|
|
163
|
+
i.cost
|
|
164
|
+
], [
|
|
165
|
+
f.day.status,
|
|
166
|
+
f.week.status,
|
|
167
|
+
f.month.status
|
|
168
|
+
])
|
|
169
|
+
},
|
|
170
|
+
hasUsage: E(Object.values(u).map(({ cost: e }) => m[e]))
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
let g = S(m, u.day, f.day.status, a), _ = S(m, u.week, f.week.status, a), v = S(m, u.month, f.month.status, a), y = Object.values(u).flatMap(({ cost: e, tokens: t }) => [m[e], m[t]]);
|
|
132
174
|
return {
|
|
133
175
|
row: {
|
|
134
|
-
id:
|
|
135
|
-
name:
|
|
136
|
-
version:
|
|
137
|
-
avatarSrc:
|
|
138
|
-
day:
|
|
139
|
-
week:
|
|
140
|
-
month:
|
|
141
|
-
status:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
176
|
+
id: t,
|
|
177
|
+
name: p,
|
|
178
|
+
version: r?.displayVersion,
|
|
179
|
+
avatarSrc: h,
|
|
180
|
+
day: g,
|
|
181
|
+
week: _,
|
|
182
|
+
month: v,
|
|
183
|
+
status: w([
|
|
184
|
+
g.tokens,
|
|
185
|
+
_.tokens,
|
|
186
|
+
v.tokens
|
|
145
187
|
], [
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
188
|
+
g.cost,
|
|
189
|
+
_.cost,
|
|
190
|
+
v.cost
|
|
149
191
|
], [
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
192
|
+
f.day.status,
|
|
193
|
+
f.week.status,
|
|
194
|
+
f.month.status
|
|
153
195
|
])
|
|
154
196
|
},
|
|
155
|
-
hasUsage:
|
|
197
|
+
hasUsage: E(y)
|
|
156
198
|
};
|
|
157
199
|
}).filter(({ hasUsage: e }) => e).map(({ row: e }) => e);
|
|
158
200
|
};
|
|
159
201
|
//#endregion
|
|
160
|
-
export {
|
|
202
|
+
export { l as USAGE_MODEL_LIMITS_I18N_KEYS, v as mapOverallCostLimitsToPeriodStatuses, D as mapUserUsageToModelLimits };
|
package/usage.d.ts
CHANGED
|
@@ -23,9 +23,10 @@ export declare const mapOverallCostLimitsToPeriodStatuses: (usage: UserLimitStat
|
|
|
23
23
|
export declare const mapUsageDataToDashboard: (usage: UserLimitStatsResponseDto | undefined, t: Translate, formatResetTime: FormatResetTime) => UsageLimitCardData[];
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Maps `usage.deployments` into `ModelLimitsSection`'s `rows` prop, joined with model
|
|
27
|
-
* from `deploymentItems`. Rows are included only when any displayed period stat has nonzero
|
|
28
|
-
* Order follows `Object.keys(deployments)` —
|
|
26
|
+
* Maps `usage.deployments` into `ModelLimitsSection`'s `rows` prop, joined with model or application
|
|
27
|
+
* identity from `deploymentItems`. Rows are included only when any displayed period stat has nonzero
|
|
28
|
+
* usage (Cost stats only, for an application). Order follows `Object.keys(deployments)` —
|
|
29
|
+
* `deploymentItems` is enrichment-only.
|
|
29
30
|
*
|
|
30
31
|
* @param resolveIconUrl - Resolves a deployment's raw `iconUrl` to the URL the avatar should load.
|
|
31
32
|
* @param resolveDisplayName - Resolves a localized-text map or plain string to the display name for `activeLocale`.
|
|
@@ -115,6 +116,10 @@ export declare const USAGE_MODEL_LIMITS_I18N_KEYS: {
|
|
|
115
116
|
readonly progressAriaLabel: "usage.progressAriaLabel";
|
|
116
117
|
/** Label for the spent-cost cell. Receives `{ amount: string }`. */
|
|
117
118
|
readonly spentLabel: "usage.spentLabel";
|
|
119
|
+
/** Type caption for an application (agent) row. Receives no interpolation. */
|
|
120
|
+
readonly applicationTypeLabel: "usage.applicationTypeLabel";
|
|
121
|
+
/** Supporting label on an application row's spent cost. Receives no interpolation. */
|
|
122
|
+
readonly includesCalledModelsLabel: "usage.includesCalledModelsLabel";
|
|
118
123
|
};
|
|
119
124
|
|
|
120
125
|
export { }
|
|
@@ -6,8 +6,8 @@ var a = (a = !0, o = !0) => {
|
|
|
6
6
|
f.current = a, p.current = o, o || (d.current = 0, c(!1));
|
|
7
7
|
}, [a, o]);
|
|
8
8
|
let m = e(() => {
|
|
9
|
-
u(
|
|
10
|
-
}, []);
|
|
9
|
+
u((e) => e.filter((e) => !l.includes(e)));
|
|
10
|
+
}, [l]);
|
|
11
11
|
return t(() => {
|
|
12
12
|
let e = (e) => !!e.dataTransfer?.types.includes("Files"), t = (t) => {
|
|
13
13
|
!p.current || !e(t) || (d.current += 1, c(!0));
|
|
@@ -18,7 +18,7 @@ var a = (a = !0, o = !0) => {
|
|
|
18
18
|
}, i = (t) => {
|
|
19
19
|
if (!(!e(t) || !p.current) && (t.preventDefault(), d.current = 0, c(!1), f.current)) {
|
|
20
20
|
let e = Array.from(t.dataTransfer?.files ?? []);
|
|
21
|
-
e.length > 0 && u(e);
|
|
21
|
+
e.length > 0 && u((t) => [...t, ...e]);
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
return document.addEventListener("dragenter", t), document.addEventListener("dragleave", n), document.addEventListener("dragover", r), document.addEventListener("drop", i), () => {
|