@epam/ai-dial-chat-hooks 1.3.0-dev.304 → 1.3.0-dev.305

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 (39) hide show
  1. package/catalog/use-publish-history.d.ts +19 -0
  2. package/catalog/use-publish-history.d.ts.map +1 -0
  3. package/catalog/use-publish-history.js +25 -0
  4. package/catalog.js +19 -18
  5. package/conversation/conversation-data-source.d.ts +47 -0
  6. package/conversation/conversation-data-source.d.ts.map +1 -0
  7. package/conversation/conversation-data-source.js +11 -0
  8. package/conversation/useConversationExport/useConversationExport.d.ts.map +1 -1
  9. package/conversation/useConversationExport/useConversationExport.js +76 -84
  10. package/conversation.js +33 -32
  11. package/entry-points/catalog.d.ts +1 -0
  12. package/entry-points/catalog.d.ts.map +1 -1
  13. package/entry-points/conversation.d.ts +1 -0
  14. package/entry-points/conversation.d.ts.map +1 -1
  15. package/entry-points/project.d.ts +5 -0
  16. package/entry-points/project.d.ts.map +1 -1
  17. package/index.d.ts +7 -0
  18. package/index.d.ts.map +1 -1
  19. package/index.js +189 -182
  20. package/package.json +17 -17
  21. package/project/create-project-chat.d.ts +34 -0
  22. package/project/create-project-chat.d.ts.map +1 -0
  23. package/project/create-project-chat.js +27 -0
  24. package/project/project-conversation-data-source.d.ts +36 -0
  25. package/project/project-conversation-data-source.d.ts.map +1 -0
  26. package/project/project-conversation-data-source.js +67 -0
  27. package/project/project-file-preview.d.ts +28 -0
  28. package/project/project-file-preview.d.ts.map +1 -0
  29. package/project/project-file-preview.js +20 -0
  30. package/project/use-project-draft.d.ts +46 -0
  31. package/project/use-project-draft.d.ts.map +1 -0
  32. package/project/use-project-draft.js +54 -0
  33. package/project/use-project-file-preview.d.ts +42 -0
  34. package/project/use-project-file-preview.d.ts.map +1 -0
  35. package/project/use-project-file-preview.js +46 -0
  36. package/project.js +15 -10
  37. package/shared/sleep.d.ts +3 -0
  38. package/shared/sleep.d.ts.map +1 -0
  39. package/shared/sleep.js +13 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@epam/ai-dial-chat-hooks",
3
3
  "description": "Framework-level React hooks extracted from AI DIAL Chat for building custom chat interfaces",
4
- "version": "1.3.0-dev.304",
4
+ "version": "1.3.0-dev.305",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "./index.js",
@@ -131,7 +131,7 @@
131
131
  }
132
132
  },
133
133
  "dependencies": {
134
- "@epam/ai-dial-chat-api-client": "1.3.0-dev.304",
134
+ "@epam/ai-dial-chat-api-client": "1.3.0-dev.305",
135
135
  "dompurify": "3.4.17",
136
136
  "fflate": "^0.8.3",
137
137
  "lru-cache": "^10.4.3",
@@ -140,23 +140,23 @@
140
140
  },
141
141
  "peerDependencies": {
142
142
  "react": "^19.2.8",
143
- "@epam/ai-dial-attachment-canvas": "1.3.0-dev.304",
144
- "@epam/ai-dial-attachment-input": "1.3.0-dev.304",
145
- "@epam/ai-dial-catalog": "1.3.0-dev.304",
146
- "@epam/ai-dial-chat-overlay": "1.3.0-dev.304",
147
- "@epam/ai-dial-chat-shared": "1.3.0-dev.304",
148
- "@epam/ai-dial-conversation-input": "1.3.0-dev.304",
149
- "@epam/ai-dial-mcp-apps": "1.3.0-dev.304",
150
- "@epam/ai-dial-projects": "1.3.0-dev.304",
151
- "@epam/ai-dial-publish-panel": "1.3.0-dev.304",
152
- "@epam/ai-dial-quotations": "1.3.0-dev.304",
143
+ "@epam/ai-dial-attachment-canvas": "1.3.0-dev.305",
144
+ "@epam/ai-dial-attachment-input": "1.3.0-dev.305",
145
+ "@epam/ai-dial-catalog": "1.3.0-dev.305",
146
+ "@epam/ai-dial-chat-overlay": "1.3.0-dev.305",
147
+ "@epam/ai-dial-chat-shared": "1.3.0-dev.305",
148
+ "@epam/ai-dial-conversation-input": "1.3.0-dev.305",
149
+ "@epam/ai-dial-mcp-apps": "1.3.0-dev.305",
150
+ "@epam/ai-dial-projects": "1.3.0-dev.305",
151
+ "@epam/ai-dial-publish-panel": "1.3.0-dev.305",
152
+ "@epam/ai-dial-quotations": "1.3.0-dev.305",
153
153
  "@epam/ai-dial-react-file-manager": "^0.4.0-dev.25",
154
- "@epam/ai-dial-scheduled-tasks": "1.3.0-dev.304",
155
- "@epam/ai-dial-share": "1.3.0-dev.304",
156
- "@epam/ai-dial-skill-editor": "1.3.0-dev.304",
157
- "@epam/ai-dial-source-panel": "1.3.0-dev.304",
154
+ "@epam/ai-dial-scheduled-tasks": "1.3.0-dev.305",
155
+ "@epam/ai-dial-share": "1.3.0-dev.305",
156
+ "@epam/ai-dial-skill-editor": "1.3.0-dev.305",
157
+ "@epam/ai-dial-source-panel": "1.3.0-dev.305",
158
158
  "@epam/ai-dial-ui-kit": "^0.16.0-dev.67",
159
- "@epam/ai-dial-usage-dashboard": "1.3.0-dev.304",
159
+ "@epam/ai-dial-usage-dashboard": "1.3.0-dev.305",
160
160
  "@modelcontextprotocol/sdk": "^1.32.2",
161
161
  "@epam/pdf-highlighter-kit": "^0.0.19"
162
162
  },
