Pathfinderby Commenda
Guides

AI content integration

Phase 1 contracts, dependencies, migration mappings, and intentional differences from existing Commenda AI elements.

Package contract

All components live in @commenda/pathfinder. Import styles.css once and optionally code-font.css for Geist Mono. Individual entry points are markdown, code-block, and inline-reference. No app-side CSS compilation, AI SDK provider, router, or upload client is required.

Streamdown 2.5.0 supplies streaming Markdown parsing. Lowlight 3.3.0 supplies Highlight.js token trees rendered as React spans; new AI runtime components do not use Shiki. Fumadocs examples and MDX fences also use Lowlight, rendered on the server; its default Shiki highlighting is disabled. Mermaid and math rendering are not enabled. Streamdown itself lists Mermaid transitively; Pathfinder does not enable its renderer.

Migration readiness

Migration is out of scope for this build. Keep legacy components in place until their consumers are explicitly migrated.

Existing API / call sitePathfinder equivalentDifference / future work
MessageResponse in CommendaAiMessageItemMarkdown children and isAnimatingReuse the same segment.part.text; no message conversion
Streamdown componentsMarkdown.componentsTyped semantic overrides; no leaking upstream AST types into the public contract
Compound CodeBlock, header, filename and copy childrenCodeBlock code/language/filename/copyConfigHeader layout is internal; old children must be mapped explicitly
showLineNumbersSame compatibility propDefaults on to match Figma; lineNumberConfig.visible takes precedence
MarkdownLink with host routing and record lookupreferenceConfig.resolve, InlineReference.onClick, or a typed link overrideHost provider is not imported; app retains business routing and link confirmation
Question fence rendererPlain code fallback in Phase 1Interactive requests belong to Phase 5; do not migrate such consumers without mapping them
Math/Mermaid plugins and word animationNot enabledSeparate opt-in work, not silent migration parity
Table copy/export/expandBuilt-in Markdown table controlsStatic semantic table; interactive sorting/editing remain Table features

Preserve stable message/part IDs in the parent, part ordering, and application-owned state. Do not flatten tool results or attachments into strings. New reference configuration must update even when the text is unchanged.

Upstream provenance

Behavioral reference: Vercel AI Elements MessageResponse and Code Block, revision 6a9d5b1822ffb10bba4bd97175f01edd7d8651cd, Apache-2.0. Pathfinder replaces the visual controls, uses compact Figma typography, removes default plugins and the text-only memo comparator, and uses Lowlight instead of Shiki. See the package's THIRD_PARTY_NOTICES.md.

Rendering rules

Treat custom renderers as trusted application code. Keep untrusted raw HTML disabled, render code as text, and validate navigation schemes. References receive ready-to-render data or a loading state; they do not fetch records. Clipboard failures stay recoverable. Do not announce each streamed token.

Markdown is intentionally available through @commenda/pathfinder/markdown only (its types are also exported from the root). Streamdown has module side effects; keeping this runtime off the root barrel prevents unrelated icon and button imports from loading the Markdown parser.

Attachments and context

Use Attachment, Attachment group, and Composer context as independent leaves. Each accepts caller-owned data and callbacks; none requires an AI provider or transport.

Existing attachment key/fileName/mimeType values map to id/filename/mediaType. Keep opaque fileRef lookup, folder aggregation, cancellation, and viewer selection in the app. Context onDismiss maps to removal by stable ID. These are documented mappings and type fixtures, not consumer migrations.

Composer and conversation starters

Use /composer, /suggested-prompt, and /suggested-prompt-group for Phase 3. These exports have no AI SDK runtime dependency. The Composer's requestConfig.status accepts AI SDK's ready, submitted, streaming, and error values directly.

