@promptbook/cli 0.112.0-125 → 0.112.0-127
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/README.md +5 -5
- package/apps/agents-server/README.md +3 -0
- package/apps/agents-server/playwright.config.ts +1 -0
- package/apps/agents-server/public/promptbook-logo-blue.png +0 -0
- package/apps/agents-server/public/promptbook-logo-white.png +0 -0
- package/apps/agents-server/src/app/[agentName]/layout.tsx +1 -0
- package/apps/agents-server/src/app/actions.ts +2 -2
- package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +68 -36
- package/apps/agents-server/src/app/agents/[agentName]/ActiveAgentBreadcrumbBinder.tsx +30 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +2 -0
- package/apps/agents-server/src/app/agents/[agentName]/chat/AgentChatHistoryPayloadState.ts +38 -4
- package/apps/agents-server/src/app/agents/[agentName]/chat/AgentChatHistorySyncOperations.ts +4 -1
- package/apps/agents-server/src/app/agents/[agentName]/chat/CanonicalAgentChatSurface.tsx +19 -15
- package/apps/agents-server/src/app/agents/[agentName]/chat/useCanonicalAgentChatPanelState.ts +58 -7
- package/apps/agents-server/src/app/agents/[agentName]/layout.tsx +47 -1
- package/apps/agents-server/src/app/api/chat/citation-label/route.ts +133 -0
- package/apps/agents-server/src/app/globals.css +78 -0
- package/apps/agents-server/src/components/Header/ActiveAgentBreadcrumbContext.tsx +82 -0
- package/apps/agents-server/src/components/Header/useHeaderActiveAgent.ts +26 -7
- package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +35 -32
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/ManGoNewAgentWizard.tsx +151 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/ManGoOnboardingNavigation.tsx +50 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/BookLanguagePanel.tsx +125 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/DropZone.tsx +83 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/EmailTestRun.tsx +216 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/KnowledgeList.tsx +79 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/Logo.tsx +20 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/MarkdownBookEditor.tsx +154 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/MarkdownPreview.tsx +188 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/RailStepper.tsx +115 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/StepFrame.tsx +47 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/TestChat.tsx +159 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/WizardShell.tsx +114 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/brand/RailArtwork.tsx +60 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/BookStep.tsx +135 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/DoneStep.tsx +215 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/KnowledgeStep.tsx +152 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/TestStep.tsx +262 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/ZadaniStep.tsx +64 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ui/Badge.tsx +41 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ui/Banner.tsx +69 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ui/Button.tsx +77 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ui/Card.tsx +33 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ui/Field.tsx +103 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ui/IconButton.tsx +40 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ui/Spinner.tsx +14 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ui/tokens.ts +37 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/config/bookSections.ts +62 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/config/emailScenarios.ts +22 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/config/steps.ts +46 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/index.ts +11 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/lib/cn.ts +4 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/lib/format.ts +9 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/lib/id.ts +11 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/agentEvalService.ts +30 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/agentTestService.ts +69 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/bookService.ts +21 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/createManGoAgentSource.ts +107 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/draftService.ts +45 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/uploadService.ts +27 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/state/OnboardingProvider.tsx +121 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/types.ts +52 -0
- package/apps/agents-server/src/components/NewAgentDialog/createNewAgentWizardSource.ts +1 -1
- package/apps/agents-server/src/components/NewAgentDialog/trackNewAgentCreationEvent.ts +1 -1
- package/apps/agents-server/src/components/NewAgentDialog/useNewAgentDialog.tsx +76 -0
- package/apps/agents-server/src/constants/newAgentWizard.ts +17 -8
- package/apps/agents-server/src/database/getMetadata.ts +37 -1
- package/apps/agents-server/src/database/metadataDefaults.ts +18 -7
- package/apps/agents-server/src/database/migrations/2026-06-2200-new-agent-wizard-metadata-key.sql +27 -0
- package/apps/agents-server/src/database/migrations/2026-06-2201-new-agent-wizard-mango-default.sql +11 -0
- package/apps/agents-server/src/generated/reservedPaths.ts +2 -0
- package/apps/agents-server/src/languages/translations/english.yaml +1 -1
- package/apps/agents-server/src/tools/createChatAttachmentToolFunctions.ts +8 -4
- package/apps/agents-server/src/utils/chat/resolveAgentsServerCitationLabel.ts +130 -0
- package/apps/agents-server/src/utils/chat/resolveCitationSourceLabel.ts +436 -0
- package/apps/agents-server/src/utils/knowledge/resolveWebsiteKnowledgeSourcesForServer.ts +10 -1
- package/apps/agents-server/src/utils/session.ts +62 -5
- package/apps/agents-server/src/utils/transpilers/resolveTranspiledTeamExport.ts +10 -10
- package/apps/agents-server/src/utils/userChat/userChatProgressCard.ts +198 -63
- package/apps/agents-server/src/utils/vpsConfiguration.ts +1 -0
- package/apps/agents-server/src/utils/vpsSelfUpdate.ts +81 -8
- package/esm/index.es.js +1052 -455
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/git/commitChanges.d.ts +3 -1
- package/esm/scripts/run-codex-prompts/main/runPromptRound.d.ts +2 -2
- package/esm/scripts/run-codex-prompts/server/buildCoderServerPromptResponse.d.ts +50 -0
- package/esm/scripts/run-codex-prompts/server/buildCoderServerRunState.d.ts +23 -0
- package/esm/scripts/run-codex-prompts/server/coderServerHtml.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/server/runCoderHttpServer.d.ts +13 -1
- package/esm/scripts/run-codex-prompts/server/updatePromptSection.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +1 -0
- package/esm/scripts/run-codex-prompts/ui/buildRunUiFrameShared.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/ui/renderCoderRunUi.d.ts +1 -0
- package/esm/src/_packages/components.index.d.ts +2 -0
- package/esm/src/_packages/types.index.d.ts +2 -0
- package/esm/src/avatars/avatarAnimationScheduler.d.ts +4 -0
- package/esm/src/book-components/Chat/Chat/ChatCitationModal.d.ts +2 -0
- package/esm/src/book-components/Chat/Chat/ChatMessageItem.d.ts +4 -0
- package/esm/src/book-components/Chat/Chat/ChatMessageList.d.ts +4 -0
- package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
- package/esm/src/book-components/Chat/Chat/ChatToolCallModal.d.ts +2 -0
- package/esm/src/book-components/Chat/Chat/ChatToolCallModalContent.d.ts +3 -1
- package/esm/src/book-components/Chat/Chat/TeamToolCallModalContent.d.ts +2 -0
- package/esm/src/book-components/Chat/SourceChip/SourceChip.d.ts +6 -1
- package/esm/src/book-components/Chat/hooks/useResolvedCitationLabel.d.ts +12 -0
- package/esm/src/book-components/Chat/types/ChatMessage.d.ts +4 -0
- package/esm/src/book-components/Chat/types/ChatParticipant.d.ts +1 -1
- package/esm/src/book-components/Chat/types/CitationLabelResolver.d.ts +8 -0
- package/esm/src/book-components/Chat/utils/citationHelpers.d.ts +9 -0
- package/esm/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.d.ts +14 -0
- package/esm/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.test.d.ts +1 -0
- package/esm/src/book-components/Chat/utils/parseCitationsFromContent.d.ts +4 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/_packages/components.index.ts +2 -0
- package/src/_packages/types.index.ts +2 -0
- package/src/avatars/avatarAnimationScheduler.ts +61 -20
- package/src/avatars/visuals/octopus3d2AvatarVisual.ts +106 -21
- package/src/avatars/visuals/octopus3d3AvatarVisual.ts +131 -28
- package/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments/augmentAgentModelRequirementsFromSource.ts +18 -2
- package/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.ts +7 -1
- package/src/book-components/Chat/Chat/Chat.tsx +4 -0
- package/src/book-components/Chat/Chat/ChatCitationModal.tsx +17 -3
- package/src/book-components/Chat/Chat/ChatMessageItem.tsx +22 -2
- package/src/book-components/Chat/Chat/ChatMessageList.tsx +6 -0
- package/src/book-components/Chat/Chat/ChatProps.tsx +6 -0
- package/src/book-components/Chat/Chat/ChatToolCallModal.tsx +4 -0
- package/src/book-components/Chat/Chat/ChatToolCallModalContent.tsx +4 -0
- package/src/book-components/Chat/Chat/TeamToolCallModalContent.tsx +16 -3
- package/src/book-components/Chat/Chat/useChatPostprocessedMessages.ts +13 -2
- package/src/book-components/Chat/SourceChip/SourceChip.module.css +8 -0
- package/src/book-components/Chat/SourceChip/SourceChip.tsx +19 -5
- package/src/book-components/Chat/hooks/useResolvedCitationLabel.ts +65 -0
- package/src/book-components/Chat/save/html/htmlSaveFormatDefinition.ts +315 -88
- package/src/book-components/Chat/save/react/reactSaveFormatDefinition.ts +7 -1
- package/src/book-components/Chat/types/ChatMessage.ts +5 -0
- package/src/book-components/Chat/types/ChatParticipant.ts +1 -1
- package/src/book-components/Chat/types/CitationLabelResolver.ts +9 -0
- package/src/book-components/Chat/utils/citationHelpers.ts +90 -2
- package/src/book-components/Chat/utils/createCitationFootnoteRenderModel.ts +3 -0
- package/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.ts +178 -0
- package/src/book-components/Chat/utils/parseCitationsFromContent.ts +6 -0
- package/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.ts +13 -2
- package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +1 -1
- package/src/cli/cli-commands/coder/run.ts +17 -20
- package/src/cli/cli-commands/coder/server.ts +13 -16
- package/src/cli/common/$deprecateCliCommand.ts +10 -1
- package/src/commitments/GOAL/GOAL.ts +7 -2
- package/src/commitments/LANGUAGE/LANGUAGE.ts +7 -2
- package/src/commitments/TEAM/TEAM.ts +12 -1
- package/src/commitments/USE_PROJECT/createUseProjectToolFunctions.ts +8 -1
- package/src/import-plugins/JsonFileImportPlugin.ts +15 -2
- package/src/import-plugins/TextFileImportPlugin.ts +8 -1
- package/src/llm-providers/_common/register/$registeredLlmToolsMessage.ts +6 -1
- package/src/other/templates/getTemplatesPipelineCollection.ts +696 -941
- package/src/utils/chat/chatAttachments/resolveChatAttachmentContent.ts +8 -1
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -1
- package/umd/index.umd.js +1055 -458
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/git/commitChanges.d.ts +3 -1
- package/umd/scripts/run-codex-prompts/main/runPromptRound.d.ts +2 -2
- package/umd/scripts/run-codex-prompts/server/buildCoderServerPromptResponse.d.ts +50 -0
- package/umd/scripts/run-codex-prompts/server/buildCoderServerRunState.d.ts +23 -0
- package/umd/scripts/run-codex-prompts/server/coderServerHtml.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/server/runCoderHttpServer.d.ts +13 -1
- package/umd/scripts/run-codex-prompts/server/updatePromptSection.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +1 -0
- package/umd/scripts/run-codex-prompts/ui/buildRunUiFrameShared.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/ui/renderCoderRunUi.d.ts +1 -0
- package/umd/src/_packages/components.index.d.ts +2 -0
- package/umd/src/_packages/types.index.d.ts +2 -0
- package/umd/src/avatars/avatarAnimationScheduler.d.ts +4 -0
- package/umd/src/book-components/Chat/Chat/ChatCitationModal.d.ts +2 -0
- package/umd/src/book-components/Chat/Chat/ChatMessageItem.d.ts +4 -0
- package/umd/src/book-components/Chat/Chat/ChatMessageList.d.ts +4 -0
- package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
- package/umd/src/book-components/Chat/Chat/ChatToolCallModal.d.ts +2 -0
- package/umd/src/book-components/Chat/Chat/ChatToolCallModalContent.d.ts +3 -1
- package/umd/src/book-components/Chat/Chat/TeamToolCallModalContent.d.ts +2 -0
- package/umd/src/book-components/Chat/SourceChip/SourceChip.d.ts +6 -1
- package/umd/src/book-components/Chat/hooks/useResolvedCitationLabel.d.ts +12 -0
- package/umd/src/book-components/Chat/types/ChatMessage.d.ts +4 -0
- package/umd/src/book-components/Chat/types/ChatParticipant.d.ts +1 -1
- package/umd/src/book-components/Chat/types/CitationLabelResolver.d.ts +8 -0
- package/umd/src/book-components/Chat/utils/citationHelpers.d.ts +9 -0
- package/umd/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.d.ts +14 -0
- package/umd/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.test.d.ts +1 -0
- package/umd/src/book-components/Chat/utils/parseCitationsFromContent.d.ts +4 -0
- package/umd/src/version.d.ts +1 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { ONBOARDING_FLOW, getFlowIndexByPath } from '../config/steps';
|
|
4
|
+
import { useManGoOnboardingNavigation } from '../ManGoOnboardingNavigation';
|
|
5
|
+
import { useOnboarding } from '../state/OnboardingProvider';
|
|
6
|
+
import { Logo } from './Logo';
|
|
7
|
+
import { RailStepper } from './RailStepper';
|
|
8
|
+
import { RailArtwork } from './brand/RailArtwork';
|
|
9
|
+
|
|
10
|
+
const RAIL_GRADIENT: CSSProperties = {
|
|
11
|
+
backgroundImage: 'var(--ob-grad-ink)',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Split-screen wizard chrome: a persistent accent rail (brand identity, agent name,
|
|
16
|
+
* vertical stepper, progress) beside the active step. The rail collapses to a compact
|
|
17
|
+
* top bar on small screens.
|
|
18
|
+
*/
|
|
19
|
+
export function WizardShell({ children }: { readonly children: ReactNode }) {
|
|
20
|
+
const { currentPath, requestClose } = useManGoOnboardingNavigation();
|
|
21
|
+
const { state } = useOnboarding();
|
|
22
|
+
|
|
23
|
+
const activeIndex = getFlowIndexByPath(currentPath);
|
|
24
|
+
const total = ONBOARDING_FLOW.length;
|
|
25
|
+
const progress = Math.round(((activeIndex + 1) / total) * 100);
|
|
26
|
+
const agentName = state.agentName.trim() || 'Váš nový agent';
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div data-onboarding-ui className="flex min-h-screen flex-col bg-zinc-50 text-zinc-900 lg:flex-row">
|
|
30
|
+
{/* Mobile: compact top bar */}
|
|
31
|
+
<div className="relative overflow-hidden text-white lg:hidden" style={RAIL_GRADIENT}>
|
|
32
|
+
<div className="relative z-10 flex items-center justify-between px-5 py-3.5">
|
|
33
|
+
<button
|
|
34
|
+
type="button"
|
|
35
|
+
onClick={requestClose}
|
|
36
|
+
className="rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50"
|
|
37
|
+
>
|
|
38
|
+
<Logo className="text-white" />
|
|
39
|
+
</button>
|
|
40
|
+
<span className="max-w-[40%] truncate text-[13px] text-white/80">{agentName}</span>
|
|
41
|
+
<button
|
|
42
|
+
type="button"
|
|
43
|
+
onClick={requestClose}
|
|
44
|
+
aria-label="Zavřít průvodce"
|
|
45
|
+
className="flex h-8 w-8 items-center justify-center rounded-lg text-xl leading-none text-white/70 transition-colors hover:bg-white/10 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50"
|
|
46
|
+
>
|
|
47
|
+
×
|
|
48
|
+
</button>
|
|
49
|
+
</div>
|
|
50
|
+
<div className="relative z-10 overflow-x-auto px-5 pb-3.5">
|
|
51
|
+
<RailStepper activeIndex={activeIndex} orientation="horizontal" />
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
{/* Desktop: persistent side rail */}
|
|
56
|
+
<aside
|
|
57
|
+
className="relative hidden w-80 flex-shrink-0 overflow-hidden p-7 text-white lg:sticky lg:top-0 lg:flex lg:h-screen lg:flex-col"
|
|
58
|
+
style={RAIL_GRADIENT}
|
|
59
|
+
>
|
|
60
|
+
<RailArtwork />
|
|
61
|
+
<div className="relative z-10 flex h-full flex-col">
|
|
62
|
+
<div className="flex items-center justify-between gap-3">
|
|
63
|
+
<button
|
|
64
|
+
type="button"
|
|
65
|
+
onClick={requestClose}
|
|
66
|
+
className="inline-flex w-fit rounded-lg transition-opacity hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50"
|
|
67
|
+
>
|
|
68
|
+
<Logo className="text-white" />
|
|
69
|
+
</button>
|
|
70
|
+
<button
|
|
71
|
+
type="button"
|
|
72
|
+
onClick={requestClose}
|
|
73
|
+
aria-label="Zavřít průvodce"
|
|
74
|
+
className="flex h-9 w-9 items-center justify-center rounded-lg text-2xl leading-none text-white/55 transition-colors hover:bg-white/10 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50"
|
|
75
|
+
>
|
|
76
|
+
×
|
|
77
|
+
</button>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div className="mt-10">
|
|
81
|
+
<div className="text-xs font-medium text-white/60">Tvorba agenta</div>
|
|
82
|
+
<div className="ob-display mt-1 text-[19px] font-semibold leading-snug">{agentName}</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div className="mt-9 flex-1">
|
|
86
|
+
<RailStepper activeIndex={activeIndex} orientation="vertical" />
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div className="relative z-10 mt-6">
|
|
90
|
+
<div className="mb-1.5 flex justify-between text-xs text-white/75">
|
|
91
|
+
<span>Průběh</span>
|
|
92
|
+
<span>
|
|
93
|
+
{activeIndex + 1} z {total}
|
|
94
|
+
</span>
|
|
95
|
+
</div>
|
|
96
|
+
<div className="h-1.5 overflow-hidden rounded-full bg-white/20">
|
|
97
|
+
<div
|
|
98
|
+
className="h-full rounded-full bg-[color:var(--ob-brand-blue)] transition-[width] duration-500 ease-out"
|
|
99
|
+
style={{ width: `${progress}%` }}
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
102
|
+
<p className="ob-display mt-5 text-[12px] leading-relaxed text-white/45">
|
|
103
|
+
Vytvořte AI, která skutečně rozumí vaší firmě.
|
|
104
|
+
</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</aside>
|
|
108
|
+
|
|
109
|
+
<main className="flex-1 px-5 py-8 sm:px-8 sm:py-12">
|
|
110
|
+
<div className="ob-animate-rise">{children}</div>
|
|
111
|
+
</main>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '../../lib/cn';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Ambient identity artwork woven into the accent rail — a large, faint "book → spark"
|
|
5
|
+
* motif (the same story as the logomark) that bleeds off the panel edges rather than
|
|
6
|
+
* sitting in a box. Purely decorative; white line art over the indigo gradient.
|
|
7
|
+
*/
|
|
8
|
+
export function RailArtwork({ className }: { readonly className?: string }) {
|
|
9
|
+
return (
|
|
10
|
+
<svg
|
|
11
|
+
viewBox="0 0 320 480"
|
|
12
|
+
preserveAspectRatio="xMidYMax slice"
|
|
13
|
+
className={cn('pointer-events-none absolute inset-0 h-full w-full', className)}
|
|
14
|
+
fill="none"
|
|
15
|
+
aria-hidden="true"
|
|
16
|
+
>
|
|
17
|
+
<g stroke="#7aebff">
|
|
18
|
+
{/* faint concentric rings around the spark */}
|
|
19
|
+
<g strokeOpacity="0.14" strokeWidth="1">
|
|
20
|
+
<circle cx="232" cy="150" r="34" />
|
|
21
|
+
<circle cx="232" cy="150" r="58" />
|
|
22
|
+
<circle cx="232" cy="150" r="86" />
|
|
23
|
+
</g>
|
|
24
|
+
|
|
25
|
+
{/* large open book, bleeding off the bottom */}
|
|
26
|
+
<g strokeOpacity="0.28" strokeWidth="1.6" strokeLinejoin="round" strokeLinecap="round">
|
|
27
|
+
<path d="M150 360 L40 388 L40 500 L150 478 Z" />
|
|
28
|
+
<path d="M150 360 L260 388 L260 500 L150 478 Z" />
|
|
29
|
+
<line x1="150" y1="360" x2="150" y2="478" />
|
|
30
|
+
<g strokeOpacity="0.18" strokeWidth="1.3">
|
|
31
|
+
<line x1="60" y1="402" x2="128" y2="416" />
|
|
32
|
+
<line x1="60" y1="420" x2="128" y2="434" />
|
|
33
|
+
<line x1="172" y1="416" x2="240" y2="402" />
|
|
34
|
+
<line x1="172" y1="434" x2="240" y2="420" />
|
|
35
|
+
</g>
|
|
36
|
+
</g>
|
|
37
|
+
|
|
38
|
+
{/* flow rising from the spine to the spark */}
|
|
39
|
+
<g strokeOpacity="0.24" strokeWidth="1.5" strokeLinecap="round">
|
|
40
|
+
<path d="M150 356 C 178 286, 196 232, 232 158" />
|
|
41
|
+
<path d="M150 352 C 200 300, 214 226, 230 160" />
|
|
42
|
+
</g>
|
|
43
|
+
|
|
44
|
+
{/* spark */}
|
|
45
|
+
<g strokeOpacity="0.6" strokeWidth="1.6" strokeLinecap="round">
|
|
46
|
+
<line x1="232" y1="132" x2="232" y2="144" />
|
|
47
|
+
<line x1="232" y1="156" x2="232" y2="168" />
|
|
48
|
+
<line x1="214" y1="150" x2="226" y2="150" />
|
|
49
|
+
<line x1="238" y1="150" x2="250" y2="150" />
|
|
50
|
+
</g>
|
|
51
|
+
</g>
|
|
52
|
+
<circle cx="232" cy="150" r="5.5" fill="#7aebff" fillOpacity="0.7" />
|
|
53
|
+
<g fill="#7aebff" fillOpacity="0.35">
|
|
54
|
+
<circle cx="196" cy="206" r="2.5" />
|
|
55
|
+
<circle cx="262" cy="104" r="2" />
|
|
56
|
+
<circle cx="150" cy="318" r="2" />
|
|
57
|
+
</g>
|
|
58
|
+
</svg>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import { ONBOARDING_ENTRY_PATH, ONBOARDING_STEPS } from '../../config/steps';
|
|
6
|
+
import { useManGoOnboardingNavigation } from '../../ManGoOnboardingNavigation';
|
|
7
|
+
import { generateBookDraft } from '../../services/draftService';
|
|
8
|
+
import { useOnboarding } from '../../state/OnboardingProvider';
|
|
9
|
+
import { BookLanguagePanel } from '../BookLanguagePanel';
|
|
10
|
+
import { MarkdownBookEditor } from '../MarkdownBookEditor';
|
|
11
|
+
import { StepFooter, StepHeader } from '../StepFrame';
|
|
12
|
+
import { Banner } from '../ui/Banner';
|
|
13
|
+
import { Button } from '../ui/Button';
|
|
14
|
+
import { Card } from '../ui/Card';
|
|
15
|
+
import { Spinner } from '../ui/Spinner';
|
|
16
|
+
|
|
17
|
+
type Phase = 'init' | 'generating' | 'ready' | 'error';
|
|
18
|
+
|
|
19
|
+
export function BookStep() {
|
|
20
|
+
const { navigateToPath } = useManGoOnboardingNavigation();
|
|
21
|
+
const { state, isHydrated, update } = useOnboarding();
|
|
22
|
+
const [phase, setPhase] = useState<Phase>('init');
|
|
23
|
+
const [error, setError] = useState<string | null>(null);
|
|
24
|
+
const startedRef = useRef(false);
|
|
25
|
+
|
|
26
|
+
const isBriefAvailable = state.agentName.trim().length > 0 && state.agentBrief.trim().length > 0;
|
|
27
|
+
|
|
28
|
+
const generate = useCallback(async () => {
|
|
29
|
+
setPhase('generating');
|
|
30
|
+
setError(null);
|
|
31
|
+
try {
|
|
32
|
+
const draft = await generateBookDraft({ agentName: state.agentName, agentBrief: state.agentBrief });
|
|
33
|
+
update({ bookSource: draft });
|
|
34
|
+
setPhase('ready');
|
|
35
|
+
} catch (caught) {
|
|
36
|
+
setError(caught instanceof Error ? caught.message : 'Generování draftu selhalo.');
|
|
37
|
+
setPhase('error');
|
|
38
|
+
}
|
|
39
|
+
}, [state.agentName, state.agentBrief, update]);
|
|
40
|
+
|
|
41
|
+
// Generate the draft once, after hydration completes — so we read the persisted
|
|
42
|
+
// name/brief rather than the initial empty state. Runs a single time (startedRef),
|
|
43
|
+
// reading the latest values from the closure captured when hydration flips true.
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!isHydrated || startedRef.current) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
startedRef.current = true;
|
|
49
|
+
|
|
50
|
+
if (state.bookSource.trim().length > 0) {
|
|
51
|
+
setPhase('ready');
|
|
52
|
+
} else if (isBriefAvailable) {
|
|
53
|
+
void generate();
|
|
54
|
+
} else {
|
|
55
|
+
setPhase('ready');
|
|
56
|
+
}
|
|
57
|
+
}, [generate, isBriefAvailable, isHydrated, state.bookSource]);
|
|
58
|
+
|
|
59
|
+
if (phase === 'init' || phase === 'generating') {
|
|
60
|
+
return (
|
|
61
|
+
<div className="mx-auto max-w-2xl">
|
|
62
|
+
<StepHeader eyebrow="Definice agenta" title="Připravujeme draft booku" />
|
|
63
|
+
<Card variant="elevated" className="flex flex-col items-center justify-center gap-5 px-8 py-20 text-center">
|
|
64
|
+
<span className="relative flex h-14 w-14 items-center justify-center">
|
|
65
|
+
<span className="absolute inset-0 animate-ping rounded-full bg-[color:var(--ob-accent-200)] opacity-60" />
|
|
66
|
+
<span className="relative flex h-14 w-14 items-center justify-center rounded-full bg-[color:var(--ob-accent-50)]">
|
|
67
|
+
<Spinner className="h-7 w-7" />
|
|
68
|
+
</span>
|
|
69
|
+
</span>
|
|
70
|
+
<div>
|
|
71
|
+
<p className="text-sm font-semibold text-zinc-800">Čtu vaše zadání a píšu draft book.md…</p>
|
|
72
|
+
<p className="mt-1 text-xs text-zinc-400">Chvíli to může trvat — generuje skutečný model.</p>
|
|
73
|
+
</div>
|
|
74
|
+
</Card>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const isContinueEnabled = state.bookSource.trim().length > 0;
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<div className="mx-auto max-w-4xl">
|
|
83
|
+
<StepHeader
|
|
84
|
+
eyebrow="Definice agenta"
|
|
85
|
+
title="Draft booku je hotový"
|
|
86
|
+
subtitle="Je to jen výchozí návrh — cokoli přepište, smažte nebo doplňte, klidně přímo na schůzce s klientem."
|
|
87
|
+
/>
|
|
88
|
+
|
|
89
|
+
{phase === 'error' && (
|
|
90
|
+
<Banner tone="warning" title="Draft se nepodařilo vygenerovat." className="mb-5">
|
|
91
|
+
<p>{error}</p>
|
|
92
|
+
<p className="mt-1">Book můžete napsat i ručně níže, nebo to zkuste znovu.</p>
|
|
93
|
+
</Banner>
|
|
94
|
+
)}
|
|
95
|
+
|
|
96
|
+
{!isBriefAvailable && state.bookSource.trim().length === 0 && phase !== 'error' && (
|
|
97
|
+
<Banner tone="info" className="mb-5">
|
|
98
|
+
Nejprve vyplňte zadání, ať můžeme draft vygenerovat — nebo book napište ručně níže.{' '}
|
|
99
|
+
<button
|
|
100
|
+
type="button"
|
|
101
|
+
className="font-semibold text-[color:var(--ob-accent-700)] underline underline-offset-2 hover:text-[color:var(--ob-accent-800)]"
|
|
102
|
+
onClick={() => navigateToPath(ONBOARDING_ENTRY_PATH)}
|
|
103
|
+
>
|
|
104
|
+
Zpět na zadání
|
|
105
|
+
</button>
|
|
106
|
+
</Banner>
|
|
107
|
+
)}
|
|
108
|
+
|
|
109
|
+
<MarkdownBookEditor
|
|
110
|
+
value={state.bookSource}
|
|
111
|
+
onChange={(value) => update({ bookSource: value })}
|
|
112
|
+
onRegenerate={isBriefAvailable ? () => void generate() : undefined}
|
|
113
|
+
/>
|
|
114
|
+
|
|
115
|
+
{state.bookSource.trim().length > 0 && <BookLanguagePanel source={state.bookSource} />}
|
|
116
|
+
|
|
117
|
+
<StepFooter
|
|
118
|
+
left={
|
|
119
|
+
<Button variant="ghost" onClick={() => navigateToPath(ONBOARDING_ENTRY_PATH)}>
|
|
120
|
+
← Zadání
|
|
121
|
+
</Button>
|
|
122
|
+
}
|
|
123
|
+
right={
|
|
124
|
+
<Button
|
|
125
|
+
disabled={!isContinueEnabled}
|
|
126
|
+
trailingIcon={<span aria-hidden>→</span>}
|
|
127
|
+
onClick={() => navigateToPath(ONBOARDING_STEPS[1].path)}
|
|
128
|
+
>
|
|
129
|
+
Pokračovat: Znalosti
|
|
130
|
+
</Button>
|
|
131
|
+
}
|
|
132
|
+
/>
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
import { useEffect, useRef } from 'react';
|
|
5
|
+
import { useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import type { AgentVisibility } from '../../../../../utils/agentVisibility';
|
|
8
|
+
import { ONBOARDING_ENTRY_PATH, ONBOARDING_STEPS } from '../../config/steps';
|
|
9
|
+
import { useManGoOnboardingNavigation } from '../../ManGoOnboardingNavigation';
|
|
10
|
+
import { createManGoAgentSource } from '../../services/createManGoAgentSource';
|
|
11
|
+
import { useOnboarding } from '../../state/OnboardingProvider';
|
|
12
|
+
import { SectionLabel, StepCard } from '../StepFrame';
|
|
13
|
+
import { Banner } from '../ui/Banner';
|
|
14
|
+
import { Badge } from '../ui/Badge';
|
|
15
|
+
import { Button } from '../ui/Button';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Created-agent payload returned by the host Agents Server dialog controller.
|
|
19
|
+
*/
|
|
20
|
+
export type ManGoCreatedAgentPayload = {
|
|
21
|
+
/**
|
|
22
|
+
* Permanent id of the created agent.
|
|
23
|
+
*/
|
|
24
|
+
readonly permanentId: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Route opened when the user leaves the completion screen.
|
|
28
|
+
*/
|
|
29
|
+
readonly targetPath: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Props accepted by the completion step.
|
|
34
|
+
*/
|
|
35
|
+
type DoneStepProps = {
|
|
36
|
+
/**
|
|
37
|
+
* Default visibility resolved from server metadata.
|
|
38
|
+
*/
|
|
39
|
+
readonly defaultVisibility: AgentVisibility;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates the real Agents Server agent.
|
|
43
|
+
*/
|
|
44
|
+
readonly onCreate: (request: {
|
|
45
|
+
readonly agentSource: ReturnType<typeof createManGoAgentSource>;
|
|
46
|
+
readonly visibility: AgentVisibility;
|
|
47
|
+
readonly knowledgeCount: number;
|
|
48
|
+
}) => Promise<ManGoCreatedAgentPayload>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Opens the created agent route selected by the host dialog controller.
|
|
52
|
+
*/
|
|
53
|
+
readonly onOpenCreatedAgent: (targetPath: string) => void;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function SummaryRow({ label, value }: { readonly label: string; readonly value: ReactNode }) {
|
|
57
|
+
return (
|
|
58
|
+
<div className="flex items-center justify-between gap-4 border-b border-zinc-100 py-2.5 last:border-b-0">
|
|
59
|
+
<span className="text-sm text-zinc-500">{label}</span>
|
|
60
|
+
<span className="text-sm font-medium text-zinc-900">{value}</span>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function DoneStep(props: DoneStepProps) {
|
|
66
|
+
const { defaultVisibility, onCreate, onOpenCreatedAgent } = props;
|
|
67
|
+
const { navigateToPath } = useManGoOnboardingNavigation();
|
|
68
|
+
const { state, isHydrated, update, reset } = useOnboarding();
|
|
69
|
+
const savedRef = useRef(false);
|
|
70
|
+
const [isCreatingAgent, setIsCreatingAgent] = useState(false);
|
|
71
|
+
const [creationError, setCreationError] = useState<string | null>(null);
|
|
72
|
+
const [creationAttempt, setCreationAttempt] = useState(0);
|
|
73
|
+
|
|
74
|
+
const knowledgeCount = state.knowledge.length;
|
|
75
|
+
const isTested = state.testMessages.some((message) => message.role === 'user');
|
|
76
|
+
const isBookAvailable = state.bookSource.trim().length > 0;
|
|
77
|
+
const isCreated = Boolean(state.savedAgentId && state.savedAgentTargetPath);
|
|
78
|
+
|
|
79
|
+
// Create the real agent once. Guarded by both a ref (single run) and the session's
|
|
80
|
+
// saved permanent id (don't re-create on revisit).
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (!isHydrated || savedRef.current) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
savedRef.current = true;
|
|
86
|
+
|
|
87
|
+
if (state.agentName.trim().length === 0 && state.bookSource.trim().length === 0) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (state.savedAgentId && state.savedAgentTargetPath) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const agentSource = createManGoAgentSource(state);
|
|
96
|
+
const readyKnowledgeCount = state.knowledge.filter((item) => item.status === 'ready').length;
|
|
97
|
+
|
|
98
|
+
setIsCreatingAgent(true);
|
|
99
|
+
setCreationError(null);
|
|
100
|
+
void onCreate({
|
|
101
|
+
agentSource,
|
|
102
|
+
visibility: defaultVisibility,
|
|
103
|
+
knowledgeCount: readyKnowledgeCount,
|
|
104
|
+
})
|
|
105
|
+
.then((agent) => {
|
|
106
|
+
update({
|
|
107
|
+
savedAgentId: agent.permanentId,
|
|
108
|
+
savedAgentTargetPath: agent.targetPath,
|
|
109
|
+
});
|
|
110
|
+
})
|
|
111
|
+
.catch((error) => {
|
|
112
|
+
savedRef.current = false;
|
|
113
|
+
setCreationError(error instanceof Error ? error.message : 'Vytvoření agenta selhalo.');
|
|
114
|
+
})
|
|
115
|
+
.finally(() => {
|
|
116
|
+
setIsCreatingAgent(false);
|
|
117
|
+
});
|
|
118
|
+
}, [creationAttempt, defaultVisibility, isHydrated, onCreate, state, update]);
|
|
119
|
+
|
|
120
|
+
function startOver() {
|
|
121
|
+
reset();
|
|
122
|
+
navigateToPath(ONBOARDING_ENTRY_PATH);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<div className="mx-auto max-w-xl text-center">
|
|
127
|
+
<div className="relative mx-auto mb-6 flex h-20 w-20 items-center justify-center">
|
|
128
|
+
<span className="absolute inset-0 rounded-full bg-emerald-100/70 blur-md" aria-hidden />
|
|
129
|
+
<span className="relative flex h-20 w-20 items-center justify-center rounded-full bg-gradient-to-br from-emerald-50 to-emerald-100 text-4xl shadow-[var(--ob-shadow-md)] ring-1 ring-emerald-200/60">
|
|
130
|
+
🎉
|
|
131
|
+
</span>
|
|
132
|
+
</div>
|
|
133
|
+
<h1 className="ob-display text-[28px] font-bold tracking-tight text-zinc-900">Agent v1 je uložen!</h1>
|
|
134
|
+
<p className="mt-2 text-sm text-zinc-500">
|
|
135
|
+
{state.agentName.trim()
|
|
136
|
+
? `${state.agentName.trim()} je připraven k dalšímu rozvoji.`
|
|
137
|
+
: 'Agent je připraven k dalšímu rozvoji.'}
|
|
138
|
+
</p>
|
|
139
|
+
|
|
140
|
+
{isCreatingAgent && (
|
|
141
|
+
<Banner tone="info" className="mt-6 text-left" title="Ukládám agenta">
|
|
142
|
+
První verze se ukládá do Agents Serveru.
|
|
143
|
+
</Banner>
|
|
144
|
+
)}
|
|
145
|
+
|
|
146
|
+
{creationError && (
|
|
147
|
+
<Banner tone="error" className="mt-6 text-left" title="Agenta se nepodařilo uložit">
|
|
148
|
+
{creationError}
|
|
149
|
+
</Banner>
|
|
150
|
+
)}
|
|
151
|
+
|
|
152
|
+
<StepCard className="mt-8 text-left">
|
|
153
|
+
<SectionLabel className="mb-3">Shrnutí první verze</SectionLabel>
|
|
154
|
+
<SummaryRow label="Název agenta" value={state.agentName.trim() || '—'} />
|
|
155
|
+
<SummaryRow
|
|
156
|
+
label="Book"
|
|
157
|
+
value={
|
|
158
|
+
<Badge tone={isBookAvailable ? 'success' : 'neutral'} dot={isBookAvailable}>
|
|
159
|
+
{isBookAvailable ? 'Definován' : 'Prázdný'}
|
|
160
|
+
</Badge>
|
|
161
|
+
}
|
|
162
|
+
/>
|
|
163
|
+
<SummaryRow
|
|
164
|
+
label="Znalostní báze"
|
|
165
|
+
value={
|
|
166
|
+
<Badge tone={knowledgeCount > 0 ? 'accent' : 'neutral'}>
|
|
167
|
+
{knowledgeCount === 0 ? 'Žádné zdroje' : `${knowledgeCount} zdroje/ů`}
|
|
168
|
+
</Badge>
|
|
169
|
+
}
|
|
170
|
+
/>
|
|
171
|
+
<SummaryRow
|
|
172
|
+
label="Testování"
|
|
173
|
+
value={
|
|
174
|
+
<Badge tone={isTested ? 'success' : 'neutral'} dot={isTested}>
|
|
175
|
+
{isTested ? 'Provedeno' : 'Neproběhlo'}
|
|
176
|
+
</Badge>
|
|
177
|
+
}
|
|
178
|
+
/>
|
|
179
|
+
<SummaryRow
|
|
180
|
+
label="Uložení"
|
|
181
|
+
value={
|
|
182
|
+
<Badge tone={isCreated ? 'success' : creationError ? 'error' : 'neutral'} dot={isCreated}>
|
|
183
|
+
{isCreated ? 'Uloženo' : creationError ? 'Chyba' : 'Probíhá'}
|
|
184
|
+
</Badge>
|
|
185
|
+
}
|
|
186
|
+
/>
|
|
187
|
+
</StepCard>
|
|
188
|
+
|
|
189
|
+
<div className="mt-7 flex flex-col gap-3">
|
|
190
|
+
<Button
|
|
191
|
+
trailingIcon={<span aria-hidden>→</span>}
|
|
192
|
+
disabled={(!state.savedAgentTargetPath && !creationError) || isCreatingAgent}
|
|
193
|
+
onClick={() => {
|
|
194
|
+
if (creationError) {
|
|
195
|
+
setCreationAttempt((previousAttempt) => previousAttempt + 1);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (state.savedAgentTargetPath) {
|
|
200
|
+
onOpenCreatedAgent(state.savedAgentTargetPath);
|
|
201
|
+
}
|
|
202
|
+
}}
|
|
203
|
+
>
|
|
204
|
+
{creationError ? 'Zkusit uložit znovu' : 'Přejít na chat agenta'}
|
|
205
|
+
</Button>
|
|
206
|
+
<Button variant="outline" disabled={isCreatingAgent} onClick={() => navigateToPath(ONBOARDING_STEPS[0].path)}>
|
|
207
|
+
Upravit agenta
|
|
208
|
+
</Button>
|
|
209
|
+
<Button variant="ghost" disabled={isCreatingAgent} onClick={startOver}>
|
|
210
|
+
Začít nový onboarding
|
|
211
|
+
</Button>
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import { ONBOARDING_STEPS } from '../../config/steps';
|
|
6
|
+
import { createId } from '../../lib/id';
|
|
7
|
+
import { uploadKnowledgeFile } from '../../services/uploadService';
|
|
8
|
+
import { useManGoOnboardingNavigation } from '../../ManGoOnboardingNavigation';
|
|
9
|
+
import { useOnboarding } from '../../state/OnboardingProvider';
|
|
10
|
+
import type { KnowledgeFileItem } from '../../types';
|
|
11
|
+
import { cn } from '../../lib/cn';
|
|
12
|
+
import { DropZone } from '../DropZone';
|
|
13
|
+
import { KnowledgeList } from '../KnowledgeList';
|
|
14
|
+
import { StepCard, StepFooter, StepHeader } from '../StepFrame';
|
|
15
|
+
import { Button } from '../ui/Button';
|
|
16
|
+
import { CONTROL, CONTROL_ERROR } from '../ui/Field';
|
|
17
|
+
|
|
18
|
+
const MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
|
|
19
|
+
|
|
20
|
+
function normalizeUrl(raw: string): string | null {
|
|
21
|
+
const trimmed = raw.trim();
|
|
22
|
+
if (!trimmed) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const withProtocol = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
26
|
+
try {
|
|
27
|
+
return new URL(withProtocol).href;
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function KnowledgeStep() {
|
|
34
|
+
const { navigateToPath } = useManGoOnboardingNavigation();
|
|
35
|
+
const { state, update } = useOnboarding();
|
|
36
|
+
const [urlInput, setUrlInput] = useState('');
|
|
37
|
+
const [urlError, setUrlError] = useState<string | null>(null);
|
|
38
|
+
|
|
39
|
+
function uploadOne(file: File) {
|
|
40
|
+
const id = createId();
|
|
41
|
+
const item: KnowledgeFileItem = {
|
|
42
|
+
kind: 'file',
|
|
43
|
+
id,
|
|
44
|
+
name: file.name,
|
|
45
|
+
size: file.size,
|
|
46
|
+
publicUrl: '',
|
|
47
|
+
objectKey: '',
|
|
48
|
+
status: 'uploading',
|
|
49
|
+
};
|
|
50
|
+
update((prev) => ({ knowledge: [...prev.knowledge, item] }));
|
|
51
|
+
|
|
52
|
+
uploadKnowledgeFile(file)
|
|
53
|
+
.then(({ publicUrl, objectKey }) => {
|
|
54
|
+
update((prev) => ({
|
|
55
|
+
knowledge: prev.knowledge.map((entry) =>
|
|
56
|
+
entry.id === id ? { ...entry, publicUrl, objectKey, status: 'ready' } : entry,
|
|
57
|
+
),
|
|
58
|
+
}));
|
|
59
|
+
})
|
|
60
|
+
.catch(() => {
|
|
61
|
+
update((prev) => ({
|
|
62
|
+
knowledge: prev.knowledge.map((entry) =>
|
|
63
|
+
entry.id === id ? { ...entry, status: 'error' } : entry,
|
|
64
|
+
),
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function handleFiles(files: readonly File[]) {
|
|
70
|
+
files.filter((file) => file.size <= MAX_FILE_SIZE_BYTES).forEach(uploadOne);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function handleAddUrl() {
|
|
74
|
+
const normalized = normalizeUrl(urlInput);
|
|
75
|
+
if (!normalized) {
|
|
76
|
+
setUrlError('Zadejte platnou adresu, např. https://firma.cz/napoveda');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
setUrlError(null);
|
|
80
|
+
setUrlInput('');
|
|
81
|
+
update((prev) => ({
|
|
82
|
+
knowledge: [...prev.knowledge, { kind: 'url', id: createId(), url: normalized, status: 'ready' }],
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function handleRemove(id: string) {
|
|
87
|
+
update((prev) => ({ knowledge: prev.knowledge.filter((entry) => entry.id !== id) }));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div className="mx-auto max-w-2xl">
|
|
92
|
+
<StepHeader
|
|
93
|
+
eyebrow="Znalostní báze"
|
|
94
|
+
title="Přidejte znalosti agenta"
|
|
95
|
+
subtitle="Agent čerpá odpovědi ze souborů a odkazů, které mu dáte. Čím relevantnější materiály, tím přesnější výstupy."
|
|
96
|
+
/>
|
|
97
|
+
|
|
98
|
+
<StepCard className="space-y-6">
|
|
99
|
+
<DropZone onFiles={handleFiles} hint="PDF, DOCX, TXT, XLSX · max. 25 MB na soubor" />
|
|
100
|
+
|
|
101
|
+
<KnowledgeList items={state.knowledge} onRemove={handleRemove} />
|
|
102
|
+
|
|
103
|
+
<div className="border-t border-zinc-100 pt-6">
|
|
104
|
+
<label htmlFor="knowledge-url" className="mb-1.5 block text-[13px] font-semibold text-zinc-700">
|
|
105
|
+
Nebo přidejte odkaz na web / dokumentaci
|
|
106
|
+
</label>
|
|
107
|
+
<div className="flex gap-2.5">
|
|
108
|
+
<input
|
|
109
|
+
id="knowledge-url"
|
|
110
|
+
type="text"
|
|
111
|
+
value={urlInput}
|
|
112
|
+
placeholder="https://firma.cz/napoveda"
|
|
113
|
+
aria-invalid={urlError ? true : undefined}
|
|
114
|
+
onChange={(event) => setUrlInput(event.target.value)}
|
|
115
|
+
onKeyDown={(event) => event.key === 'Enter' && handleAddUrl()}
|
|
116
|
+
className={cn(CONTROL, urlError && CONTROL_ERROR)}
|
|
117
|
+
/>
|
|
118
|
+
<Button
|
|
119
|
+
variant="outline"
|
|
120
|
+
onClick={handleAddUrl}
|
|
121
|
+
className="whitespace-nowrap"
|
|
122
|
+
leadingIcon={<span aria-hidden>+</span>}
|
|
123
|
+
>
|
|
124
|
+
Přidat
|
|
125
|
+
</Button>
|
|
126
|
+
</div>
|
|
127
|
+
{urlError ? (
|
|
128
|
+
<p className="mt-1 text-xs text-red-600">{urlError}</p>
|
|
129
|
+
) : (
|
|
130
|
+
<p className="mt-1 text-xs text-zinc-400">Agent si stránku přečte a zahrne do znalostní báze.</p>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
</StepCard>
|
|
134
|
+
|
|
135
|
+
<StepFooter
|
|
136
|
+
left={
|
|
137
|
+
<Button variant="ghost" onClick={() => navigateToPath(ONBOARDING_STEPS[0].path)}>
|
|
138
|
+
← Book
|
|
139
|
+
</Button>
|
|
140
|
+
}
|
|
141
|
+
right={
|
|
142
|
+
<Button
|
|
143
|
+
trailingIcon={<span aria-hidden>→</span>}
|
|
144
|
+
onClick={() => navigateToPath(ONBOARDING_STEPS[2].path)}
|
|
145
|
+
>
|
|
146
|
+
Pokračovat: Test
|
|
147
|
+
</Button>
|
|
148
|
+
}
|
|
149
|
+
/>
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
}
|