@@ -0,0 +1,34 @@
1
+ import { ConversationResponseDto } from '@epam/ai-dial-chat-api-client';
2
+ import { ChatSettingsValues } from '../useChatSettingsFormConfig/useChatSettingsFormConfig';
3
+ import { ConversationCreateRequest, ProjectsApiClient } from './projects-api-client';
4
+ /** Why creating a project chat failed, as the host explains it. */
5
+ export declare enum ProjectChatCreateFailure {
6
+ /** The project has no room left for another chat. */
7
+ StorageFull = "storage-full",
8
+ /** Any other failure. */
9
+ Failed = "failed"
10
+ }
11
+ /** A failed chat create, classified for the host's message. */
12
+ export interface ProjectChatCreateFailureDetails {
13
+ /** Why the create failed. */
14
+ failure: ProjectChatCreateFailure;
15
+ /** Trace id of the failed request, when the response carried one. */
16
+ requestId?: string;
17
+ }
18
+ /**
19
+ * Creates a project chat from its first message, saves the composer's chat
20
+ * settings onto it, and hands the saved chat to `onCreated` in every case where
21
+ * the chat exists, even when saving the settings fails (the chat exists either
22
+ * way, and opening it avoids a duplicate on retry). A failed save is rethrown
23
+ * after `onCreated` ran; a failed create rejects without calling it.
24
+ *
25
+ * @param client - Configured project requests, from `createProjectsApiClient`.
26
+ * @param projectId - The project's DIAL id.
27
+ * @param request - First message, deployment, attachments, tool configuration, form values and skills.
28
+ * @param settings - System prompt, temperature and response format saved onto the new chat.
29
+ * @param onCreated - Receives the chat with the settings applied, e.g. to open it.
30
+ */
31
+ export declare const createProjectChat: (client: Pick<ProjectsApiClient, "createProjectConversation" | "saveProjectConversation">, projectId: string, request: ConversationCreateRequest, settings: ChatSettingsValues, onCreated: (saved: ConversationResponseDto) => void) => Promise<ConversationResponseDto>;
32
+ /** Classifies a rejected project chat create as storage-full or a plain failure, with its trace id. */
33
+ export declare const classifyProjectChatCreateError: (error: unknown) => Promise<ProjectChatCreateFailureDetails>;
34
+ //# sourceMappingURL=create-project-chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-project-chat.d.ts","sourceRoot":"","sources":["../../src/project/create-project-chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wDAAwD,CAAC;AACjG,OAAO,KAAK,EACV,yBAAyB,EACzB,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAE/B,mEAAmE;AACnE,oBAAY,wBAAwB;IAClC,qDAAqD;IACrD,WAAW,iBAAiB;IAC5B,yBAAyB;IACzB,MAAM,WAAW;CAClB;AAED,+DAA+D;AAC/D,MAAM,WAAW,+BAA+B;IAC9C,6BAA6B;IAC7B,OAAO,EAAE,wBAAwB,CAAC;IAClC,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,IAAI,CACV,iBAAiB,EACjB,2BAA2B,GAAG,yBAAyB,CACxD,EACD,WAAW,MAAM,EACjB,SAAS,yBAAyB,EAClC,UAAU,kBAAkB,EAC5B,WAAW,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,KAClD,OAAO,CAAC,uBAAuB,CAiBjC,CAAC;AAEF,uGAAuG;AACvG,eAAO,MAAM,8BAA8B,GACzC,OAAO,OAAO,KACb,OAAO,CAAC,+BAA+B,CASzC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { getApiErrorDetails as e } from "../api-error/api-error.js";
2
+ import { ProjectCreateErrorCode as t } from "@epam/ai-dial-chat-api-client";
3
+ //#region src/project/create-project-chat.ts
4
+ var n = /* @__PURE__ */ function(e) {
5
+ return e.StorageFull = "storage-full", e.Failed = "failed", e;
6
+ }({}), r = async (e, t, n, r, i) => {
7
+ let a = await e.createProjectConversation(t, n), o = {
8
+ ...a,
9
+ prompt: r.systemPrompt,
10
+ temperature: r.temperature,
11
+ responseFormat: r.responseFormat
12
+ };
13
+ try {
14
+ await e.saveProjectConversation(a.id, o);
15
+ } finally {
16
+ i(o);
17
+ }
18
+ return o;
19
+ }, i = async (n) => {
20
+ let { code: r, traceId: i } = await e(n);
21
+ return {
22
+ failure: r === t.ProjectStorageFull ? "storage-full" : "failed",
23
+ requestId: i
24
+ };
25
+ };
26
+ //#endregion
27
+ export { n as ProjectChatCreateFailure, i as classifyProjectChatCreateError, r as createProjectChat };
@@ -0,0 +1,36 @@
1
+ import { ConversationDataSource } from '../conversation/conversation-data-source';
2
+ import { CreateChatStreamApiDeps } from '../conversation/create-chat-stream-api';
3
+ import { SerializedKeyedWriter } from '../shared/serialized-writer';
4
+ import { ProjectsApiClient } from './projects-api-client';
5
+ /** Host ports of {@link createProjectConversationDataSource}. */
6
+ export interface ProjectConversationDataSourceOptions {
7
+ /** The project's DIAL id. */
8
+ projectId: string;
9
+ /** Whether the caller owns the project; a conversation opens read-only without it. */
10
+ canEdit: boolean;
11
+ /** Configured project requests, from `createProjectsApiClient`; only the conversation requests are used. */
12
+ client: Pick<ProjectsApiClient, 'getProjectConversation' | 'saveProjectConversation' | 'deleteProjectConversation' | 'attachToProjectGeneration'>;
13
+ /** Where and how the completion stream is sent: the host's base path under the project, and its CSRF token store. */
14
+ stream: Pick<CreateChatStreamApiDeps, 'getCsrfToken' | 'setCsrfToken' | 'completionsBasePath'>;
15
+ /** The host's routes: a project conversation's page, and where a deleted or missing one goes. */
16
+ routes: {
17
+ /** Returns the page route of a conversation. */
18
+ getConversationRoute: (id: string) => string;
19
+ /** Returns the route a deleted or missing conversation navigates to. */
20
+ getExitRoute: () => string;
21
+ };
22
+ /** The queue viewed marks go through, shared with the host's other pages so they write one at a time. */
23
+ viewedWriter: SerializedKeyedWriter;
24
+ /** Translation key of the toast shown when the conversation cannot be loaded; the host resolves it. */
25
+ notFoundMessageKey?: string;
26
+ }
27
+ /**
28
+ * Returns the data source of a conversation stored inside a project: the
29
+ * project conversation requests for loads, saves and streams, the host's
30
+ * routes, read-only from `canEdit`, no sidebar list side effects and no
31
+ * Duplicate. A project chat has no sidebar row, so the open chat is marked
32
+ * viewed through `viewedWriter`, and a generation starting drops a mark still
33
+ * waiting for its chat.
34
+ */
35
+ export declare const createProjectConversationDataSource: ({ projectId, canEdit, client, stream, routes, viewedWriter, notFoundMessageKey, }: ProjectConversationDataSourceOptions) => ConversationDataSource;
36
+ //# sourceMappingURL=project-conversation-data-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-conversation-data-source.d.ts","sourceRoot":"","sources":["../../src/project/project-conversation-data-source.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,sBAAsB,EAE5B,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,wCAAwC,CAAC;AAGhD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAU/D,iEAAiE;AACjE,MAAM,WAAW,oCAAoC;IACnD,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,OAAO,EAAE,OAAO,CAAC;IACjB,4GAA4G;IAC5G,MAAM,EAAE,IAAI,CACV,iBAAiB,EACf,wBAAwB,GACxB,yBAAyB,GACzB,2BAA2B,GAC3B,2BAA2B,CAC9B,CAAC;IACF,qHAAqH;IACrH,MAAM,EAAE,IAAI,CACV,uBAAuB,EACvB,cAAc,GAAG,cAAc,GAAG,qBAAqB,CACxD,CAAC;IACF,iGAAiG;IACjG,MAAM,EAAE;QACN,gDAAgD;QAChD,oBAAoB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;QAC7C,wEAAwE;QACxE,YAAY,EAAE,MAAM,MAAM,CAAC;KAC5B,CAAC;IACF,yGAAyG;IACzG,YAAY,EAAE,qBAAqB,CAAC;IACpC,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAsED;;;;;;;GAOG;AACH,eAAO,MAAM,mCAAmC,GAAI,mFAQjD,oCAAoC,KAAG,sBAiEzC,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { createChatStreamApi as e } from "../conversation/create-chat-stream-api.js";
2
+ import { NO_CONVERSATION_LIST_SYNC as t } from "../conversation/conversation-data-source.js";
3
+ import { getBrowserTimezone as n } from "../shared/browser-timezone.js";
4
+ import { sleep as r } from "../shared/sleep.js";
5
+ //#region src/project/project-conversation-data-source.ts
6
+ var i = "projects/", a = 5, o = 2e3, s = 5e3, c = "data: {\"action\":\"UPDATE\"}\n\n", l = (e) => e.startsWith(i) ? e : `${i}${e}`, u = (e) => {
7
+ let t = new TextEncoder().encode(c);
8
+ return new ReadableStream({ async pull(n) {
9
+ await r(s, e), e.aborted ? n.close() : n.enqueue(t);
10
+ } }, { highWaterMark: 0 });
11
+ }, d = (e, t, n, i) => {
12
+ let s = new AbortController();
13
+ return (async () => {
14
+ for (let c = 0; c < a; c++) {
15
+ if (await r(o, s.signal), s.signal.aborted) return;
16
+ try {
17
+ let { name: r } = await e(t, s.signal);
18
+ if (s.signal.aborted) return;
19
+ if (r && r !== n) {
20
+ i(r);
21
+ return;
22
+ }
23
+ } catch {
24
+ if (s.signal.aborted) return;
25
+ }
26
+ }
27
+ })(), () => s.abort();
28
+ }, f = ({ projectId: r, canEdit: i, client: a, stream: o, routes: s, viewedWriter: c, notFoundMessageKey: f }) => {
29
+ let { streamCompletion: p, stopCompletion: m } = e({
30
+ ...o,
31
+ getTimezone: n
32
+ }), h = {
33
+ ...t,
34
+ markUnread: (e) => c.drop(e),
35
+ markViewed: async (e) => {
36
+ try {
37
+ await c.enqueue(e);
38
+ } catch {}
39
+ },
40
+ shouldMarkOpenChatViewed: !0
41
+ }, g = (e, t) => a.saveProjectConversation(l(e), t);
42
+ return {
43
+ transport: {
44
+ streamCompletion: p,
45
+ stopCompletion: m,
46
+ watchConversation: async (e, t) => u(t),
47
+ attachToGeneration: (e, t) => a.attachToProjectGeneration(r, e, t),
48
+ getConversation: async (e, t) => await a.getProjectConversation(e, t),
49
+ saveConversation: async (e, t) => await g(e, t)
50
+ },
51
+ getConversation: a.getProjectConversation,
52
+ saveConversation: g,
53
+ handlersApi: {
54
+ saveConversation: ({ path: e, saveConversationBodyDto: t }) => g(e, t.conversation),
55
+ deleteConversation: ({ path: e }) => a.deleteProjectConversation(l(e))
56
+ },
57
+ watchTitle: (e, t, n) => d(a.getProjectConversation, e, t, n),
58
+ getConversationRoute: s.getConversationRoute,
59
+ getExitRoute: s.getExitRoute,
60
+ isReadOnly: () => !i,
61
+ listSync: h,
62
+ canDuplicate: !1,
63
+ notFoundMessageKey: f
64
+ };
65
+ };
66
+ //#endregion
67
+ export { f as createProjectConversationDataSource };
@@ -0,0 +1,28 @@
1
+ import { DisplayAttachment } from '@epam/ai-dial-chat-shared';
2
+ import { ProjectContextFile, ProjectOutputItem } from '@epam/ai-dial-projects';
3
+ /** A project file card the page opens in the canvas: its card id, name and MIME type. */
4
+ export interface ProjectFileCard {
5
+ /** Id of the card on the page; also the attachment id. */
6
+ id: string;
7
+ /** File name shown in the canvas header. */
8
+ name: string;
9
+ /** MIME type of the file. */
10
+ contentType: string;
11
+ }
12
+ /** Builds the locator a canvas content resolver fetches for a project file, from the project id and the file name. The host owns the scheme. */
13
+ export type ProjectFileLocatorBuilder = (projectId: string, name: string) => string;
14
+ /** Returns the canvas key of a project file, `{scope}::{id}`; the scope keeps one file name in two projects apart. */
15
+ export declare const toProjectPreviewKey: (scope: string, id: string) => string;
16
+ /** Returns the card id behind a canvas key, or `undefined` when the key belongs to another scope or is not a project key. */
17
+ export declare const fromProjectPreviewKey: (scope: string, key: string | undefined) => string | undefined;
18
+ /** Returns the card id of an output in a project preview key, `artifacts/{name}`. */
19
+ export declare const toProjectOutputCardId: (name: string) => string;
20
+ /** Returns the output name behind a card id, or `undefined` when the card is not an output. */
21
+ export declare const fromProjectOutputCardId: (cardId: string | undefined) => string | undefined;
22
+ /** Returns the attachment for a file stored in a project; its `url` is the host-built locator the canvas content resolvers fetch like any DIAL file. */
23
+ export declare const toStoredProjectFileAttachment: ({ id, name, contentType }: ProjectFileCard, projectId: string, toLocator: ProjectFileLocatorBuilder) => DisplayAttachment;
24
+ /** Returns the attachment the project view opens in the canvas for one of its outputs; its `url` is the host-built output locator. */
25
+ export declare const toProjectOutputAttachment: ({ name, contentType }: ProjectOutputItem, projectId: string, toLocator: ProjectFileLocatorBuilder) => DisplayAttachment;
26
+ /** Returns the attachment a project form opens in the canvas for one of its cards: a file added in this session is its own attachment (it carries the `File`), a stored one is built from its project, and a stored file with no project yields `undefined`. */
27
+ export declare const toProjectContextFileAttachment: (file: ProjectContextFile, projectId: string | null, toLocator: ProjectFileLocatorBuilder) => DisplayAttachment | undefined;
28
+ //# sourceMappingURL=project-file-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-file-preview.d.ts","sourceRoot":"","sources":["../../src/project/project-file-preview.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAGvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,wBAAwB,CAAC;AAMhC,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAC;IACX,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,gJAAgJ;AAChJ,MAAM,MAAM,yBAAyB,GAAG,CACtC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,KACT,MAAM,CAAC;AAEZ,sHAAsH;AACtH,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,EAAE,IAAI,MAAM,KAAG,MACvB,CAAC;AAE1C,6HAA6H;AAC7H,eAAO,MAAM,qBAAqB,GAChC,OAAO,MAAM,EACb,KAAK,MAAM,GAAG,SAAS,KACtB,MAAM,GAAG,SAGX,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,KAAG,MAClB,CAAC;AAEpC,+FAA+F;AAC/F,eAAO,MAAM,uBAAuB,GAClC,QAAQ,MAAM,GAAG,SAAS,KACzB,MAAM,GAAG,SAGG,CAAC;AAEhB,wJAAwJ;AACxJ,eAAO,MAAM,6BAA6B,GACxC,2BAA2B,eAAe,EAC1C,WAAW,MAAM,EACjB,WAAW,yBAAyB,KACnC,iBAOD,CAAC;AAEH,sIAAsI;AACtI,eAAO,MAAM,yBAAyB,GACpC,uBAAuB,iBAAiB,EACxC,WAAW,MAAM,EACjB,WAAW,yBAAyB,KACnC,iBAKA,CAAC;AAEJ,gQAAgQ;AAChQ,eAAO,MAAM,8BAA8B,GACzC,MAAM,kBAAkB,EACxB,WAAW,MAAM,GAAG,IAAI,EACxB,WAAW,yBAAyB,KACnC,iBAAiB,GAAG,SAKtB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { RequestStatus as e, getAttachmentTypeFromMime as t } from "@epam/ai-dial-chat-shared";
2
+ import { isStoredContextFile as n } from "@epam/ai-dial-projects";
3
+ //#region src/project/project-file-preview.ts
4
+ var r = "::", i = "artifacts/", a = (e, t) => `${e}${r}${t}`, o = (e, t) => {
5
+ let n = `${e}${r}`;
6
+ return t?.startsWith(n) ? t.slice(n.length) : void 0;
7
+ }, s = (e) => `${i}${e}`, c = (e) => e?.startsWith(i) ? e.slice(10) : void 0, l = ({ id: n, name: r, contentType: i }, a, o) => ({
8
+ id: n,
9
+ name: r,
10
+ contentType: i,
11
+ type: t(i),
12
+ status: e.Idle,
13
+ url: o(a, r)
14
+ }), u = ({ name: e, contentType: t }, n, r) => l({
15
+ id: e,
16
+ name: e,
17
+ contentType: t
18
+ }, n, r), d = (e, t, r) => n(e) ? t == null ? void 0 : l(e, t, r) : e;
19
+ //#endregion
20
+ export { c as fromProjectOutputCardId, o as fromProjectPreviewKey, d as toProjectContextFileAttachment, u as toProjectOutputAttachment, s as toProjectOutputCardId, a as toProjectPreviewKey, l as toStoredProjectFileAttachment };
@@ -0,0 +1,46 @@
1
+ import { ProjectDetailsDto } from '@epam/ai-dial-chat-api-client';
2
+ import { ProjectContextFile, ProjectCreateFormErrors, ProjectCreateFormValues } from '@epam/ai-dial-projects';
3
+ import { Dispatch, SetStateAction } from 'react';
4
+ /** Which project form a {@link useProjectDraft} draft backs. */
5
+ export declare enum ProjectDraftMode {
6
+ /** The New project form: empty at the start, nothing stored yet. */
7
+ Create = "create",
8
+ /** The Edit project form: seeded from a loaded project. */
9
+ Edit = "edit"
10
+ }
11
+ /** Mode of a {@link useProjectDraft} draft, and the loaded project of an edit draft. */
12
+ export type UseProjectDraftOptions = {
13
+ /** The New project form. */
14
+ mode: ProjectDraftMode.Create;
15
+ } | {
16
+ /** The Edit project form. */
17
+ mode: ProjectDraftMode.Edit;
18
+ /** The loaded project, or `null` while none is; the draft is seeded once per its `contentVersion`. */
19
+ project: ProjectDetailsDto | null;
20
+ };
21
+ /** State and handlers of a project form draft. */
22
+ export interface UseProjectDraftResult {
23
+ /** Name and instructions as typed. */
24
+ values: ProjectCreateFormValues;
25
+ /** The form's context file cards: stored files (edit mode) and files added in this session. */
26
+ contextFiles: ProjectContextFile[];
27
+ /** Field errors the host set, e.g. from a rejected request. */
28
+ errors: ProjectCreateFormErrors;
29
+ /** Sets the field errors, for a rejection the host maps to a field. */
30
+ setErrors: Dispatch<SetStateAction<ProjectCreateFormErrors>>;
31
+ /** Changes one text field; a change to the name clears its error. */
32
+ onFieldChange: <K extends keyof ProjectCreateFormValues>(field: K, value: ProjectCreateFormValues[K]) => void;
33
+ /** Replaces the context file cards and clears the context error. */
34
+ onContextFilesChange: (files: ProjectContextFile[]) => void;
35
+ /** Whether the draft is ready to submit: always in create mode, once seeded from the loaded project in edit mode. */
36
+ isSeeded: boolean;
37
+ /** Whether the draft holds edits that leaving would discard. */
38
+ isDirty: boolean;
39
+ /** Names of stored files the user removed (edit mode); empty in create mode. */
40
+ removedFileNames: string[];
41
+ /** Files added in this session, not yet stored. */
42
+ newFiles: File[];
43
+ }
44
+ /** Owns the form state of the New project and Edit project pages: values, context files, field errors, dirtiness, and the removed and new files a save sends. */
45
+ export declare const useProjectDraft: (options: UseProjectDraftOptions) => UseProjectDraftResult;
46
+ //# sourceMappingURL=use-project-draft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-project-draft.d.ts","sourceRoot":"","sources":["../../src/project/use-project-draft.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAGf,gEAAgE;AAChE,oBAAY,gBAAgB;IAC1B,oEAAoE;IACpE,MAAM,WAAW;IACjB,2DAA2D;IAC3D,IAAI,SAAS;CACd;AAED,wFAAwF;AACxF,MAAM,MAAM,sBAAsB,GAC9B;IACE,4BAA4B;IAC5B,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC;CAC/B,GACD;IACE,6BAA6B;IAC7B,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC;IAC5B,sGAAsG;IACtG,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACnC,CAAC;AAEN,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,MAAM,EAAE,uBAAuB,CAAC;IAChC,+FAA+F;IAC/F,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,+DAA+D;IAC/D,MAAM,EAAE,uBAAuB,CAAC;IAChC,uEAAuE;IACvE,SAAS,EAAE,QAAQ,CAAC,cAAc,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAC7D,qEAAqE;IACrE,aAAa,EAAE,CAAC,CAAC,SAAS,MAAM,uBAAuB,EACrD,KAAK,EAAE,CAAC,EACR,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,KAC9B,IAAI,CAAC;IACV,oEAAoE;IACpE,oBAAoB,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,IAAI,CAAC;IAC5D,qHAAqH;IACrH,QAAQ,EAAE,OAAO,CAAC;IAClB,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,EAAE,IAAI,EAAE,CAAC;CAClB;AAKD,iKAAiK;AACjK,eAAO,MAAM,eAAe,GAC1B,SAAS,sBAAsB,KAC9B,qBA4FF,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { mapStoredContextFiles as e } from "./project-mapping.js";
2
+ import { useCallback as t, useEffect as n, useMemo as r, useState as i } from "react";
3
+ import { isStoredContextFile as a } from "@epam/ai-dial-projects";
4
+ //#region src/project/use-project-draft.ts
5
+ var o = /* @__PURE__ */ function(e) {
6
+ return e.Create = "create", e.Edit = "edit", e;
7
+ }({}), s = {
8
+ name: "",
9
+ instructions: ""
10
+ }, c = [], l = (o) => {
11
+ let l = o.mode === "edit" ? o.project : null, u = o.mode === "edit", [d, f] = i(s), [p, m] = i(c), [h, g] = i({}), [_, v] = i(null);
12
+ n(() => {
13
+ u && l != null && l.contentVersion !== _ && (f({
14
+ name: l.name,
15
+ instructions: l.instructions
16
+ }), m(e(l)), g({}), v(l.contentVersion));
17
+ }, [
18
+ u,
19
+ l,
20
+ _
21
+ ]);
22
+ let y = r(() => {
23
+ if (l == null) return [];
24
+ let e = new Set(p.filter(a).map((e) => e.name));
25
+ return l.contextFiles.map((e) => e.name).filter((t) => !e.has(t));
26
+ }, [l, p]), b = r(() => p.flatMap((e) => a(e) ? [] : [e.file]), [p]), x = !u || l != null && _ === l.contentVersion, S = u ? l != null && x && (d.name !== l.name || d.instructions !== l.instructions || y.length > 0 || b.length > 0) : d.name !== "" || d.instructions !== "" || p.length > 0;
27
+ return {
28
+ values: d,
29
+ contextFiles: p,
30
+ errors: h,
31
+ setErrors: g,
32
+ onFieldChange: t((e, t) => {
33
+ f((n) => ({
34
+ ...n,
35
+ [e]: t
36
+ })), e === "name" && g((e) => e.name ? {
37
+ ...e,
38
+ name: void 0
39
+ } : e);
40
+ }, []),
41
+ onContextFilesChange: t((e) => {
42
+ m(e), g((e) => e.context ? {
43
+ ...e,
44
+ context: void 0
45
+ } : e);
46
+ }, []),
47
+ isSeeded: x,
48
+ isDirty: S,
49
+ removedFileNames: y,
50
+ newFiles: b
51
+ };
52
+ };
53
+ //#endregion
54
+ export { o as ProjectDraftMode, l as useProjectDraft };
@@ -0,0 +1,42 @@
1
+ import { DisplayAttachment } from '@epam/ai-dial-chat-shared';
2
+ /** Tells whether the request that produced a result may still show it; `false` once a newer request superseded it. */
3
+ export type ProjectPreviewCommitGuard = () => boolean;
4
+ /** Opens an attachment in the host's canvas under a key, showing it only while the guard allows; the host's `openAttachmentCanvas` fits. */
5
+ export type OpenProjectPreviewAttachment = (attachment: DisplayAttachment, canvasAttachmentId: string, shouldCommit: ProjectPreviewCommitGuard) => unknown;
6
+ /** Host canvas operations and card lookups for the project file preview. */
7
+ export interface UseProjectFilePreviewOptions {
8
+ /** Id of the project the page shows, or a fixed value before it exists; it keeps one file name in two projects apart. */
9
+ scope: string;
10
+ /** Id of the attachment the canvas holds now, or `undefined` when it is closed. */
11
+ attachmentId: string | undefined;
12
+ /** Opens an attachment in the canvas under a key. */
13
+ openAttachment: OpenProjectPreviewAttachment;
14
+ /** Closes the canvas. */
15
+ closeCanvas: () => void;
16
+ /** Starts a canvas request and returns the guard that says whether it is still the latest. */
17
+ startRequest: () => ProjectPreviewCommitGuard;
18
+ /** Returns the attachment to open for a context card id, or `undefined` for a card the page does not hold; it should keep its identity while the cards are unchanged. */
19
+ resolveContextAttachment: (cardId: string) => DisplayAttachment | undefined;
20
+ /** Returns the attachment to open for an output name; omit it where outputs are not shown. */
21
+ resolveOutputAttachment?: (name: string) => DisplayAttachment | undefined;
22
+ }
23
+ /** Selection state and stable card callbacks of the project file preview. */
24
+ export interface UseProjectFilePreviewResult {
25
+ /** Card id of the open project file, an output's card id included, or `undefined` when none of this scope is open. */
26
+ selectedCardId: string | undefined;
27
+ /** Card id of the open context file; `undefined` while an output or nothing is open. */
28
+ selectedContextFileId: string | undefined;
29
+ /** Name of the open output; `undefined` while a context file or nothing is open. */
30
+ selectedOutputName: string | undefined;
31
+ /** Opens a context card, or closes the canvas when that card is already open. */
32
+ onContextFileClick: (cardId: string) => void;
33
+ /** Opens an output, or closes the canvas when that output is already open. */
34
+ onOutputClick: (name: string) => void;
35
+ /** Closes the canvas when the open context card is no longer among the page's cards. */
36
+ closeIfRemoved: (cards: readonly {
37
+ id: string;
38
+ }[]) => void;
39
+ }
40
+ /** Opens project files in the host's attachment canvas for the New project, Edit project and project view pages, deriving the selected card from the canvas. */
41
+ export declare const useProjectFilePreview: ({ scope, attachmentId, openAttachment, closeCanvas, startRequest, resolveContextAttachment, resolveOutputAttachment, }: UseProjectFilePreviewOptions) => UseProjectFilePreviewResult;
42
+ //# sourceMappingURL=use-project-file-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-project-file-preview.d.ts","sourceRoot":"","sources":["../../src/project/use-project-file-preview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AASnE,sHAAsH;AACtH,MAAM,MAAM,yBAAyB,GAAG,MAAM,OAAO,CAAC;AAEtD,4IAA4I;AAC5I,MAAM,MAAM,4BAA4B,GAAG,CACzC,UAAU,EAAE,iBAAiB,EAC7B,kBAAkB,EAAE,MAAM,EAC1B,YAAY,EAAE,yBAAyB,KACpC,OAAO,CAAC;AAEb,4EAA4E;AAC5E,MAAM,WAAW,4BAA4B;IAC3C,yHAAyH;IACzH,KAAK,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,qDAAqD;IACrD,cAAc,EAAE,4BAA4B,CAAC;IAC7C,yBAAyB;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,8FAA8F;IAC9F,YAAY,EAAE,MAAM,yBAAyB,CAAC;IAC9C,yKAAyK;IACzK,wBAAwB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC;IAC5E,8FAA8F;IAC9F,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC;CAC3E;AAED,6EAA6E;AAC7E,MAAM,WAAW,2BAA2B;IAC1C,sHAAsH;IACtH,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,wFAAwF;IACxF,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,oFAAoF;IACpF,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,iFAAiF;IACjF,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,8EAA8E;IAC9E,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,wFAAwF;IACxF,cAAc,EAAE,CAAC,KAAK,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,IAAI,CAAC;CAC5D;AAED,gKAAgK;AAChK,eAAO,MAAM,qBAAqB,GAAI,wHAQnC,4BAA4B,KAAG,2BA6EjC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { fromProjectOutputCardId as e, fromProjectPreviewKey as t, toProjectOutputCardId as n, toProjectPreviewKey as r } from "./project-file-preview.js";
2
+ import { useCallback as i } from "react";
3
+ //#region src/project/use-project-file-preview.ts
4
+ var a = ({ scope: a, attachmentId: o, openAttachment: s, closeCanvas: c, startRequest: l, resolveContextAttachment: u, resolveOutputAttachment: d }) => {
5
+ let f = t(a, o), p = e(f), m = p == null ? f : void 0;
6
+ return {
7
+ selectedCardId: f,
8
+ selectedContextFileId: m,
9
+ selectedOutputName: p,
10
+ onContextFileClick: i((e) => {
11
+ if (e === m) {
12
+ c();
13
+ return;
14
+ }
15
+ let t = u(e);
16
+ t && s(t, r(a, e), l());
17
+ }, [
18
+ c,
19
+ s,
20
+ u,
21
+ a,
22
+ m,
23
+ l
24
+ ]),
25
+ onOutputClick: i((e) => {
26
+ if (e === p) {
27
+ c();
28
+ return;
29
+ }
30
+ let t = d?.(e);
31
+ t && s(t, r(a, n(e)), l());
32
+ }, [
33
+ c,
34
+ s,
35
+ d,
36
+ a,
37
+ p,
38
+ l
39
+ ]),
40
+ closeIfRemoved: i((e) => {
41
+ m != null && !e.some((e) => e.id === m) && c();
42
+ }, [c, m])
43
+ };
44
+ };
45
+ //#endregion
46
+ export { a as useProjectFilePreview };
package/project.js CHANGED
@@ -2,13 +2,18 @@ import { buildCreateConversationDto as e, createProjectsApiClient as t, splitPro
2
2
  import { mapProjectArtifactsToOutputs as r, mapProjectDetailsToViewModel as i, mapProjectDtoToItem as a, mapProjectSource as o, mapStoredContextFiles as s } from "./project/project-mapping.js";
3
3
  import { DEFAULT_PROJECT_CONTEXT_ALLOWED_EXTENSIONS as c, DEFAULT_PROJECT_CONTEXT_FILE_MAX_BYTES as l, DEFAULT_PROJECT_CONTEXT_TOTAL_MAX_BYTES as u, getMimeTypesForExtensions as d, resolveByteLimit as f, resolveExtensionList as p } from "./project/project-limits.js";
4
4
  import { ProjectFormErrorField as m, ProjectFormErrorReason as h, getProjectFormError as g } from "./project/project-form-errors.js";
5
- import { useProjects as _ } from "./project/use-projects.js";
6
- import { ProjectRefreshOutcome as v } from "./project/project-refresh.js";
7
- import { useProject as y } from "./project/use-project.js";
8
- import { useProjectWatch as b } from "./project/use-project-watch.js";
9
- import { useCreateProject as x, useSaveProject as S } from "./project/use-project-submit.js";
10
- import { useProjectConversations as C } from "./project/use-project-conversations.js";
11
- import { useProjectArtifacts as w } from "./project/use-project-artifacts.js";
12
- import { ProjectActionError as T, useProjectActions as E } from "./project/use-project-actions.js";
13
- import { createSerializedKeyedWriter as D } from "./shared/serialized-writer.js";
14
- export { c as DEFAULT_PROJECT_CONTEXT_ALLOWED_EXTENSIONS, l as DEFAULT_PROJECT_CONTEXT_FILE_MAX_BYTES, u as DEFAULT_PROJECT_CONTEXT_TOTAL_MAX_BYTES, T as ProjectActionError, m as ProjectFormErrorField, h as ProjectFormErrorReason, v as ProjectRefreshOutcome, e as buildCreateConversationDto, t as createProjectsApiClient, D as createSerializedKeyedWriter, d as getMimeTypesForExtensions, g as getProjectFormError, r as mapProjectArtifactsToOutputs, i as mapProjectDetailsToViewModel, a as mapProjectDtoToItem, o as mapProjectSource, s as mapStoredContextFiles, f as resolveByteLimit, p as resolveExtensionList, n as splitProjectConversationId, x as useCreateProject, y as useProject, E as useProjectActions, w as useProjectArtifacts, C as useProjectConversations, b as useProjectWatch, _ as useProjects, S as useSaveProject };
5
+ import { fromProjectOutputCardId as _, fromProjectPreviewKey as v, toProjectContextFileAttachment as y, toProjectOutputAttachment as b, toProjectOutputCardId as x, toProjectPreviewKey as S, toStoredProjectFileAttachment as C } from "./project/project-file-preview.js";
6
+ import { useProjectFilePreview as w } from "./project/use-project-file-preview.js";
7
+ import { ProjectDraftMode as T, useProjectDraft as E } from "./project/use-project-draft.js";
8
+ import { ProjectChatCreateFailure as D, classifyProjectChatCreateError as O, createProjectChat as k } from "./project/create-project-chat.js";
9
+ import { createProjectConversationDataSource as A } from "./project/project-conversation-data-source.js";
10
+ import { useProjects as j } from "./project/use-projects.js";
11
+ import { ProjectRefreshOutcome as M } from "./project/project-refresh.js";
12
+ import { useProject as N } from "./project/use-project.js";
13
+ import { useProjectWatch as P } from "./project/use-project-watch.js";
14
+ import { useCreateProject as F, useSaveProject as I } from "./project/use-project-submit.js";
15
+ import { useProjectConversations as L } from "./project/use-project-conversations.js";
16
+ import { useProjectArtifacts as R } from "./project/use-project-artifacts.js";
17
+ import { ProjectActionError as z, useProjectActions as B } from "./project/use-project-actions.js";
18
+ import { createSerializedKeyedWriter as V } from "./shared/serialized-writer.js";
19
+ export { c as DEFAULT_PROJECT_CONTEXT_ALLOWED_EXTENSIONS, l as DEFAULT_PROJECT_CONTEXT_FILE_MAX_BYTES, u as DEFAULT_PROJECT_CONTEXT_TOTAL_MAX_BYTES, z as ProjectActionError, D as ProjectChatCreateFailure, T as ProjectDraftMode, m as ProjectFormErrorField, h as ProjectFormErrorReason, M as ProjectRefreshOutcome, e as buildCreateConversationDto, O as classifyProjectChatCreateError, k as createProjectChat, A as createProjectConversationDataSource, t as createProjectsApiClient, V as createSerializedKeyedWriter, _ as fromProjectOutputCardId, v as fromProjectPreviewKey, d as getMimeTypesForExtensions, g as getProjectFormError, r as mapProjectArtifactsToOutputs, i as mapProjectDetailsToViewModel, a as mapProjectDtoToItem, o as mapProjectSource, s as mapStoredContextFiles, f as resolveByteLimit, p as resolveExtensionList, n as splitProjectConversationId, y as toProjectContextFileAttachment, b as toProjectOutputAttachment, x as toProjectOutputCardId, S as toProjectPreviewKey, C as toStoredProjectFileAttachment, F as useCreateProject, N as useProject, B as useProjectActions, R as useProjectArtifacts, L as useProjectConversations, E as useProjectDraft, w as useProjectFilePreview, P as useProjectWatch, j as useProjects, I as useSaveProject };
@@ -0,0 +1,3 @@
1
+ /** Resolves after `ms`, or immediately once `signal` aborts; a signal that is already aborted sets no timer. */
2
+ export declare const sleep: (ms: number, signal: AbortSignal) => Promise<void>;
3
+ //# sourceMappingURL=sleep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../src/shared/sleep.ts"],"names":[],"mappings":"AAAA,gHAAgH;AAChH,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,EAAE,QAAQ,WAAW,KAAG,OAAO,CAAC,IAAI,CAehE,CAAC"}
@@ -0,0 +1,13 @@
1
+ //#region src/shared/sleep.ts
2
+ var e = (e, t) => new Promise((n) => {
3
+ if (t.aborted) {
4
+ n();
5
+ return;
6
+ }
7
+ let r = setTimeout(n, e);
8
+ t.addEventListener("abort", () => {
9
+ clearTimeout(r), n();
10
+ }, { once: !0 });
11
+ });
12
+ //#endregion
13
+ export { e as sleep };