@data-club/ai-hub 0.0.11 → 0.0.12
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/dist/auth/locales/cs.d.ts.map +1 -1
- package/dist/auth/locales/cs.js +4 -0
- package/dist/auth/locales/cs.js.map +1 -1
- package/dist/auth/locales/sk.d.ts.map +1 -1
- package/dist/auth/locales/sk.js +4 -0
- package/dist/auth/locales/sk.js.map +1 -1
- package/dist/auth/texts.d.ts +8 -0
- package/dist/auth/texts.d.ts.map +1 -1
- package/dist/auth/texts.js +4 -0
- package/dist/auth/texts.js.map +1 -1
- package/dist/components/ChatShell/index.d.ts +2 -0
- package/dist/components/ChatShell/index.d.ts.map +1 -1
- package/dist/components/ChatShell/index.js +3 -1
- package/dist/components/ChatShell/index.js.map +1 -1
- package/dist/components/DataClubAIHub/index.d.ts +2 -0
- package/dist/components/DataClubAIHub/index.d.ts.map +1 -1
- package/dist/components/DataClubAIHub/index.js +2 -0
- package/dist/components/DataClubAIHub/index.js.map +1 -1
- package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts.map +1 -1
- package/dist/components/DataClubAIHubAdmin/SettingsPage.js +3 -1
- package/dist/components/DataClubAIHubAdmin/SettingsPage.js.map +1 -1
- package/dist/components/MainColumn/index.d.ts +8 -0
- package/dist/components/MainColumn/index.d.ts.map +1 -1
- package/dist/components/MainColumn/index.js +40 -2
- package/dist/components/MainColumn/index.js.map +1 -1
- package/dist/state/affordances.d.ts +3 -1
- package/dist/state/affordances.d.ts.map +1 -1
- package/dist/state/affordances.js +3 -1
- package/dist/state/affordances.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/util/exportConversation.d.ts +64 -0
- package/dist/util/exportConversation.d.ts.map +1 -0
- package/dist/util/exportConversation.js +78 -0
- package/dist/util/exportConversation.js.map +1 -0
- package/package.json +1 -1
- package/src/auth/locales/cs.ts +4 -0
- package/src/auth/locales/sk.ts +4 -0
- package/src/auth/texts.ts +12 -0
- package/src/components/ChatShell/index.tsx +5 -0
- package/src/components/DataClubAIHub/index.tsx +5 -0
- package/src/components/DataClubAIHubAdmin/SettingsPage.tsx +3 -1
- package/src/components/MainColumn/index.tsx +85 -1
- package/src/state/affordances.ts +5 -1
- package/src/styles/default.css +21 -0
- package/src/types.ts +2 -0
- package/src/util/exportConversation.ts +101 -0
|
@@ -18,12 +18,14 @@ import { useMemo } from "react";
|
|
|
18
18
|
import {} from "../../auth/texts.js";
|
|
19
19
|
import { useResolvedTexts } from "../../context/useAIHubTexts.js";
|
|
20
20
|
import { useAIHub } from "../../context/useAIHub.js";
|
|
21
|
+
import { buildConversationMarkdown, conversationExportFilename, } from "../../util/exportConversation.js";
|
|
21
22
|
import { TurnStatusIndicator } from "../TurnStatusIndicator/index.js";
|
|
22
23
|
const DEFAULT_CLASS_NAMES = Object.freeze({
|
|
23
24
|
root: "data-club-ai-hub__main-column",
|
|
24
25
|
header: "data-club-ai-hub__chat-header",
|
|
25
26
|
back: "data-club-ai-hub__chat-header__back",
|
|
26
27
|
title: "data-club-ai-hub__chat-header__title",
|
|
28
|
+
export: "data-club-ai-hub__chat-header__export",
|
|
27
29
|
extras: "data-club-ai-hub__chat-header__extras",
|
|
28
30
|
body: "data-club-ai-hub__main-column__body",
|
|
29
31
|
});
|
|
@@ -34,15 +36,51 @@ const DEFAULT_CLASS_NAMES = Object.freeze({
|
|
|
34
36
|
* @returns the rendered column.
|
|
35
37
|
*/
|
|
36
38
|
export function MainColumn(props) {
|
|
37
|
-
const { agents, activeAgentId, setActiveAgent } = useAIHub();
|
|
39
|
+
const { agents, activeAgentId, setActiveAgent, sessions, activeSessionId, messages, } = useAIHub();
|
|
38
40
|
const texts = useResolvedTexts(props.texts);
|
|
39
41
|
const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
|
|
40
42
|
const showBack = props.showBackToAgents ?? true;
|
|
41
43
|
const showTurnStatus = props.showTurnStatus ?? true;
|
|
44
|
+
const showExportButton = props.showExportButton ?? true;
|
|
42
45
|
const activeAgent = useMemo(() => agents.find((a) => a.id === activeAgentId) ?? null, [agents, activeAgentId]);
|
|
46
|
+
const activeSession = useMemo(() => (sessions ?? []).find((s) => s.id === activeSessionId) ?? null, [sessions, activeSessionId]);
|
|
47
|
+
// Whether the export button has anything to export — at least one
|
|
48
|
+
// user/assistant message with text content (mirrors the serializer's
|
|
49
|
+
// skip rules so we never download an empty document).
|
|
50
|
+
const hasExportableMessages = useMemo(() => (messages ?? []).some((m) => (m.role === "user" || m.role === "assistant") &&
|
|
51
|
+
m.content.trim().length > 0), [messages]);
|
|
52
|
+
/**
|
|
53
|
+
* Serializes the visible conversation to Markdown and triggers a
|
|
54
|
+
* client-side download. System-prompt rows (`role: "system"`) and tool
|
|
55
|
+
* rows are excluded by the serializer; rotating-message sessions open
|
|
56
|
+
* with the agent's reply because the rotation runner already deleted
|
|
57
|
+
* its own prompt server-side.
|
|
58
|
+
*/
|
|
59
|
+
function handleExport() {
|
|
60
|
+
const exportedAt = new Date();
|
|
61
|
+
const sessionTitle = activeSession?.title && activeSession.title.trim().length > 0
|
|
62
|
+
? activeSession.title
|
|
63
|
+
: texts.chat.untitledSessionFallback;
|
|
64
|
+
const markdown = buildConversationMarkdown({
|
|
65
|
+
sessionTitle,
|
|
66
|
+
agentDisplayName: activeAgent?.display_name ?? texts.chat.exportAssistantFallbackLabel,
|
|
67
|
+
userLabel: texts.chat.exportUserLabel,
|
|
68
|
+
messages: messages ?? [],
|
|
69
|
+
exportedAt,
|
|
70
|
+
});
|
|
71
|
+
const blob = new Blob([markdown], { type: "text/markdown;charset=utf-8" });
|
|
72
|
+
const url = URL.createObjectURL(blob);
|
|
73
|
+
const anchor = document.createElement("a");
|
|
74
|
+
anchor.href = url;
|
|
75
|
+
anchor.download = conversationExportFilename(sessionTitle, exportedAt);
|
|
76
|
+
document.body.appendChild(anchor);
|
|
77
|
+
anchor.click();
|
|
78
|
+
anchor.remove();
|
|
79
|
+
URL.revokeObjectURL(url);
|
|
80
|
+
}
|
|
43
81
|
const rootClass = props.className
|
|
44
82
|
? `${cls.root} ${props.className}`
|
|
45
83
|
: cls.root;
|
|
46
|
-
return (_jsxs("section", { className: rootClass, "data-testid": "main-column", children: [_jsxs("header", { className: cls.header, "data-testid": "chat-header", children: [showBack ? (_jsx("button", { type: "button", className: cls.back, onClick: () => setActiveAgent(null), "data-testid": "chat-header-back", children: texts.chat.backToAgentsLink })) : null, _jsx("h2", { className: cls.title, "data-testid": "chat-header-title", children: activeAgent?.display_name ?? "" }), showTurnStatus ? _jsx(TurnStatusIndicator, {}) : null, props.customHeaderContent ? (_jsx("div", { className: cls.extras, "data-testid": "chat-header-extras", children: props.customHeaderContent })) : null] }), _jsx("div", { className: cls.body, children: props.children })] }));
|
|
84
|
+
return (_jsxs("section", { className: rootClass, "data-testid": "main-column", children: [_jsxs("header", { className: cls.header, "data-testid": "chat-header", children: [showBack ? (_jsx("button", { type: "button", className: cls.back, onClick: () => setActiveAgent(null), "data-testid": "chat-header-back", children: texts.chat.backToAgentsLink })) : null, _jsx("h2", { className: cls.title, "data-testid": "chat-header-title", children: activeAgent?.display_name ?? "" }), showTurnStatus ? _jsx(TurnStatusIndicator, {}) : null, showExportButton && activeSessionId !== null ? (_jsx("button", { type: "button", className: cls.export, onClick: handleExport, disabled: !hasExportableMessages, "aria-label": texts.chat.exportConversationAriaLabel, title: texts.chat.exportConversationAriaLabel, "data-testid": "chat-header-export", children: texts.chat.exportConversationButton })) : null, props.customHeaderContent ? (_jsx("div", { className: cls.extras, "data-testid": "chat-header-extras", children: props.customHeaderContent })) : null] }), _jsx("div", { className: cls.body, children: props.children })] }));
|
|
47
85
|
}
|
|
48
86
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/MainColumn/index.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAkB,MAAM,OAAO,CAAC;AAEhD,OAAO,EAGN,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/MainColumn/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -60,6 +60,8 @@ export interface AIHubAffordanceFlags {
|
|
|
60
60
|
scrollToPresentVisible: boolean;
|
|
61
61
|
/** Whether the turn-status indicator renders in the chat header. Default true. */
|
|
62
62
|
turnStatusVisible: boolean;
|
|
63
|
+
/** Whether the export-conversation (.md) button renders in the chat header. Default true. */
|
|
64
|
+
exportConversationEnabled: boolean;
|
|
63
65
|
}
|
|
64
66
|
/** Built-in defaults — applied when neither server nor React prop sets a value. */
|
|
65
67
|
export declare const DEFAULT_AFFORDANCE_FLAGS: AIHubAffordanceFlags;
|
|
@@ -70,7 +72,7 @@ export declare const DEFAULT_AFFORDANCE_FLAGS: AIHubAffordanceFlags;
|
|
|
70
72
|
*/
|
|
71
73
|
export declare const FEATURE_TOGGLE_KEY_MAP: ReadonlyArray<readonly [keyof AIHubFeatureToggles, keyof AIHubAffordanceFlags]>;
|
|
72
74
|
/**
|
|
73
|
-
* Composes the three layers into a flat resolved record of all
|
|
75
|
+
* Composes the three layers into a flat resolved record of all 14
|
|
74
76
|
* affordance booleans.
|
|
75
77
|
*
|
|
76
78
|
* Per §8.4: server toggle wins; falling through, the React prop wins;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affordances.d.ts","sourceRoot":"","sources":["../../src/state/affordances.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,UAAU,EACX,MAAM,aAAa,CAAC;AAErB;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,oBAAoB,EAAE,OAAO,CAAC;IAC9B,oEAAoE;IACpE,sBAAsB,EAAE,OAAO,CAAC;IAChC,iEAAiE;IACjE,wBAAwB,EAAE,OAAO,CAAC;IAClC,0EAA0E;IAC1E,0BAA0B,EAAE,OAAO,CAAC;IACpC,2EAA2E;IAC3E,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gFAAgF;IAChF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,0EAA0E;IAC1E,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gEAAgE;IAChE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,qFAAqF;IACrF,gBAAgB,EAAE,OAAO,CAAC;IAC1B,8EAA8E;IAC9E,oBAAoB,EAAE,OAAO,CAAC;IAC9B,4FAA4F;IAC5F,sBAAsB,EAAE,OAAO,CAAC;IAChC,kFAAkF;IAClF,iBAAiB,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"affordances.d.ts","sourceRoot":"","sources":["../../src/state/affordances.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,6 +40,7 @@ export const DEFAULT_AFFORDANCE_FLAGS = Object.freeze({
|
|
|
40
40
|
effortControlVisible: true,
|
|
41
41
|
scrollToPresentVisible: true,
|
|
42
42
|
turnStatusVisible: true,
|
|
43
|
+
exportConversationEnabled: true,
|
|
43
44
|
});
|
|
44
45
|
/**
|
|
45
46
|
* Per-flag mapping from the wire key (`AIHubFeatureToggles`) to the
|
|
@@ -60,6 +61,7 @@ export const FEATURE_TOGGLE_KEY_MAP = Object.freeze([
|
|
|
60
61
|
["effort_control_visible", "effortControlVisible"],
|
|
61
62
|
["scroll_to_present_visible", "scrollToPresentVisible"],
|
|
62
63
|
["turn_status_visible", "turnStatusVisible"],
|
|
64
|
+
["export_conversation_enabled", "exportConversationEnabled"],
|
|
63
65
|
]);
|
|
64
66
|
/**
|
|
65
67
|
* Resolves the precedence stack for one toggle.
|
|
@@ -83,7 +85,7 @@ function resolveOne(serverValue, propValue, defaultValue) {
|
|
|
83
85
|
return defaultValue;
|
|
84
86
|
}
|
|
85
87
|
/**
|
|
86
|
-
* Composes the three layers into a flat resolved record of all
|
|
88
|
+
* Composes the three layers into a flat resolved record of all 14
|
|
87
89
|
* affordance booleans.
|
|
88
90
|
*
|
|
89
91
|
* Per §8.4: server toggle wins; falling through, the React prop wins;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affordances.js","sourceRoot":"","sources":["../../src/state/affordances.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;
|
|
1
|
+
{"version":3,"file":"affordances.js","sourceRoot":"","sources":["../../src/state/affordances.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -657,6 +657,8 @@ export interface AIHubFeatureToggles {
|
|
|
657
657
|
scroll_to_present_visible?: boolean;
|
|
658
658
|
/** Overrides `showTurnStatus` prop. */
|
|
659
659
|
turn_status_visible?: boolean;
|
|
660
|
+
/** Overrides `showExportButton` prop. */
|
|
661
|
+
export_conversation_enabled?: boolean;
|
|
660
662
|
}
|
|
661
663
|
/**
|
|
662
664
|
* Top-level error shape the React client hands to user-supplied `onError`
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMrD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,GAAG,aAAa,CAAC;AAExE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,sEAAsE;IACtE,IAAI,EAAE,SAAS,CAAC;IAChB;;;;;;OAMG;IACH,gBAAgB,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,aAAa,EAAE,OAAO,GAAG,MAAM,CAAC;IAChC;;;;OAIG;IACH,sBAAsB,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,gBAAgB,EAAE,aAAa,CAAC;IAChC;;;;OAIG;IACH,oBAAoB,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;OAGG;IACH,sBAAsB,EAAE,OAAO,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,IAAI,EAAE,SAAS,CAAC;IAChB,wEAAwE;IACxE,UAAU,EAAE,eAAe,CAAC;CAC7B;AAMD;;;;;;;;GAQG;AACH,MAAM,WAAW,OAAO;IACtB,mBAAmB;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE;QACV,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;KAChC,CAAC;IACF;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE;QACb,+EAA+E;QAC/E,MAAM,CAAC,EAAE;YAAE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;SAAE,CAAC;QACzC,gDAAgD;QAChD,gBAAgB,CAAC,EAAE;YAAE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;SAAE,CAAC;QACnD,yDAAyD;QACzD,SAAS,CAAC,EAAE;YAAE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;SAAE,CAAC;QAC5C,4CAA4C;QAC5C,eAAe,CAAC,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;KAChD,CAAC;CACH;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,mBAAmB,EAAE,GAAG,IAAI,CAAC;CAC3C;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,qEAAqE;IACrE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE9E;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GACpB,YAAY,GACZ,iBAAiB,GACjB,kBAAkB,GAClB,gBAAgB,GAChB,kBAAkB,GAClB,eAAe,CAAC;AAEpB;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,8DAA8D;IAC9D,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAMD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,MAAM,EAAE,UAAU,CAAC;IACnB,0EAA0E;IAC1E,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;GAKG;AACH,UAAU,cAAc;IACtB,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,KAAK,EAAE,eAAe,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,8BAA+B,SAAQ,cAAc;IACpE,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE;QACJ,uEAAuE;QACvE,gBAAgB,EAAE,MAAM,CAAC;QACzB,wCAAwC;QACxC,UAAU,EAAE,MAAM,CAAC;QACnB,uEAAuE;QACvE,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;;;;;GAMG;AACH,MAAM,WAAW,4BAA6B,SAAQ,cAAc;IAClE,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE;QACJ,8DAA8D;QAC9D,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC;KACxC,CAAC;CACH;AAED;;;;;GAKG;AACH,MAAM,WAAW,4BAA6B,SAAQ,cAAc;IAClE,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,+BAAgC,SAAQ,cAAc;IACrE,KAAK,EAAE,iBAAiB,CAAC;IACzB,IAAI,EAAE;QACJ,oCAAoC;QACpC,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;;;;GAKG;AACH,MAAM,WAAW,+BAAgC,SAAQ,cAAc;IACrE,KAAK,EAAE,iBAAiB,CAAC;IACzB,IAAI,EAAE;QACJ,oCAAoC;QACpC,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;;;;;GAMG;AACH,MAAM,WAAW,yCAA0C,SAAQ,cAAc;IAC/E,KAAK,EAAE,4BAA4B,CAAC;IACpC,IAAI,EAAE;QACJ,wEAAwE;QACxE,OAAO,EAAE,YAAY,CAAC;KACvB,CAAC;CACH;AAED;;;;;;GAMG;AACH,MAAM,WAAW,yBAA0B,SAAQ,cAAc;IAC/D,KAAK,EAAE,mBAAmB,CAAC;IAC3B,IAAI,EAAE;QACJ,6DAA6D;QAC7D,YAAY,EAAE,MAAM,CAAC;QACrB,4BAA4B;QAC5B,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA6B,SAAQ,cAAc;IAClE,KAAK,EAAE,uBAAuB,CAAC;IAC/B,IAAI,EAAE;QACJ,8DAA8D;QAC9D,YAAY,EAAE,MAAM,CAAC;QACrB,2CAA2C;QAC3C,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;;;;GAKG;AACH,MAAM,WAAW,4BAA6B,SAAQ,cAAc;IAClE,KAAK,EAAE,sBAAsB,CAAC;IAC9B,IAAI,EAAE;QACJ,8DAA8D;QAC9D,YAAY,EAAE,MAAM,CAAC;QACrB,+DAA+D;QAC/D,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA2B,SAAQ,cAAc;IAChE,KAAK,EAAE,oBAAoB,CAAC;IAC5B,IAAI,EAAE;QACJ,8DAA8D;QAC9D,YAAY,EAAE,MAAM,CAAC;QACrB,4EAA4E;QAC5E,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAyB,SAAQ,cAAc;IAC9D,KAAK,EAAE,kBAAkB,CAAC;IAC1B,IAAI,EAAE;QACJ,8DAA8D;QAC9D,YAAY,EAAE,MAAM,CAAC;QACrB,kEAAkE;QAClE,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE;YACN,wDAAwD;YACxD,IAAI,EAAE,MAAM,CAAC;YACb,kCAAkC;YAClC,OAAO,EAAE,MAAM,CAAC;SACjB,CAAC;KACH,CAAC;CACH;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAuB,SAAQ,cAAc;IAC5D,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE;QACJ,4CAA4C;QAC5C,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;QAC7C,4DAA4D;QAC5D,OAAO,EAAE,MAAM,CAAC;QAChB,oEAAoE;QACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE;QACJ,wDAAwD;QACxD,IAAI,EAAE,eAAe,GAAG,gBAAgB,GAAG,UAAU,GAAG,aAAa,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;QACtF,kCAAkC;QAClC,OAAO,EAAE,MAAM,CAAC;QAChB,6CAA6C;QAC7C,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAClB,8BAA8B,GAC9B,4BAA4B,GAC5B,4BAA4B,GAC5B,+BAA+B,GAC/B,+BAA+B,GAC/B,yCAAyC,GACzC,yBAAyB,GACzB,4BAA4B,GAC5B,4BAA4B,GAC5B,0BAA0B,GAC1B,wBAAwB,GACxB,sBAAsB,GACtB,qBAAqB,CAAC;AAM1B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,+CAA+C;IAC/C,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,iDAAiD;IACjD,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,gDAAgD;IAChD,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC,kCAAkC;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uCAAuC;IACvC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sCAAsC;IACtC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,2CAA2C;IAC3C,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,0CAA0C;IAC1C,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,kDAAkD;IAClD,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,uCAAuC;IACvC,mBAAmB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation → Markdown export helpers.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions — the `<MainColumn />` export button calls
|
|
5
|
+
* `buildConversationMarkdown` on the already-loaded `useAIHub().messages`
|
|
6
|
+
* array and hands the result to a Blob download. Keeping the serialization
|
|
7
|
+
* here (instead of inline in the component) makes the export rules
|
|
8
|
+
* unit-testable without a DOM.
|
|
9
|
+
*
|
|
10
|
+
* Export rules:
|
|
11
|
+
*
|
|
12
|
+
* - Only `user` and `assistant` messages are exported. `system` rows (the
|
|
13
|
+
* compiled system prompt travels in the transcript as `role: "system"`)
|
|
14
|
+
* and `tool` rows never appear in the file.
|
|
15
|
+
* - Assistant messages with no text content (tool-call-only / reasoning-only
|
|
16
|
+
* bubbles) are skipped — the export is the human-readable dialog, not the
|
|
17
|
+
* agent trace.
|
|
18
|
+
* - Rotating-message sessions need no special casing: the rotation runner
|
|
19
|
+
* deletes its own prompt's `user_message` from the Letta conversation, so
|
|
20
|
+
* the transcript (and therefore the export) opens with the agent's reply.
|
|
21
|
+
*
|
|
22
|
+
* @see ../components/MainColumn/index.tsx — the export button
|
|
23
|
+
* @see SPECIFICATIONS.md §8.4 — `export_conversation_enabled` toggle
|
|
24
|
+
*/
|
|
25
|
+
import type { AIHubMessage } from "../types.js";
|
|
26
|
+
/** Inputs for {@link buildConversationMarkdown}. */
|
|
27
|
+
export interface ConversationExportArgs {
|
|
28
|
+
/** The session's user-supplied title; used as the document heading. */
|
|
29
|
+
sessionTitle: string;
|
|
30
|
+
/** Agent display name; rendered as the assistant speaker label. */
|
|
31
|
+
agentDisplayName: string;
|
|
32
|
+
/** Speaker label for `user` messages (localized, e.g. "You"). */
|
|
33
|
+
userLabel: string;
|
|
34
|
+
/** The transcript, chronologically sorted (as served by the provider). */
|
|
35
|
+
messages: ReadonlyArray<AIHubMessage>;
|
|
36
|
+
/** Export timestamp; injected so tests are deterministic. */
|
|
37
|
+
exportedAt: Date;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Serializes a conversation to a Markdown document.
|
|
41
|
+
*
|
|
42
|
+
* Format: an `# <title>` heading plus an "exported" byline, then one
|
|
43
|
+
* `## <speaker>` section per user/assistant message with the message's
|
|
44
|
+
* (already-markdown) content verbatim underneath.
|
|
45
|
+
*
|
|
46
|
+
* @param args - see {@link ConversationExportArgs}.
|
|
47
|
+
* @returns the Markdown document text (trailing newline included).
|
|
48
|
+
*/
|
|
49
|
+
export declare function buildConversationMarkdown(args: ConversationExportArgs): string;
|
|
50
|
+
/**
|
|
51
|
+
* Derives a safe `.md` filename from the session title.
|
|
52
|
+
*
|
|
53
|
+
* Lowercases, strips diacritics (Czech/Slovak titles are common here),
|
|
54
|
+
* collapses every non-alphanumeric run to a single `-`, and appends the
|
|
55
|
+
* export date so repeated exports don't shadow each other in the user's
|
|
56
|
+
* downloads folder. Falls back to `conversation` for titles that reduce
|
|
57
|
+
* to nothing.
|
|
58
|
+
*
|
|
59
|
+
* @param sessionTitle - the session's title.
|
|
60
|
+
* @param exportedAt - export timestamp (date part is used).
|
|
61
|
+
* @returns e.g. `muj-rozhovor-2026-07-17.md`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function conversationExportFilename(sessionTitle: string, exportedAt: Date): string;
|
|
64
|
+
//# sourceMappingURL=exportConversation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exportConversation.d.ts","sourceRoot":"","sources":["../../src/util/exportConversation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,oDAAoD;AACpD,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACtC,6DAA6D;IAC7D,UAAU,EAAE,IAAI,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,CAqB9E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,IAAI,GACf,MAAM,CAUR"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation → Markdown export helpers.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions — the `<MainColumn />` export button calls
|
|
5
|
+
* `buildConversationMarkdown` on the already-loaded `useAIHub().messages`
|
|
6
|
+
* array and hands the result to a Blob download. Keeping the serialization
|
|
7
|
+
* here (instead of inline in the component) makes the export rules
|
|
8
|
+
* unit-testable without a DOM.
|
|
9
|
+
*
|
|
10
|
+
* Export rules:
|
|
11
|
+
*
|
|
12
|
+
* - Only `user` and `assistant` messages are exported. `system` rows (the
|
|
13
|
+
* compiled system prompt travels in the transcript as `role: "system"`)
|
|
14
|
+
* and `tool` rows never appear in the file.
|
|
15
|
+
* - Assistant messages with no text content (tool-call-only / reasoning-only
|
|
16
|
+
* bubbles) are skipped — the export is the human-readable dialog, not the
|
|
17
|
+
* agent trace.
|
|
18
|
+
* - Rotating-message sessions need no special casing: the rotation runner
|
|
19
|
+
* deletes its own prompt's `user_message` from the Letta conversation, so
|
|
20
|
+
* the transcript (and therefore the export) opens with the agent's reply.
|
|
21
|
+
*
|
|
22
|
+
* @see ../components/MainColumn/index.tsx — the export button
|
|
23
|
+
* @see SPECIFICATIONS.md §8.4 — `export_conversation_enabled` toggle
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Serializes a conversation to a Markdown document.
|
|
27
|
+
*
|
|
28
|
+
* Format: an `# <title>` heading plus an "exported" byline, then one
|
|
29
|
+
* `## <speaker>` section per user/assistant message with the message's
|
|
30
|
+
* (already-markdown) content verbatim underneath.
|
|
31
|
+
*
|
|
32
|
+
* @param args - see {@link ConversationExportArgs}.
|
|
33
|
+
* @returns the Markdown document text (trailing newline included).
|
|
34
|
+
*/
|
|
35
|
+
export function buildConversationMarkdown(args) {
|
|
36
|
+
const lines = [];
|
|
37
|
+
lines.push(`# ${args.sessionTitle}`);
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push(`> ${args.agentDisplayName} — exported ${args.exportedAt.toISOString()}`);
|
|
40
|
+
for (const msg of args.messages) {
|
|
41
|
+
if (msg.role !== "user" && msg.role !== "assistant")
|
|
42
|
+
continue;
|
|
43
|
+
const content = msg.content.trim();
|
|
44
|
+
if (content.length === 0)
|
|
45
|
+
continue;
|
|
46
|
+
const speaker = msg.role === "user" ? args.userLabel : args.agentDisplayName;
|
|
47
|
+
lines.push("");
|
|
48
|
+
lines.push(`## ${speaker}`);
|
|
49
|
+
lines.push("");
|
|
50
|
+
lines.push(content);
|
|
51
|
+
}
|
|
52
|
+
return `${lines.join("\n")}\n`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Derives a safe `.md` filename from the session title.
|
|
56
|
+
*
|
|
57
|
+
* Lowercases, strips diacritics (Czech/Slovak titles are common here),
|
|
58
|
+
* collapses every non-alphanumeric run to a single `-`, and appends the
|
|
59
|
+
* export date so repeated exports don't shadow each other in the user's
|
|
60
|
+
* downloads folder. Falls back to `conversation` for titles that reduce
|
|
61
|
+
* to nothing.
|
|
62
|
+
*
|
|
63
|
+
* @param sessionTitle - the session's title.
|
|
64
|
+
* @param exportedAt - export timestamp (date part is used).
|
|
65
|
+
* @returns e.g. `muj-rozhovor-2026-07-17.md`.
|
|
66
|
+
*/
|
|
67
|
+
export function conversationExportFilename(sessionTitle, exportedAt) {
|
|
68
|
+
const slug = sessionTitle
|
|
69
|
+
.normalize("NFKD")
|
|
70
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
71
|
+
.toLowerCase()
|
|
72
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
73
|
+
.replace(/^-+|-+$/g, "")
|
|
74
|
+
.slice(0, 60);
|
|
75
|
+
const date = exportedAt.toISOString().slice(0, 10);
|
|
76
|
+
return `${slug.length > 0 ? slug : "conversation"}-${date}.md`;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=exportConversation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exportConversation.js","sourceRoot":"","sources":["../../src/util/exportConversation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAkBH;;;;;;;;;GASG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAA4B;IACpE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IACrC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CACR,KAAK,IAAI,CAAC,gBAAgB,eAAe,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,CACzE,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW;YAAE,SAAS;QAC9D,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,MAAM,OAAO,GACX,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC;QAC/D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,0BAA0B,CACxC,YAAoB,EACpB,UAAgB;IAEhB,MAAM,IAAI,GAAG,YAAY;SACtB,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACnD,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,IAAI,IAAI,KAAK,CAAC;AACjE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@data-club/ai-hub",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "React package for the data-club ai-hub: chat UI, login + change-password, admin UI, AIHub.* primitives, defineWebComponent helper, client SDK. See docs/SPECIFICATIONS.md §7.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
package/src/auth/locales/cs.ts
CHANGED
|
@@ -68,6 +68,10 @@ export const csTexts: AIHubTexts = {
|
|
|
68
68
|
collapseSessionsPanel: "Sbalit panel konverzací",
|
|
69
69
|
expandSessionsPanel: "Zobrazit panel konverzací",
|
|
70
70
|
backToAgentsLink: "← Agenti",
|
|
71
|
+
exportConversationButton: "Export .md",
|
|
72
|
+
exportConversationAriaLabel: "Exportovat konverzaci jako Markdown",
|
|
73
|
+
exportUserLabel: "Vy",
|
|
74
|
+
exportAssistantFallbackLabel: "Asistent",
|
|
71
75
|
untitledSessionFallback: "(bez názvu)",
|
|
72
76
|
noActiveSessionHint:
|
|
73
77
|
"Vyberte konverzaci vlevo nebo začněte novou.",
|
package/src/auth/locales/sk.ts
CHANGED
|
@@ -68,6 +68,10 @@ export const skTexts: AIHubTexts = {
|
|
|
68
68
|
collapseSessionsPanel: "Zbaliť panel konverzácií",
|
|
69
69
|
expandSessionsPanel: "Zobraziť panel konverzácií",
|
|
70
70
|
backToAgentsLink: "← Agenti",
|
|
71
|
+
exportConversationButton: "Export .md",
|
|
72
|
+
exportConversationAriaLabel: "Exportovať konverzáciu ako Markdown",
|
|
73
|
+
exportUserLabel: "Vy",
|
|
74
|
+
exportAssistantFallbackLabel: "Asistent",
|
|
71
75
|
untitledSessionFallback: "(bez názvu)",
|
|
72
76
|
noActiveSessionHint:
|
|
73
77
|
"Vyberte konverzáciu vľavo alebo začnite novú.",
|
package/src/auth/texts.ts
CHANGED
|
@@ -154,6 +154,14 @@ export interface AIHubChatTexts {
|
|
|
154
154
|
expandSessionsPanel: string;
|
|
155
155
|
/** `[← Agents]` back-to-picker link in the chat header. */
|
|
156
156
|
backToAgentsLink: string;
|
|
157
|
+
/** Export-conversation (.md) button label in the chat header. */
|
|
158
|
+
exportConversationButton: string;
|
|
159
|
+
/** `aria-label` / tooltip on the export-conversation button. */
|
|
160
|
+
exportConversationAriaLabel: string;
|
|
161
|
+
/** Speaker heading for the user's messages in the exported Markdown. */
|
|
162
|
+
exportUserLabel: string;
|
|
163
|
+
/** Assistant speaker heading in the export when no agent name resolves. */
|
|
164
|
+
exportAssistantFallbackLabel: string;
|
|
157
165
|
/** Fallback title for a session somehow rendered without one. */
|
|
158
166
|
untitledSessionFallback: string;
|
|
159
167
|
/** Body shown when no session is selected yet. */
|
|
@@ -921,6 +929,10 @@ export const defaultAIHubTexts: AIHubTexts = Object.freeze({
|
|
|
921
929
|
collapseSessionsPanel: "Collapse sessions panel",
|
|
922
930
|
expandSessionsPanel: "Show sessions panel",
|
|
923
931
|
backToAgentsLink: "← Agents",
|
|
932
|
+
exportConversationButton: "Export .md",
|
|
933
|
+
exportConversationAriaLabel: "Export conversation as Markdown",
|
|
934
|
+
exportUserLabel: "You",
|
|
935
|
+
exportAssistantFallbackLabel: "Assistant",
|
|
924
936
|
untitledSessionFallback: "(untitled)",
|
|
925
937
|
noActiveSessionHint:
|
|
926
938
|
"Pick a chat from the left or start a new one to begin.",
|
|
@@ -100,6 +100,8 @@ export interface ChatShellProps {
|
|
|
100
100
|
showScrollToPresentButton?: boolean;
|
|
101
101
|
/** turn_status_visible default. */
|
|
102
102
|
showTurnStatus?: boolean;
|
|
103
|
+
/** export_conversation_enabled default. */
|
|
104
|
+
showExportButton?: boolean;
|
|
103
105
|
/** Whether the ThemeSwitcher renders in the user menu (server override wins). */
|
|
104
106
|
showThemeSwitcher?: boolean;
|
|
105
107
|
|
|
@@ -153,6 +155,8 @@ function buildPropOverrides(
|
|
|
153
155
|
out.scrollToPresentVisible = props.showScrollToPresentButton;
|
|
154
156
|
if (props.showTurnStatus !== undefined)
|
|
155
157
|
out.turnStatusVisible = props.showTurnStatus;
|
|
158
|
+
if (props.showExportButton !== undefined)
|
|
159
|
+
out.exportConversationEnabled = props.showExportButton;
|
|
156
160
|
return out;
|
|
157
161
|
}
|
|
158
162
|
|
|
@@ -293,6 +297,7 @@ export function ChatShell(props: ChatShellProps): ReactNode {
|
|
|
293
297
|
showAgentsPicker && agentSwitcherEnabled && agents.length > 1
|
|
294
298
|
}
|
|
295
299
|
showTurnStatus={flags.turnStatusVisible}
|
|
300
|
+
showExportButton={flags.exportConversationEnabled}
|
|
296
301
|
{...(props.texts !== undefined ? { texts: props.texts } : {})}
|
|
297
302
|
{...(props.customHeaderContent !== undefined
|
|
298
303
|
? { customHeaderContent: props.customHeaderContent }
|
|
@@ -114,6 +114,8 @@ export interface DataClubAIHubProps {
|
|
|
114
114
|
showScrollToPresentButton?: boolean;
|
|
115
115
|
/** Default for turn_status_visible. Default true. */
|
|
116
116
|
showTurnStatus?: boolean;
|
|
117
|
+
/** Default for export_conversation_enabled. Default true. */
|
|
118
|
+
showExportButton?: boolean;
|
|
117
119
|
|
|
118
120
|
/* ── Theming (§7.6) ────────────────────────────────────────────── */
|
|
119
121
|
/**
|
|
@@ -300,6 +302,9 @@ function AuthedShell({ props }: { props: DataClubAIHubProps }): ReactNode {
|
|
|
300
302
|
{...(props.showTurnStatus !== undefined
|
|
301
303
|
? { showTurnStatus: props.showTurnStatus }
|
|
302
304
|
: {})}
|
|
305
|
+
{...(props.showExportButton !== undefined
|
|
306
|
+
? { showExportButton: props.showExportButton }
|
|
307
|
+
: {})}
|
|
303
308
|
{...(props.showThemeSwitcher !== undefined
|
|
304
309
|
? { showThemeSwitcher: props.showThemeSwitcher }
|
|
305
310
|
: {})}
|
|
@@ -53,6 +53,7 @@ const ALL_TOGGLE_KEYS: ReadonlyArray<keyof AIHubFeatureToggles> = [
|
|
|
53
53
|
"effort_control_visible",
|
|
54
54
|
"scroll_to_present_visible",
|
|
55
55
|
"turn_status_visible",
|
|
56
|
+
"export_conversation_enabled",
|
|
56
57
|
];
|
|
57
58
|
|
|
58
59
|
/** Toggles grouped by the §8.4 visual grouping (purely organizational). */
|
|
@@ -83,6 +84,7 @@ const TOGGLE_GROUPS: ReadonlyArray<{
|
|
|
83
84
|
"tpm_notice_visible",
|
|
84
85
|
"scroll_to_present_visible",
|
|
85
86
|
"turn_status_visible",
|
|
87
|
+
"export_conversation_enabled",
|
|
86
88
|
],
|
|
87
89
|
},
|
|
88
90
|
];
|
|
@@ -614,7 +616,7 @@ function FeatureTogglesSection(props: FeatureTogglesSectionProps): ReactNode {
|
|
|
614
616
|
// The server's blob may omit keys (meaning "fall through to defaults"). The
|
|
615
617
|
// UI shows the effective value for the user — fill in defaults for any
|
|
616
618
|
// missing key. Save only sends the keys the user actually has toggled (in
|
|
617
|
-
// our case all of them, since the blob always carries all
|
|
619
|
+
// our case all of them, since the blob always carries all 14 once saved).
|
|
618
620
|
const [values, setValues] = useState<Record<string, boolean>>(() => {
|
|
619
621
|
const initial: Record<string, boolean> = {};
|
|
620
622
|
for (const key of ALL_TOGGLE_KEYS) {
|
|
@@ -22,6 +22,10 @@ import {
|
|
|
22
22
|
} from "../../auth/texts.js";
|
|
23
23
|
import { useResolvedTexts } from "../../context/useAIHubTexts.js";
|
|
24
24
|
import { useAIHub } from "../../context/useAIHub.js";
|
|
25
|
+
import {
|
|
26
|
+
buildConversationMarkdown,
|
|
27
|
+
conversationExportFilename,
|
|
28
|
+
} from "../../util/exportConversation.js";
|
|
25
29
|
|
|
26
30
|
import { TurnStatusIndicator } from "../TurnStatusIndicator/index.js";
|
|
27
31
|
|
|
@@ -37,6 +41,8 @@ export interface MainColumnClassNames {
|
|
|
37
41
|
back: string;
|
|
38
42
|
/** Agent display-name text. */
|
|
39
43
|
title: string;
|
|
44
|
+
/** Export-conversation (.md) button. */
|
|
45
|
+
export: string;
|
|
40
46
|
/** Wrapper for slot content on the right side of the header. */
|
|
41
47
|
extras: string;
|
|
42
48
|
/** Children container (messages + input live here). */
|
|
@@ -48,6 +54,7 @@ const DEFAULT_CLASS_NAMES: MainColumnClassNames = Object.freeze({
|
|
|
48
54
|
header: "data-club-ai-hub__chat-header",
|
|
49
55
|
back: "data-club-ai-hub__chat-header__back",
|
|
50
56
|
title: "data-club-ai-hub__chat-header__title",
|
|
57
|
+
export: "data-club-ai-hub__chat-header__export",
|
|
51
58
|
extras: "data-club-ai-hub__chat-header__extras",
|
|
52
59
|
body: "data-club-ai-hub__main-column__body",
|
|
53
60
|
}) as MainColumnClassNames;
|
|
@@ -68,6 +75,12 @@ export interface MainColumnProps {
|
|
|
68
75
|
* default). Defaults to true.
|
|
69
76
|
*/
|
|
70
77
|
showTurnStatus?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Whether the export-conversation (.md) button renders in the chat
|
|
80
|
+
* header. Receives the resolved §8.4 `export_conversation_enabled`
|
|
81
|
+
* flag. Defaults to true.
|
|
82
|
+
*/
|
|
83
|
+
showExportButton?: boolean;
|
|
71
84
|
/** Slot rendered on the right side of the chat header. */
|
|
72
85
|
customHeaderContent?: ReactNode;
|
|
73
86
|
/** The children — `<MessageList />` + `<MessageInput />` (or whatever). */
|
|
@@ -87,17 +100,75 @@ export interface MainColumnProps {
|
|
|
87
100
|
* @returns the rendered column.
|
|
88
101
|
*/
|
|
89
102
|
export function MainColumn(props: MainColumnProps): ReactNode {
|
|
90
|
-
const {
|
|
103
|
+
const {
|
|
104
|
+
agents,
|
|
105
|
+
activeAgentId,
|
|
106
|
+
setActiveAgent,
|
|
107
|
+
sessions,
|
|
108
|
+
activeSessionId,
|
|
109
|
+
messages,
|
|
110
|
+
} = useAIHub();
|
|
91
111
|
const texts = useResolvedTexts(props.texts);
|
|
92
112
|
const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
|
|
93
113
|
const showBack = props.showBackToAgents ?? true;
|
|
94
114
|
const showTurnStatus = props.showTurnStatus ?? true;
|
|
115
|
+
const showExportButton = props.showExportButton ?? true;
|
|
95
116
|
|
|
96
117
|
const activeAgent = useMemo(
|
|
97
118
|
() => agents.find((a) => a.id === activeAgentId) ?? null,
|
|
98
119
|
[agents, activeAgentId],
|
|
99
120
|
);
|
|
100
121
|
|
|
122
|
+
const activeSession = useMemo(
|
|
123
|
+
() => (sessions ?? []).find((s) => s.id === activeSessionId) ?? null,
|
|
124
|
+
[sessions, activeSessionId],
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Whether the export button has anything to export — at least one
|
|
128
|
+
// user/assistant message with text content (mirrors the serializer's
|
|
129
|
+
// skip rules so we never download an empty document).
|
|
130
|
+
const hasExportableMessages = useMemo(
|
|
131
|
+
() =>
|
|
132
|
+
(messages ?? []).some(
|
|
133
|
+
(m) =>
|
|
134
|
+
(m.role === "user" || m.role === "assistant") &&
|
|
135
|
+
m.content.trim().length > 0,
|
|
136
|
+
),
|
|
137
|
+
[messages],
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Serializes the visible conversation to Markdown and triggers a
|
|
142
|
+
* client-side download. System-prompt rows (`role: "system"`) and tool
|
|
143
|
+
* rows are excluded by the serializer; rotating-message sessions open
|
|
144
|
+
* with the agent's reply because the rotation runner already deleted
|
|
145
|
+
* its own prompt server-side.
|
|
146
|
+
*/
|
|
147
|
+
function handleExport(): void {
|
|
148
|
+
const exportedAt = new Date();
|
|
149
|
+
const sessionTitle =
|
|
150
|
+
activeSession?.title && activeSession.title.trim().length > 0
|
|
151
|
+
? activeSession.title
|
|
152
|
+
: texts.chat.untitledSessionFallback;
|
|
153
|
+
const markdown = buildConversationMarkdown({
|
|
154
|
+
sessionTitle,
|
|
155
|
+
agentDisplayName:
|
|
156
|
+
activeAgent?.display_name ?? texts.chat.exportAssistantFallbackLabel,
|
|
157
|
+
userLabel: texts.chat.exportUserLabel,
|
|
158
|
+
messages: messages ?? [],
|
|
159
|
+
exportedAt,
|
|
160
|
+
});
|
|
161
|
+
const blob = new Blob([markdown], { type: "text/markdown;charset=utf-8" });
|
|
162
|
+
const url = URL.createObjectURL(blob);
|
|
163
|
+
const anchor = document.createElement("a");
|
|
164
|
+
anchor.href = url;
|
|
165
|
+
anchor.download = conversationExportFilename(sessionTitle, exportedAt);
|
|
166
|
+
document.body.appendChild(anchor);
|
|
167
|
+
anchor.click();
|
|
168
|
+
anchor.remove();
|
|
169
|
+
URL.revokeObjectURL(url);
|
|
170
|
+
}
|
|
171
|
+
|
|
101
172
|
const rootClass = props.className
|
|
102
173
|
? `${cls.root} ${props.className}`
|
|
103
174
|
: cls.root;
|
|
@@ -119,6 +190,19 @@ export function MainColumn(props: MainColumnProps): ReactNode {
|
|
|
119
190
|
{activeAgent?.display_name ?? ""}
|
|
120
191
|
</h2>
|
|
121
192
|
{showTurnStatus ? <TurnStatusIndicator /> : null}
|
|
193
|
+
{showExportButton && activeSessionId !== null ? (
|
|
194
|
+
<button
|
|
195
|
+
type="button"
|
|
196
|
+
className={cls.export}
|
|
197
|
+
onClick={handleExport}
|
|
198
|
+
disabled={!hasExportableMessages}
|
|
199
|
+
aria-label={texts.chat.exportConversationAriaLabel}
|
|
200
|
+
title={texts.chat.exportConversationAriaLabel}
|
|
201
|
+
data-testid="chat-header-export"
|
|
202
|
+
>
|
|
203
|
+
{texts.chat.exportConversationButton}
|
|
204
|
+
</button>
|
|
205
|
+
) : null}
|
|
122
206
|
{props.customHeaderContent ? (
|
|
123
207
|
<div className={cls.extras} data-testid="chat-header-extras">
|
|
124
208
|
{props.customHeaderContent}
|