@poncho-ai/harness 0.31.0 → 0.31.2

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.
@@ -36,6 +36,8 @@ const MODEL_CONTEXT_WINDOWS: Record<string, number> = {
36
36
  const DEFAULT_CONTEXT_WINDOW = 200_000;
37
37
  const OPENAI_CODEX_DEFAULT_INSTRUCTIONS =
38
38
  "You are Codex, based on GPT-5. You are running as a coding agent in Poncho.";
39
+ const OPENAI_CODEX_RESPONSES_URL =
40
+ process.env.OPENAI_CODEX_RESPONSES_URL ?? "https://chatgpt.com/backend-api/codex/responses";
39
41
 
40
42
  const extractSystemInstructionFromInput = (input: unknown): string | undefined => {
41
43
  if (!Array.isArray(input)) return undefined;
@@ -62,6 +64,22 @@ const extractSystemInstructionFromInput = (input: unknown): string | undefined =
62
64
  return undefined;
63
65
  };
64
66
 
67
+ const normalizeToolParameterSchemas = (tools: unknown): void => {
68
+ if (!Array.isArray(tools)) return;
69
+ for (const tool of tools) {
70
+ if (!tool || typeof tool !== "object") continue;
71
+ const entry = tool as { parameters?: unknown };
72
+ if (!entry.parameters || typeof entry.parameters !== "object") continue;
73
+ const schema = entry.parameters as {
74
+ type?: unknown;
75
+ properties?: unknown;
76
+ };
77
+ if (schema.type === "object" && (typeof schema.properties !== "object" || schema.properties === null)) {
78
+ schema.properties = {};
79
+ }
80
+ }
81
+ };
82
+
65
83
  /**
66
84
  * Returns the context window size (in tokens) for a given model name.
67
85
  * Uses startsWith matching so dated variants (e.g. claude-opus-4-6-20260217)
@@ -117,7 +135,7 @@ export const createModelProvider = (provider?: string, config?: ProviderConfig):
117
135
  parsed.pathname.includes("/v1/responses") ||
118
136
  parsed.pathname.includes("/chat/completions");
119
137
  const targetUrl = shouldRewrite
120
- ? "https://chatgpt.com/backend-api/codex/responses"
138
+ ? OPENAI_CODEX_RESPONSES_URL
121
139
  : originalUrl;
122
140
  let body = init?.body;
123
141
  if (
@@ -130,12 +148,14 @@ export const createModelProvider = (provider?: string, config?: ProviderConfig):
130
148
  instructions?: unknown;
131
149
  input?: unknown;
132
150
  store?: unknown;
151
+ tools?: unknown;
133
152
  };
134
153
  if (typeof payload.instructions !== "string" || payload.instructions.trim() === "") {
135
154
  payload.instructions =
136
155
  extractSystemInstructionFromInput(payload.input) ??
137
156
  OPENAI_CODEX_DEFAULT_INSTRUCTIONS;
138
157
  }
158
+ normalizeToolParameterSchemas(payload.tools);
139
159
  // Codex endpoint requires store=false explicitly.
140
160
  payload.store = false;
141
161
  body = JSON.stringify(payload);
@@ -143,7 +163,20 @@ export const createModelProvider = (provider?: string, config?: ProviderConfig):
143
163
  // Keep original body if parsing fails.
144
164
  }
145
165
  }
146
- return fetch(targetUrl, { ...init, headers, body });
166
+ try {
167
+ return await fetch(targetUrl, { ...init, headers, body });
168
+ } catch (error) {
169
+ const message = error instanceof Error ? error.message : String(error);
170
+ if (
171
+ shouldRewrite &&
172
+ targetUrl.includes("chatgpt.com") &&
173
+ message.includes("ENOTFOUND chatgpt.com")
174
+ ) {
175
+ // Some networks block/override chatgpt.com DNS; retry on the SDK's original URL.
176
+ return fetch(originalUrl, { ...init, headers, body });
177
+ }
178
+ throw error;
179
+ }
147
180
  },
148
181
  });
149
182
  return (modelName: string) => openai(modelName);
package/src/state.ts CHANGED
@@ -30,6 +30,16 @@ export interface PendingSubagentResult {
30
30
  timestamp: number;
31
31
  }
32
32
 
33
+ export interface ArchivedToolResult {
34
+ toolResultId: string;
35
+ conversationId: string;
36
+ toolName: string;
37
+ toolCallId: string;
38
+ createdAt: number;
39
+ sizeBytes: number;
40
+ payload: string;
41
+ }
42
+
33
43
  export interface Conversation {
34
44
  conversationId: string;
35
45
  title: string;
@@ -80,6 +90,8 @@ export interface Conversation {
80
90
  * Unlike `_continuationMessages`, this is always set after a run
81
91
  * and does NOT signal that a continuation is pending. */
82
92
  _harnessMessages?: Message[];
93
+ /** Archived full-fidelity tool results keyed by toolResultId. */
94
+ _toolResultArchive?: Record<string, ArchivedToolResult>;
83
95
  createdAt: number;
84
96
  updatedAt: number;
85
97
  }
