@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.
- package/README.md +56 -0
- package/dist/components/CodexTranscript.d.ts +41 -0
- package/dist/components/ErrorBlock.d.ts +7 -0
- package/dist/components/ExecBlock.d.ts +9 -0
- package/dist/components/ItemErrorBoundary.d.ts +16 -0
- package/dist/components/Markdown.d.ts +20 -0
- package/dist/components/MessageBubble.d.ts +10 -0
- package/dist/components/PatchBlock.d.ts +9 -0
- package/dist/components/RawEventBlock.d.ts +7 -0
- package/dist/components/ReasoningBlock.d.ts +11 -0
- package/dist/components/SearchBlock.d.ts +10 -0
- package/dist/components/StatusBar.d.ts +10 -0
- package/dist/components/TodoListBlock.d.ts +9 -0
- package/dist/components/ToolCallBlock.d.ts +9 -0
- package/dist/components/TurnContainer.d.ts +7 -0
- package/dist/components/_shared.d.ts +2 -0
- package/dist/components/icons.d.ts +16 -0
- package/dist/hooks/useCodexTranscript.d.ts +10 -0
- package/dist/hooks/useSmoothStream.d.ts +7 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +13520 -0
- package/dist/index.js.map +1 -0
- package/dist/reducer/status.d.ts +2 -0
- package/dist/reducer/transcript.d.ts +4 -0
- package/dist/styles.css +493 -0
- package/dist/types/events.d.ts +164 -0
- package/dist/types/model.d.ts +75 -0
- package/docs/api.md +156 -0
- package/docs/changelog.md +40 -0
- package/docs/events.md +65 -0
- package/docs/integration-agentweb.md +112 -0
- package/docs/styling.md +81 -0
- package/docs/superpowers/plans/2026-05-15-codexview-implementation.md +3903 -0
- package/docs/superpowers/specs/2026-05-15-codexview-design.md +661 -0
- 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,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,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,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;
|
package/dist/index.d.ts
ADDED
|
@@ -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";
|