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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ocpipe",
3
- "version": "0.6.7",
3
+ "version": "0.6.8",
4
4
  "description": "SDK for LLM pipelines with OpenCode, Codex, and Zod",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
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 { CodexOptions, RunAgentOptions, RunAgentResult } from './types.js'
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 (${response.length} chars) [thread:${sessionStr}]`,
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
  }