@codexview/react 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +56 -0
  2. package/dist/components/CodexTranscript.d.ts +41 -0
  3. package/dist/components/ErrorBlock.d.ts +7 -0
  4. package/dist/components/ExecBlock.d.ts +9 -0
  5. package/dist/components/ItemErrorBoundary.d.ts +16 -0
  6. package/dist/components/Markdown.d.ts +20 -0
  7. package/dist/components/MessageBubble.d.ts +10 -0
  8. package/dist/components/PatchBlock.d.ts +9 -0
  9. package/dist/components/RawEventBlock.d.ts +7 -0
  10. package/dist/components/ReasoningBlock.d.ts +11 -0
  11. package/dist/components/SearchBlock.d.ts +10 -0
  12. package/dist/components/StatusBar.d.ts +10 -0
  13. package/dist/components/TodoListBlock.d.ts +9 -0
  14. package/dist/components/ToolCallBlock.d.ts +9 -0
  15. package/dist/components/TurnContainer.d.ts +7 -0
  16. package/dist/components/_shared.d.ts +2 -0
  17. package/dist/components/icons.d.ts +16 -0
  18. package/dist/hooks/useCodexTranscript.d.ts +10 -0
  19. package/dist/hooks/useSmoothStream.d.ts +7 -0
  20. package/dist/index.d.ts +38 -0
  21. package/dist/index.js +13520 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/reducer/status.d.ts +2 -0
  24. package/dist/reducer/transcript.d.ts +4 -0
  25. package/dist/styles.css +493 -0
  26. package/dist/types/events.d.ts +164 -0
  27. package/dist/types/model.d.ts +75 -0
  28. package/docs/api.md +156 -0
  29. package/docs/changelog.md +40 -0
  30. package/docs/events.md +65 -0
  31. package/docs/integration-agentweb.md +112 -0
  32. package/docs/styling.md +81 -0
  33. package/docs/superpowers/plans/2026-05-15-codexview-implementation.md +3903 -0
  34. package/docs/superpowers/specs/2026-05-15-codexview-design.md +661 -0
  35. package/package.json +84 -0
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # codexview
2
+
3
+ React components for rendering OpenAI Codex CLI chat streams. Designed for agentweb but framework-agnostic for any host that produces compatible `ChatStreamEvent` sequences.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add codexview lucide-react react react-dom
9
+ ```
10
+
11
+ Import the stylesheet once in your app entrypoint:
12
+
13
+ ```ts
14
+ import 'codexview/styles.css';
15
+ ```
16
+
17
+ ## 60-second quick start
18
+
19
+ ```tsx
20
+ import { CodexTranscript, type ChatStreamEvent } from 'codexview';
21
+ import 'codexview/styles.css';
22
+
23
+ const events: ChatStreamEvent[] = [
24
+ { type: 'thread_started', threadId: 'T', at: Date.now() },
25
+ { type: 'turn_started', turnId: 'A', at: Date.now() },
26
+ { type: 'user_message', turnId: 'A', itemId: 'u1', text: 'Hello!', at: Date.now() },
27
+ { type: 'agent_message', turnId: 'A', itemId: 'a1', text: 'Hi.', partial: false, at: Date.now() },
28
+ { type: 'turn_completed', turnId: 'A', at: Date.now() },
29
+ ];
30
+
31
+ export function App() {
32
+ return <CodexTranscript events={events} />;
33
+ }
34
+ ```
35
+
36
+ `events` is a plain array. Append new events as they arrive (typically via SSE) and pass the same array reference back; CodexView reduces incrementally.
37
+
38
+ ## Status
39
+
40
+ Session-level status (`idle | working | completed | stopped | failed`) is inferred automatically. Override via the `status` prop (e.g. when SSE drops, set `status="stopped"`).
41
+
42
+ ## Customizing
43
+
44
+ - Swap any block via `components` prop: `<CodexTranscript components={{ ToolCallBlock: MyToolUI }} />`
45
+ - Theme via CSS variables — see [docs/styling.md](docs/styling.md) for the full list.
46
+
47
+ ## More docs
48
+
49
+ - [docs/api.md](docs/api.md) — every public API
50
+ - [docs/events.md](docs/events.md) — `ChatStreamEvent` contract
51
+ - [docs/styling.md](docs/styling.md) — CSS variables
52
+ - [docs/integration-agentweb.md](docs/integration-agentweb.md) — drop-in for agentweb
53
+
54
+ ## License
55
+
56
+ MIT.
@@ -0,0 +1,41 @@
1
+ import { ComponentType, ReactNode } from 'react';
2
+ import { ChatStreamEvent } from '../types/events.js';
3
+ import { TranscriptStatus } from '../types/model.js';
4
+ import { MessageBubbleProps } from './MessageBubble.js';
5
+ import { ReasoningBlockProps } from './ReasoningBlock.js';
6
+ import { ToolCallBlockProps } from './ToolCallBlock.js';
7
+ import { ExecBlockProps } from './ExecBlock.js';
8
+ import { SearchBlockProps } from './SearchBlock.js';
9
+ import { PatchBlockProps } from './PatchBlock.js';
10
+ import { TodoListBlockProps } from './TodoListBlock.js';
11
+ import { ErrorBlockProps } from './ErrorBlock.js';
12
+ import { RawEventBlockProps } from './RawEventBlock.js';
13
+ import { StatusBarProps } from './StatusBar.js';
14
+ export interface CodexTranscriptComponents {
15
+ StatusBar: ComponentType<StatusBarProps>;
16
+ MessageBubble: ComponentType<MessageBubbleProps>;
17
+ ReasoningBlock: ComponentType<ReasoningBlockProps>;
18
+ ToolCallBlock: ComponentType<ToolCallBlockProps>;
19
+ ExecBlock: ComponentType<ExecBlockProps>;
20
+ SearchBlock: ComponentType<SearchBlockProps>;
21
+ PatchBlock: ComponentType<PatchBlockProps>;
22
+ TodoListBlock: ComponentType<TodoListBlockProps>;
23
+ ErrorBlock: ComponentType<ErrorBlockProps>;
24
+ RawEventBlock: ComponentType<RawEventBlockProps>;
25
+ }
26
+ export interface CodexTranscriptProps {
27
+ events: ChatStreamEvent[];
28
+ status?: TranscriptStatus;
29
+ error?: {
30
+ message: string;
31
+ details?: string;
32
+ };
33
+ className?: string;
34
+ maxItems?: number;
35
+ emptyState?: ReactNode;
36
+ onItemClick?: (itemId: string) => void;
37
+ components?: Partial<CodexTranscriptComponents>;
38
+ disableSmoothStream?: boolean;
39
+ onInternalError?: (err: unknown, event?: ChatStreamEvent) => void;
40
+ }
41
+ export declare function CodexTranscript(props: CodexTranscriptProps): JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface ErrorBlockProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'error';
5
+ }>;
6
+ }
7
+ export declare function ErrorBlock({ item }: ErrorBlockProps): JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface ExecBlockProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'exec';
5
+ }>;
6
+ /** Open by default? Defaults to false (collapsed). */
7
+ defaultOpen?: boolean;
8
+ }
9
+ export declare function ExecBlock({ item, defaultOpen }: ExecBlockProps): JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { Component, ErrorInfo, ReactNode } from 'react';
2
+ export interface ItemErrorBoundaryProps {
3
+ fallback?: ReactNode;
4
+ onError?: (err: unknown, info: ErrorInfo) => void;
5
+ children: ReactNode;
6
+ }
7
+ interface State {
8
+ hasError: boolean;
9
+ }
10
+ export declare class ItemErrorBoundary extends Component<ItemErrorBoundaryProps, State> {
11
+ state: State;
12
+ static getDerivedStateFromError(): State;
13
+ componentDidCatch(err: unknown, info: ErrorInfo): void;
14
+ render(): ReactNode;
15
+ }
16
+ export {};
@@ -0,0 +1,20 @@
1
+ export interface MarkdownProps {
2
+ /** Plain text or Markdown source. Treated as Markdown by default. */
3
+ children: string;
4
+ /** Skip parsing — render as plain pre-wrapped text. */
5
+ asPlain?: boolean;
6
+ className?: string;
7
+ }
8
+ /**
9
+ * Lightweight Markdown renderer wired with GFM (tables, strikethrough, task
10
+ * lists, autolinks). Code blocks render with monospace + dark background.
11
+ * Intentionally bare: no syntax highlighting (keeps the bundle small) and no
12
+ * raw HTML allowed (XSS-safe by default).
13
+ *
14
+ * Inline `::action{params}` directives (a Codex Web/IDE convention emitted by
15
+ * the model after successful side-effects) are extracted out of the Markdown
16
+ * stream and rendered as compact badges.
17
+ */
18
+ declare function MarkdownInner({ children, asPlain, className }: MarkdownProps): JSX.Element;
19
+ export declare const Markdown: import('react').MemoExoticComponent<typeof MarkdownInner>;
20
+ export {};
@@ -0,0 +1,10 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface MessageBubbleProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'user_message' | 'assistant_text';
5
+ }>;
6
+ smoothStream?: boolean;
7
+ /** When true (default), parse text as Markdown. */
8
+ markdown?: boolean;
9
+ }
10
+ export declare function MessageBubble({ item, smoothStream, markdown }: MessageBubbleProps): JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface PatchBlockProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'patch';
5
+ }>;
6
+ /** Open by default? Defaults to false (collapsed). */
7
+ defaultOpen?: boolean;
8
+ }
9
+ export declare function PatchBlock({ item, defaultOpen }: PatchBlockProps): JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface RawEventBlockProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'raw';
5
+ }>;
6
+ }
7
+ export declare function RawEventBlock({ item }: RawEventBlockProps): JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface ReasoningBlockProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'reasoning';
5
+ }>;
6
+ defaultOpen?: boolean;
7
+ smoothStream?: boolean;
8
+ /** Render body as Markdown. Defaults to true. */
9
+ markdown?: boolean;
10
+ }
11
+ export declare function ReasoningBlock({ item, defaultOpen, smoothStream, markdown }: ReasoningBlockProps): JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface SearchBlockProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'search';
5
+ }>;
6
+ initialVisible?: number;
7
+ /** Open by default? Defaults to false (collapsed). */
8
+ defaultOpen?: boolean;
9
+ }
10
+ export declare function SearchBlock({ item, initialVisible, defaultOpen }: SearchBlockProps): JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { TranscriptStatus } from '../types/model.js';
2
+ export interface StatusBarProps {
3
+ status: TranscriptStatus;
4
+ label?: string;
5
+ error?: {
6
+ message: string;
7
+ details?: string;
8
+ };
9
+ }
10
+ export declare function StatusBar({ status, label, error }: StatusBarProps): JSX.Element | null;
@@ -0,0 +1,9 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface TodoListBlockProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'todo_list';
5
+ }>;
6
+ /** Initial open/collapsed state. Defaults to collapsed. */
7
+ defaultOpen?: boolean;
8
+ }
9
+ export declare function TodoListBlock({ item, defaultOpen }: TodoListBlockProps): JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { ItemView } from '../types/model.js';
2
+ export interface ToolCallBlockProps {
3
+ item: Extract<ItemView, {
4
+ kind: 'tool_call';
5
+ }>;
6
+ /** Whether the block is open by default. Defaults to false (collapsed). */
7
+ defaultOpen?: boolean;
8
+ }
9
+ export declare function ToolCallBlock({ item, defaultOpen }: ToolCallBlockProps): JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from 'react';
2
+ import { TurnView } from '../types/model.js';
3
+ export interface TurnContainerProps {
4
+ turn: TurnView;
5
+ children: ReactNode;
6
+ }
7
+ export declare function TurnContainer({ turn, children }: TurnContainerProps): JSX.Element;
@@ -0,0 +1,2 @@
1
+ export declare function shouldCollapseValue(value: unknown): boolean;
2
+ export declare function safeStringify(value: unknown): string;
@@ -0,0 +1,16 @@
1
+ export declare const ICONS: {
2
+ readonly tool: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
3
+ readonly exec: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
4
+ readonly patch: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
5
+ readonly search: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
6
+ readonly web: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
7
+ readonly message: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
8
+ readonly reasoning: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
9
+ readonly ok: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
10
+ readonly fail: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
11
+ readonly stop: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
12
+ readonly warn: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
13
+ readonly expand: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
14
+ readonly collapse: import('react').ForwardRefExoticComponent<Omit<import('lucide-react').LucideProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
15
+ };
16
+ export type IconKey = keyof typeof ICONS;
@@ -0,0 +1,10 @@
1
+ import { ChatStreamEvent } from '../types/events.js';
2
+ import { TranscriptModel, TranscriptStatus } from '../types/model.js';
3
+ export interface UseCodexTranscriptOptions {
4
+ status?: TranscriptStatus;
5
+ onInternalError?: (err: unknown, event?: ChatStreamEvent) => void;
6
+ }
7
+ export declare function useCodexTranscript(events: ChatStreamEvent[], options?: UseCodexTranscriptOptions): {
8
+ model: TranscriptModel;
9
+ status: TranscriptStatus;
10
+ };
@@ -0,0 +1,7 @@
1
+ export interface UseSmoothStreamOptions {
2
+ enabled?: boolean;
3
+ /** When > 0, override automatic chars-per-frame calculation. */
4
+ charsPerFrame?: number;
5
+ minDelayMs?: number;
6
+ }
7
+ export declare function useSmoothStream(fullText: string, options?: UseSmoothStreamOptions): string;
@@ -0,0 +1,38 @@
1
+ export type { ChatStreamEvent, ChatStreamEventType, TokenUsage, SearchResult, PatchFile, TodoEntry } from './types/events.js';
2
+ export type { TranscriptModel, TurnView, ItemView, ItemKind, ItemStatus, TranscriptStatus } from './types/model.js';
3
+ export { EMPTY_MODEL } from './types/model.js';
4
+ export { reduceTranscript } from './reducer/transcript.js';
5
+ export { inferStatus } from './reducer/status.js';
6
+ export { useCodexTranscript } from './hooks/useCodexTranscript.js';
7
+ export type { UseCodexTranscriptOptions } from './hooks/useCodexTranscript.js';
8
+ export { useSmoothStream } from './hooks/useSmoothStream.js';
9
+ export type { UseSmoothStreamOptions } from './hooks/useSmoothStream.js';
10
+ export { CodexTranscript } from './components/CodexTranscript.js';
11
+ export type { CodexTranscriptProps, CodexTranscriptComponents } from './components/CodexTranscript.js';
12
+ export { StatusBar } from './components/StatusBar.js';
13
+ export type { StatusBarProps } from './components/StatusBar.js';
14
+ export { TurnContainer } from './components/TurnContainer.js';
15
+ export type { TurnContainerProps } from './components/TurnContainer.js';
16
+ export { MessageBubble } from './components/MessageBubble.js';
17
+ export type { MessageBubbleProps } from './components/MessageBubble.js';
18
+ export { ReasoningBlock } from './components/ReasoningBlock.js';
19
+ export type { ReasoningBlockProps } from './components/ReasoningBlock.js';
20
+ export { ToolCallBlock } from './components/ToolCallBlock.js';
21
+ export type { ToolCallBlockProps } from './components/ToolCallBlock.js';
22
+ export { ExecBlock } from './components/ExecBlock.js';
23
+ export type { ExecBlockProps } from './components/ExecBlock.js';
24
+ export { SearchBlock } from './components/SearchBlock.js';
25
+ export type { SearchBlockProps } from './components/SearchBlock.js';
26
+ export { PatchBlock } from './components/PatchBlock.js';
27
+ export type { PatchBlockProps } from './components/PatchBlock.js';
28
+ export { TodoListBlock } from './components/TodoListBlock.js';
29
+ export type { TodoListBlockProps } from './components/TodoListBlock.js';
30
+ export { ErrorBlock } from './components/ErrorBlock.js';
31
+ export type { ErrorBlockProps } from './components/ErrorBlock.js';
32
+ export { RawEventBlock } from './components/RawEventBlock.js';
33
+ export type { RawEventBlockProps } from './components/RawEventBlock.js';
34
+ export { ItemErrorBoundary } from './components/ItemErrorBoundary.js';
35
+ export type { ItemErrorBoundaryProps } from './components/ItemErrorBoundary.js';
36
+ export { Markdown } from './components/Markdown.js';
37
+ export type { MarkdownProps } from './components/Markdown.js';
38
+ export declare const VERSION = "0.1.1";