Existing surfacePathfinder mapping
ChatComposer initialInput / provider text stateInitialize React state and pass value / onValueChange
onSubmit(text, attachments)Adapt onSubmit({ text, attachments, command }) in the host
status, onStoprequestConfig={{ status, onStop }}
Existing attachment objectsMap to stable AttachmentItem IDs; keep backend metadata in the host
toolsSlottoolbar.leading
contextSlotcontextConfig or existing ComposerContext composition
Existing upload service, file ingestion, folder uploadRetain in the host; wire attachmentConfig.items, onAdd, onRemove, onRetry
Suggestion click handlerSuggestedPrompt onSelect or SuggestedPromptGroup onSelect

The selected skill is separate typed metadata, so plain-text drafts and existing backend payloads do not require rich-text migration. Convert that metadata only where the application builds its request. Do not serialize internal component state or import private implementation files.

Vercel AI Elements' Prompt Input and Suggestion informed the textarea, toolbar, keyboard, and request-state responsibilities. Pathfinder implements those behaviors using its existing primitives and its controlled-data contract. It does not vendor a second Radix/shadcn component stack or introduce Shiki. Actual application migration remains out of scope.

Activity and execution

Existing AI Elements conceptPathfinderHost responsibility
Reasoning / ReasoningTrigger / ReasoningContentReasoning with optional disclosureConfig and childrenSupply approved summary text and elapsed duration
Tool / ToolInput / ToolOutputToolCall with input and output source stringsMap tool status and redact secrets before rendering
ChainOfThought step compositionChainOfThought with discriminated stepsKeep stable IDs and preserve source ordering
Thinking / ShimmerThinkingIndicatorHide label after first content; remove at completion

AI SDK mapping: input-streaming → pending, input-available → running, output-available → done, output-error → failed. Approval states require application UI; do not present approval as completed execution. Keep this adapter in the host so SDK upgrades do not change the design system contract. No consumer migrations are included.

Reasoning's isStreaming describes the reasoning part, not the entire chat request. Set it false when answer content starts so automatic collapse happens a second later. A manual toggle wins until remount; use a stable key for one response, a new key for a new response. A controlled disclosureConfig.open delegates all automation to the host. Compose Markdown explicitly for formatted summaries; it remains a subpath-only runtime dependency.

Architecture references: Vercel Reasoning, Tool, and Chain of Thought. Pathfinder adapts these concepts to Figma and uses Base UI Collapsible, the same panel measurement foundation used by Accordion. It does not import legacy UI wrappers or their Shiki/Streamdown code plugins.

Requests, approvals, and optional actions

QuestionCard, ApprovalCard, PlanReviewCard and UploadRequestCard share a request result contract. Keep request IDs and tool-call IDs stable and key each card by request ID/version. A handler returns accepted plus the server receipt, or failed plus a user-facing message. Retain drafts on failure and persist accepted ResponseRecap data in the originating message. Approval/plan receipts include the actor and timestamp. Explicit skip, deny, approve and submit are different domain events; temporary dismissal never resolves a request.

Route a typed Composer response to the active question as a written answer. For an active approval, the Figma contract treats a typed response as denial. Implement that deliberate mapping in the host orchestrator, together with authorization and idempotency. Do not attach approval to global keyboard shortcuts or merely closing a card. Plan review opens app-owned plan content. Upload request passes files to app-owned validation/upload and sends only ready attachment IDs.

ActionCard is optional: it does not pause or resume a turn. Return completed only after the action succeeds. Persist completion/dismissal independently; no toast or follow-up message is generated. Use state to restore completed or dismissed actions from history.

For migration, map existing Ask single/multiple data to QuestionCard; approve to ApprovalCard; plan to PlanReviewCard; upload to UploadRequestCard. Map accepted records to ResponseRecap and optional Action records to ActionCard. Keep existing orchestration callbacks behind these typed boundaries. No application migration, AI SDK state conversion, plan editor or upload transport is included in this phase.

Existing question flow compatibility

Reviewed QuestionDockedCard in CommendaAiConversation, the historical QuestionBlockRenderer, QuestionSelectCard, QuestionPlanCard, QuestionAnsweredRecap, and the question-block.ts backend contract. These remain unchanged.

