ocpipe 0.6.7 → 0.6.8
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/package.json +1 -1
- package/src/codex.ts +105 -2
- package/src/index.ts +5 -0
- package/src/types.ts +34 -0
package/package.json
CHANGED
package/src/codex.ts
CHANGED
|
@@ -7,10 +7,16 @@
|
|
|
7
7
|
import {
|
|
8
8
|
Codex,
|
|
9
9
|
type CodexOptions as CodexSdkClientOptions,
|
|
10
|
+
type RunResult,
|
|
10
11
|
type ThreadOptions,
|
|
11
12
|
} from '@openai/codex-sdk'
|
|
12
13
|
import { PROJECT_ROOT } from './paths.js'
|
|
13
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
CodexOptions,
|
|
16
|
+
CodexRunSummary,
|
|
17
|
+
RunAgentOptions,
|
|
18
|
+
RunAgentResult,
|
|
19
|
+
} from './types.js'
|
|
14
20
|
|
|
15
21
|
class CodexLogFilter {
|
|
16
22
|
private buf = ''
|
|
@@ -121,13 +127,15 @@ export async function runCodexAgent(
|
|
|
121
127
|
|
|
122
128
|
const nextSessionId = codex?.ephemeral ? '' : (thread.id ?? '')
|
|
123
129
|
const sessionStr = nextSessionId || 'none'
|
|
130
|
+
const runSummary = buildCodexRunSummary(result)
|
|
124
131
|
console.error(
|
|
125
|
-
`<<< Codex SDK done
|
|
132
|
+
`<<< Codex SDK done [thread:${sessionStr}]\n${formatCodexRunSummary(runSummary)}`,
|
|
126
133
|
)
|
|
127
134
|
|
|
128
135
|
return {
|
|
129
136
|
text: response,
|
|
130
137
|
sessionId: nextSessionId,
|
|
138
|
+
runSummary,
|
|
131
139
|
}
|
|
132
140
|
} catch (err) {
|
|
133
141
|
if (timedOut) {
|
|
@@ -143,6 +151,101 @@ export async function runCodexAgent(
|
|
|
143
151
|
}
|
|
144
152
|
}
|
|
145
153
|
|
|
154
|
+
/** buildCodexRunSummary projects a Codex turn into a parent-readable summary. */
|
|
155
|
+
export function buildCodexRunSummary(result: RunResult): CodexRunSummary {
|
|
156
|
+
const commands: CodexRunSummary['commands'] = []
|
|
157
|
+
const fileChanges: CodexRunSummary['fileChanges'] = []
|
|
158
|
+
let errorMessage = ''
|
|
159
|
+
let finalMessage = result.finalResponse.trim()
|
|
160
|
+
|
|
161
|
+
for (const item of result.items) {
|
|
162
|
+
switch (item.type) {
|
|
163
|
+
case 'agent_message':
|
|
164
|
+
if (item.text) finalMessage = item.text
|
|
165
|
+
break
|
|
166
|
+
case 'command_execution':
|
|
167
|
+
commands.push({
|
|
168
|
+
command: item.command,
|
|
169
|
+
status: item.status,
|
|
170
|
+
exitCode: item.exit_code ?? null,
|
|
171
|
+
})
|
|
172
|
+
break
|
|
173
|
+
case 'file_change':
|
|
174
|
+
for (const change of item.changes) {
|
|
175
|
+
fileChanges.push({
|
|
176
|
+
path: change.path,
|
|
177
|
+
kind: change.kind,
|
|
178
|
+
status: item.status,
|
|
179
|
+
})
|
|
180
|
+
}
|
|
181
|
+
break
|
|
182
|
+
case 'error':
|
|
183
|
+
errorMessage = item.message
|
|
184
|
+
break
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const usage = result.usage
|
|
189
|
+
return {
|
|
190
|
+
status: errorMessage ? 'failed' : 'completed',
|
|
191
|
+
finalMessage: finalMessage.trim(),
|
|
192
|
+
errorMessage,
|
|
193
|
+
commands,
|
|
194
|
+
fileChanges,
|
|
195
|
+
tokens:
|
|
196
|
+
usage ?
|
|
197
|
+
{
|
|
198
|
+
input: usage.input_tokens,
|
|
199
|
+
cached: usage.cached_input_tokens,
|
|
200
|
+
output: usage.output_tokens,
|
|
201
|
+
reasoning: usage.reasoning_output_tokens,
|
|
202
|
+
}
|
|
203
|
+
: null,
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** formatCodexRunSummary renders a Codex run summary as a clean text block. */
|
|
208
|
+
export function formatCodexRunSummary(summary: CodexRunSummary): string {
|
|
209
|
+
const lines: string[] = [`status: ${summary.status}`]
|
|
210
|
+
if (summary.errorMessage) {
|
|
211
|
+
lines.push(`error: ${summary.errorMessage}`)
|
|
212
|
+
}
|
|
213
|
+
if (summary.commands.length > 0) {
|
|
214
|
+
const failed = summary.commands.filter(isFailedCommand).length
|
|
215
|
+
lines.push(
|
|
216
|
+
`commands: ${summary.commands.length} completed, ${failed} failed`,
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
if (summary.fileChanges.length > 0) {
|
|
220
|
+
let add = 0
|
|
221
|
+
let update = 0
|
|
222
|
+
let del = 0
|
|
223
|
+
for (const change of summary.fileChanges) {
|
|
224
|
+
if (change.kind === 'add') add++
|
|
225
|
+
else if (change.kind === 'delete') del++
|
|
226
|
+
else update++
|
|
227
|
+
}
|
|
228
|
+
lines.push(`files: add=${add} update=${update} delete=${del}`)
|
|
229
|
+
}
|
|
230
|
+
if (summary.tokens) {
|
|
231
|
+
const t = summary.tokens
|
|
232
|
+
lines.push(
|
|
233
|
+
`tokens: input=${t.input} cached=${t.cached} output=${t.output} reasoning=${t.reasoning}`,
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
if (summary.finalMessage) {
|
|
237
|
+
lines.push(`final_message:\n${summary.finalMessage}`)
|
|
238
|
+
}
|
|
239
|
+
return lines.join('\n')
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function isFailedCommand(command: CodexRunSummary['commands'][number]): boolean {
|
|
243
|
+
return (
|
|
244
|
+
command.status === 'failed' ||
|
|
245
|
+
(command.exitCode !== null && command.exitCode !== 0)
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
146
249
|
function buildCodexClientOptions(
|
|
147
250
|
codex: CodexOptions | undefined,
|
|
148
251
|
): CodexSdkClientOptions {
|
package/src/index.ts
CHANGED
|
@@ -50,6 +50,7 @@ export { createSessionId, createBaseState, extendBaseState } from './state.js'
|
|
|
50
50
|
|
|
51
51
|
// Agent integration
|
|
52
52
|
export { runAgent, logStep } from './agent.js'
|
|
53
|
+
export { buildCodexRunSummary, formatCodexRunSummary } from './codex.js'
|
|
53
54
|
|
|
54
55
|
// Response parsing
|
|
55
56
|
export {
|
|
@@ -116,6 +117,10 @@ export type {
|
|
|
116
117
|
// Agent types
|
|
117
118
|
RunAgentOptions,
|
|
118
119
|
RunAgentResult,
|
|
120
|
+
CodexRunSummary,
|
|
121
|
+
CodexRunCommand,
|
|
122
|
+
CodexRunFileChange,
|
|
123
|
+
CodexRunTokens,
|
|
119
124
|
// Correction types
|
|
120
125
|
CorrectionMethod,
|
|
121
126
|
CorrectionConfig,
|
package/src/types.ts
CHANGED
|
@@ -418,4 +418,38 @@ export interface RunAgentResult {
|
|
|
418
418
|
text: string
|
|
419
419
|
/** Session ID (for continuing the conversation). */
|
|
420
420
|
sessionId: string
|
|
421
|
+
/** Clean run summary, set for the Codex backend. */
|
|
422
|
+
runSummary?: CodexRunSummary
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** CodexRunCommand records one command the Codex agent executed. */
|
|
426
|
+
export interface CodexRunCommand {
|
|
427
|
+
command: string
|
|
428
|
+
status: string
|
|
429
|
+
exitCode: number | null
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/** CodexRunFileChange records one file the Codex agent changed. */
|
|
433
|
+
export interface CodexRunFileChange {
|
|
434
|
+
path: string
|
|
435
|
+
kind: 'add' | 'update' | 'delete'
|
|
436
|
+
status: string
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/** CodexRunTokens records token usage for a Codex turn. */
|
|
440
|
+
export interface CodexRunTokens {
|
|
441
|
+
input: number
|
|
442
|
+
cached: number
|
|
443
|
+
output: number
|
|
444
|
+
reasoning: number
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** CodexRunSummary is the parent-readable projection of a Codex turn. */
|
|
448
|
+
export interface CodexRunSummary {
|
|
449
|
+
status: 'completed' | 'failed' | 'unknown'
|
|
450
|
+
finalMessage: string
|
|
451
|
+
errorMessage: string
|
|
452
|
+
commands: CodexRunCommand[]
|
|
453
|
+
fileChanges: CodexRunFileChange[]
|
|
454
|
+
tokens: CodexRunTokens | null
|
|
421
455
|
}
|