package/src/telemetry.ts CHANGED
@@ -58,6 +58,10 @@ export class TelemetryEmitter {
58
58
  // Latitude telemetry is handled by LatitudeTelemetry (from
59
59
  // @latitude-data/telemetry) via harness.runWithTelemetry().
60
60
  // Default behavior in local dev: print concise structured logs.
61
+ // Skip per-token stream logs to keep console output readable.
62
+ if (event.type === "model:chunk") {
63
+ return;
64
+ }
61
65
  // Strip large binary payloads (e.g. base64 images) to keep logs readable.
62
66
  process.stdout.write(`[event] ${event.type} ${sanitizeEventForLog(event)}\n`);
63
67
  }
@@ -1,6 +0,0 @@
1
-
2
- > @poncho-ai/harness@0.11.2 lint /Users/cesar/Dev/latitude/poncho-ai/packages/harness
3
- > eslint src/
4
-
5
- sh: eslint: command not found
6
-  ELIFECYCLE  Command failed.
@@ -1,34 +0,0 @@
1
-
2
- > @poncho-ai/harness@0.26.0 test /Users/cesar/Dev/latitude/poncho-ai/packages/harness
3
- > vitest
4
-
5
-
6
-  RUN  v1.6.1 /Users/cesar/Dev/latitude/poncho-ai/packages/harness
7
-
8
- stdout | test/mcp.test.ts > mcp bridge protocol transports > discovers and calls tools over streamable HTTP
9
- [poncho][mcp] {"event":"catalog.loaded","server":"remote","discoveredCount":1}
10
- [poncho][mcp] {"event":"tools.selected","requestedPatternCount":1,"registeredCount":1,"filteredByPolicyCount":0,"filteredByIntentCount":0}
11
-
12
- stdout | test/mcp.test.ts > mcp bridge protocol transports > sends custom headers alongside bearer token
13
- [poncho][mcp] {"event":"catalog.loaded","server":"custom-headers","discoveredCount":1}
14
-
15
- stderr | test/mcp.test.ts > mcp bridge protocol transports > skips discovery when bearer token env value is missing
16
- stdout | test/mcp.test.ts > mcp bridge protocol transports > selects discovered tools by requested patterns
17
- [poncho][mcp] {"event":"auth.token_missing","server":"remote","tokenEnv":"MISSING_TOKEN_ENV"}
18
- [poncho][mcp] {"event":"catalog.loaded","server":"remote","discoveredCount":2}
19
- [poncho][mcp] {"event":"tools.selected","requestedPatternCount":1,"registeredCount":1,"filteredByPolicyCount":0,"filteredByIntentCount":1}
20
-
21
- [poncho][mcp] {"event":"tools.selected","requestedPatternCount":1,"registeredCount":2,"filteredByPolicyCount":0,"filteredByIntentCount":0}
22
-
23
- stdout | test/mcp.test.ts > mcp bridge protocol transports > skips discovery when bearer token env value is missing
24
- [poncho][mcp] {"event":"tools.selected","requestedPatternCount":1,"registeredCount":0,"filteredByPolicyCount":0,"filteredByIntentCount":0}
25
-
26
- [event] step:completed {"type":"step:completed","step":1,"duration":1}
27
- ✓ test/telemetry.test.ts  (3 tests) 5ms
28
- [event] step:started {"type":"step:started","step":2}
29
- ✓ test/schema-converter.test.ts  (27 tests) 13ms
30
- stdout | test/mcp.test.ts > mcp bridge protocol transports > returns actionable errors for 403 permission failures
31
- [poncho][mcp] {"event":"catalog.loaded","server":"remote","discoveredCount":1}
32
- [poncho][mcp] {"event":"tools.selected","requestedPatternCount":1,"registeredCount":1,"filteredByPolicyCount":0,"filteredByIntentCount":0}
33
-
34
- ✓ test/mcp.test.ts  (7 tests) 84ms