Existing contractPathfinder mappingPreserved behavior / adapter boundary
toolCallId and indexed questions[]React key ${toolCallId}:${questionIndex} plus paginationConfigHost keeps the tool-call ID, batches answers and persists drafts; no automatic 250ms page advance in the primitive
single_select / multi_select, positional options with titlemode, options: { id, label, description }[]Use stable position-derived IDs for this immutable request, not labels; duplicate labels remain distinct
selectedByIndex, writeInByIndexdefaultAnswer, onAnswerChangeStore per-question drafts in the adapter before changing pages
ANSWER_MAX_LENGTH = 300writeInConfig={{ maxLength: 300 }}Retain the current backend limit; validate combined multi-choice text server-side
onAnswer({toolCallId, answers, text})onSubmit / onSkipAdapter maps selected IDs back to questionIndex/chosen, carries the original tool ID and answer marker; accepted result is explicit
Plan body and correction textareaplanConfig.onOpen, onSuggestChangesIntentional new Figma design: plan/editor lives in the host, no Skip or embedded correction editor
Completed QuestionRecordResponseRecap / state: resolvedRestore accepted answers from persisted records; do not infer receipt state from message text
onCloseonDismissTemporary hide only; do not submit an answer or cancel a tool

The existing data-question-answer marker and backend request schema remain application-owned. The visual component never rewrites history or infers a tool-call ID. ApprovalCard, UploadRequestCard and optional ActionCard are new surfaces with no required legacy transport. This phase implements the Figma request/action designs directly with Pathfinder controls; it vendors no additional Vercel AI Elements source or dependencies.

Messages and conversation composition

Use @commenda/pathfinder/message and @commenda/pathfinder/conversation. Keep existing SDK objects and pass typed render callbacks; no serialization or role conversion is required. Message's from="person" is presentation only. Markdown remains a separate import, and unknown tool/custom parts must be handled by the application renderer.

Existing integrationPathfinder boundaryHost responsibility
CommendaAiMessageItem and compound Message contentMessage<Part> with parts, getPartKey, renderPartPreserve original IDs, order, custom metadata and tool states
MessageActions / feedback modalactionConfigControlled feedback, app modal, persistence and retry eligibility
Compound Conversation / scroll buttonConversation<Item>Stable message keys, bounded height and app-owned history loading
Docked questionsfooter containing QuestionCard and ComposerPut accepted recap in the originating message, persist it, remove the dock

MESSAGE-04: errors retain partial replies. CONVERSATION-02: follow only near bottom and preserve reading position across history prepend. CONVERSATION-03: supply turn-level announcements, never per-token live text. These are optional boundaries for a future migration; the existing application is unchanged.

Outputs and run history

Use Output List for artifact rows and Run List for execution history. The responsive panel and complete simulated workflow live in the Output List examples. Import each component from its own package subpath; no global AI provider is required.

Existing integrationPathfinder boundaryPreserved behavior / intentional difference
AgentRunsRail active conversation and run queriesRunList.items, selectedId, onOpen, paginationConfigHost maps IDs, formatted dates, paging, and router navigation
useMarkRunRead and schedule actionsonMarkRead, actionConfigHost owns mutations; no optimistic unread change in the primitive
Canceled treated as failurestatus="canceled"Deliberate Figma change: canceled and skipped use neutral indicators
AttachmentPreviewPanel / document viewerOutputList.onOpenHost retains signed URLs, preview tabs, downloads, and viewer lifecycle
Per-person rail preferencedisclosureConfig and host panel stateHost persists disclosure and responsive visibility; no storage access in the package

OUTPUT-03 keeps independent row/menu actions, and RUN-02 keeps canceled runs neutral. Supply newest-first records with stable IDs. The compact lists do not sort backend data or virtualize unlimited history. These boundaries make incremental adoption possible; actual migration and full artifact editing are out of scope.

On this page