better-codex 0.1.4 → 0.2.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.
@@ -1,4 +1,4 @@
1
- import type { Message, MessageKind } from '../types'
1
+ import type { CommandAction, FileChangeMeta, Message, MessageKind, MessageMeta } from '../types'
2
2
 
3
3
  type ThreadItem = {
4
4
  type: string
@@ -6,11 +6,11 @@ type ThreadItem = {
6
6
  [key: string]: unknown
7
7
  }
8
8
 
9
- type CommandAction =
10
- | { type: 'read'; command: string; name: string; path: string }
11
- | { type: 'listFiles'; command: string; path?: string | null }
12
- | { type: 'search'; command: string; query?: string | null; path?: string | null }
13
- | { type: 'unknown'; command: string }
9
+ // type CommandAction =
10
+ // | { type: 'read'; command: string; name: string; path: string }
11
+ // | { type: 'listFiles'; command: string; path?: string | null }
12
+ // | { type: 'search'; command: string; query?: string | null; path?: string | null }
13
+ // | { type: 'unknown'; command: string }
14
14
 
15
15
  const clampText = (value: string, max = 1400) => {
16
16
  if (value.length <= max) {
@@ -99,7 +99,43 @@ const formatCommandActions = (actions: CommandAction[], commandFallback: string)
99
99
  }
100
100
  }
101
101
 
102
- export const formatThreadItem = (item: ThreadItem): { kind: MessageKind; content: string; title?: string } | null => {
102
+ type FormattedThreadItem = {
103
+ kind: MessageKind
104
+ content: string
105
+ title?: string
106
+ meta?: MessageMeta
107
+ }
108
+
109
+ const toFileChangeMeta = (change: {
110
+ path?: unknown
111
+ kind?: unknown
112
+ diff?: string
113
+ movePath?: unknown
114
+ move_path?: unknown
115
+ }): FileChangeMeta => {
116
+ const path = typeof change.path === 'string' ? change.path : 'unknown'
117
+ const kind =
118
+ typeof change.kind === 'string'
119
+ ? change.kind
120
+ : typeof (change.kind as { type?: string } | null | undefined)?.type === 'string'
121
+ ? String((change.kind as { type?: string }).type)
122
+ : 'update'
123
+ const movePath =
124
+ typeof change.movePath === 'string'
125
+ ? change.movePath
126
+ : typeof change.move_path === 'string'
127
+ ? change.move_path
128
+ : undefined
129
+
130
+ return {
131
+ path,
132
+ kind: kind === 'add' || kind === 'delete' ? kind : 'update',
133
+ diff: typeof change.diff === 'string' ? change.diff : undefined,
134
+ movePath: movePath ?? null,
135
+ }
136
+ }
137
+
138
+ export const formatThreadItem = (item: ThreadItem): FormattedThreadItem | null => {
103
139
  switch (item.type) {
104
140
  case 'reasoning': {
105
141
  const summary = Array.isArray(item.summary) ? item.summary.join('\n') : ''
@@ -113,13 +149,22 @@ export const formatThreadItem = (item: ThreadItem): { kind: MessageKind; content
113
149
  const actions = Array.isArray(item.commandActions) ? (item.commandActions as CommandAction[]) : []
114
150
  const actionSummary = formatCommandActions(actions, command)
115
151
  const content = output ? `${actionSummary.content}\n\n${output}` : actionSummary.content
116
- return { kind: actionSummary.kind, content: clampText(content), title: `${actionSummary.title} · ${status}` }
152
+ const meta: MessageMeta = {
153
+ commandActions: actions.length ? actions : undefined,
154
+ command,
155
+ status,
156
+ }
157
+ return { kind: actionSummary.kind, content: clampText(content), title: actionSummary.title, meta }
117
158
  }
118
159
  case 'fileChange': {
119
160
  const changes = Array.isArray(item.changes) ? item.changes : []
120
161
  const content = formatFileChanges(changes as Array<{ path?: string; kind?: string; diff?: string; movePath?: string }>)
121
162
  const status = typeof item.status === 'string' ? item.status : 'inProgress'
122
- return { kind: 'file', content, title: `Files · ${status}` }
163
+ const meta: MessageMeta = {
164
+ fileChanges: changes.length ? changes.map((change) => toFileChangeMeta(change as Record<string, unknown>)) : undefined,
165
+ status,
166
+ }
167
+ return { kind: 'file', content, title: 'Files', meta }
123
168
  }
124
169
  case 'mcpToolCall': {
125
170
  const server = typeof item.server === 'string' ? item.server : 'mcp'
@@ -166,5 +211,6 @@ export const buildSystemMessage = (item: ThreadItem): Message | null => {
166
211
  title: formatted.title,
167
212
  content: formatted.content,
168
213
  timestamp: '',
214
+ meta: formatted.meta,
169
215
  }
170
216
  }
@@ -4,6 +4,7 @@ export type SlashCommandId =
4
4
  | 'cwd'
5
5
  | 'approvals'
6
6
  | 'skills'
7
+ | 'switch'
7
8
  | 'review'
8
9
  | 'new'
9
10
  | 'resume'
@@ -32,6 +33,7 @@ export const SLASH_COMMANDS: SlashCommandDefinition[] = [
32
33
  { id: 'cwd', description: 'set working directory for the thread', availableDuringTask: false },
33
34
  { id: 'approvals', description: 'choose what Codex can do without approval', availableDuringTask: false },
34
35
  { id: 'skills', description: 'browse and insert skills', availableDuringTask: true },
36
+ { id: 'switch', description: 'switch to a different account for this thread', availableDuringTask: false },
35
37
  { id: 'review', description: 'review my current changes and find issues', availableDuringTask: false },
36
38
  { id: 'new', description: 'start a new chat during a conversation', availableDuringTask: false },
37
39
  { id: 'resume', description: 'resume a saved chat', availableDuringTask: false },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-codex",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "description": "Web launcher for Codex Hub",
5
5
  "bin": {
6
6
  "better-codex": "bin/better-codex.cjs"