History

Drop em-dashes from new comments

Rhys Sullivan committed 4 months ago

Commit 69499191 parent 6a494f97 files · +13 −13Browse files

Unified · Split

7 files
  1. apps/cloud/drizzle/0010_ndjson_output_arrays.sql +1 −1
  2. e2e/scenarios/openapi-ndjson-output.test.ts +6 −6
  3. packages/plugins/openapi/src/sdk/extract.test.ts +1 −1
  4. packages/plugins/openapi/src/sdk/extract.ts +1 −1
  5. packages/plugins/openapi/src/sdk/ndjson-output-migration.ts +2 −2
  6. packages/plugins/openapi/src/sdk/openapi-utils.ts +1 −1
  7. packages/plugins/openapi/src/sdk/streaming-response.test.ts +1 −1
apps/cloud/drizzle/0010_ndjson_output_arrays.sql+1−1
@@ -1,6 +1,6 @@
1-- Extraction used to persist an NDJSON operation's PER-LINE response schema1-- Extraction used to persist an NDJSON operation's PER-LINE response schema
2-- as the tool's output schema, while the invoke path returns an ARRAY of2-- as the tool's output schema, while the invoke path returns an ARRAY of
3-- parsed lines — so describe previews promised a single object invocations3-- parsed lines, so describe previews promised a single object invocations
4-- never returned. The producer now wraps those schemas in an array. Persisted4-- never returned. The producer now wraps those schemas in an array. Persisted
5-- `tool` rows can't be recognized as NDJSON-derived from their schema alone,5-- `tool` rows can't be recognized as NDJSON-derived from their schema alone,
6-- but the stored operation bindings kept the response content type, so the6-- but the stored operation bindings kept the response content type, so the
e2e/scenarios/openapi-ndjson-output.test.ts+6−6
@@ -4,7 +4,7 @@ · 3 unmodified lines
4// NDJSON endpoints (Vercel's getRuntimeLogs is the motivating real case) are4// NDJSON endpoints (Vercel's getRuntimeLogs is the motivating real case) are
5// spec'd with a PER-LINE schema under `application/stream+json`: the schema5// spec'd with a PER-LINE schema under `application/stream+json`: the schema
6// describes one log line, the body is many of them. Executor's invoke path6// describes one log line, the body is many of them. Executor's invoke path
7// already understands this — it collects the stream and returns an ARRAY of7// already understands this: it collects the stream and returns an ARRAY of
8// parsed rows. But extraction stores the per-line schema as the operation's8// parsed rows. But extraction stores the per-line schema as the operation's
9// outputSchema unchanged, so `tools.schema` / `tools.describe.tool()` advertise9// outputSchema unchanged, so `tools.schema` / `tools.describe.tool()` advertise
10// `data: { level; message; ... }` (a single object) while the runtime value is10// `data: { level; message; ... }` (a single object) while the runtime value is
@@ -31,7 +31,7 @@ const api = composePluginApi([openApiHttpPlugin()] as const); · 20 unmodified lines
31 31
32const unique = (prefix: string) => `${prefix}_${randomBytes(4).toString("hex")}`;32const unique = (prefix: string) => `${prefix}_${randomBytes(4).toString("hex")}`;
33 33
34// Three real-shaped runtime-log lines, one JSON document per line — exactly34// Three real-shaped runtime-log lines, one JSON document per line, exactly
35// what Vercel's runtime-logs endpoint sends over application/stream+json.35// what Vercel's runtime-logs endpoint sends over application/stream+json.
36const LOG_LINES = [36const LOG_LINES = [
37 { level: "info", message: "build started", rowId: "r1", timestampInMs: 1_700_000_000_000 },37 { level: "info", message: "build started", rowId: "r1", timestampInMs: 1_700_000_000_000 },
@@ -63,7 +63,7 @@ const serveNdjsonLogs = Effect.acquireRelease( · 25 unmodified lines
63 (server) => Effect.sync(server.close),63 (server) => Effect.sync(server.close),
64);64);
65 65
66// The response declares the schema of ONE line under application/stream+json —66// The response declares the schema of ONE line under application/stream+json,
67// the same convention Vercel's spec uses for getRuntimeLogs.67// the same convention Vercel's spec uses for getRuntimeLogs.
68const runtimeLogsSpec = (baseUrl: string): string =>68const runtimeLogsSpec = (baseUrl: string): string =>
69 JSON.stringify({69 JSON.stringify({
@@ -219,7 +219,7 @@ scenario( · 149 unmodified lines
219 219
220 // THE CONTRACT UNDER TEST: the advertised type must describe that220 // THE CONTRACT UNDER TEST: the advertised type must describe that
221 // array. Today extraction stores the per-line schema unwrapped, so221 // array. Today extraction stores the per-line schema unwrapped, so
222 // the typedef claims `data` is a single log-line object — the exact222 // the typedef claims `data` is a single log-line object, the exact
223 // mismatch that pushes agents into JSON.stringify shape-probing.223 // mismatch that pushes agents into JSON.stringify shape-probing.
224 const advertised = schema.outputTypeScript ?? "";224 const advertised = schema.outputTypeScript ?? "";
225 expect(225 expect(
@@ -229,7 +229,7 @@ scenario( · 3 unmodified lines
229 ` runtime: Array<{ level; message; rowId; timestampInMs }> (${rows.length} rows)`,229 ` runtime: Array<{ level; message; rowId; timestampInMs }> (${rows.length} rows)`,
230 ).toBe(true);230 ).toBe(true);
231 231
232 // And the sandbox's describe.tool must tell the same story — it is232 // And the sandbox's describe.tool must tell the same story: it is
233 // the surface agents actually consult before writing code.233 // the surface agents actually consult before writing code.
234 const sandboxAdvertised = String(invoked.outputTypeScript ?? "");234 const sandboxAdvertised = String(invoked.outputTypeScript ?? "");
235 expect(235 expect(
@@ -238,7 +238,7 @@ scenario( · 2 unmodified lines
238 ` advertised: ${sandboxAdvertised}`,238 ` advertised: ${sandboxAdvertised}`,
239 ).toBe(true);239 ).toBe(true);
240 }),240 }),
241 // Selfhost shares one workspace identity — leaked connections fail241 // Selfhost shares one workspace identity; leaked connections fail
242 // other scenarios' zero-state assertions.242 // other scenarios' zero-state assertions.
243 Effect.gen(function* () {243 Effect.gen(function* () {
244 yield* executeJson(session, removeConnectionsCode(slug)).pipe(Effect.ignore);244 yield* executeJson(session, removeConnectionsCode(slug)).pipe(Effect.ignore);
packages/plugins/openapi/src/sdk/extract.test.ts+1−1
@@ -93,7 +93,7 @@ describe("OpenAPI extract response bodies", () => { · 92 unmodified lines
93 // NDJSON endpoints (e.g. Vercel's runtime-logs) declare the schema of93 // NDJSON endpoints (e.g. Vercel's runtime-logs) declare the schema of
94 // ONE line under application/stream+json; the invoke path returns an94 // ONE line under application/stream+json; the invoke path returns an
95 // array of parsed lines, so the advertised output schema must be that95 // array of parsed lines, so the advertised output schema must be that
96 // array — not the per-line object.96 // array, not the per-line object.
97 const lineSchema = {97 const lineSchema = {
98 type: "object",98 type: "object",
99 properties: { level: { type: "string" }, message: { type: "string" } },99 properties: { level: { type: "string" }, message: { type: "string" } },
packages/plugins/openapi/src/sdk/extract.ts+1−1
@@ -265,7 +265,7 @@ const extractResponseBody = ( · 264 unmodified lines
265 * Derive an operation's output schema from its response body. NDJSON bodies265 * Derive an operation's output schema from its response body. NDJSON bodies
266 * (`application/stream+json` and friends) are spec'd per LINE but returned by266 * (`application/stream+json` and friends) are spec'd per LINE but returned by
267 * the invoke path as an array of parsed lines, so the advertised schema wraps267 * the invoke path as an array of parsed lines, so the advertised schema wraps
268 * the line schema in an array — otherwise describe previews promise a single268 * the line schema in an array; otherwise describe previews promise a single
269 * object that invocations never return. Used by both the whole-tree extract269 * object that invocations never return. Used by both the whole-tree extract
270 * and the serve path's stored-binding rebuild so the two stay in lockstep.270 * and the serve path's stored-binding rebuild so the two stay in lockstep.
271 */271 */
packages/plugins/openapi/src/sdk/ndjson-output-migration.ts+2−2
@@ -3,7 +3,7 @@ · 2 unmodified lines
3//3//
4// Extraction used to persist an NDJSON operation's PER-LINE response schema as4// Extraction used to persist an NDJSON operation's PER-LINE response schema as
5// the tool's output schema, while the invoke path returns an ARRAY of parsed5// the tool's output schema, while the invoke path returns an ARRAY of parsed
6// lines — so describe previews promised a single object that invocations never6// lines, so describe previews promised a single object that invocations never
7// returned. The producer now wraps those schemas in an array; the per-line7// returned. The producer now wraps those schemas in an array; the per-line
8// shape can't be recognized from a persisted `tool` row alone (it's just a8// shape can't be recognized from a persisted `tool` row alone (it's just a
9// JSON schema), but the stored operation bindings kept the response content9// JSON schema), but the stored operation bindings kept the response content
@@ -52,7 +52,7 @@ const tableExists = (client: SqliteDataMigrationClient, table: string) => · 42 unmodified lines
52/** Stale-mark every connection whose integration has at least one stored52/** Stale-mark every connection whose integration has at least one stored
53 * operation binding with an NDJSON response, so the next read rebuilds its53 * operation binding with an NDJSON response, so the next read rebuilds its
54 * tool rows (with array-wrapped output schemas). Returns the number of54 * tool rows (with array-wrapped output schemas). Returns the number of
55 * connections marked. Fresh databases may lack either table — nothing to55 * connections marked. Fresh databases may lack either table; nothing to
56 * migrate. */56 * migrate. */
57export const runSqliteNdjsonOutputMigration = (57export const runSqliteNdjsonOutputMigration = (
58 client: SqliteDataMigrationClient,58 client: SqliteDataMigrationClient,
packages/plugins/openapi/src/sdk/openapi-utils.ts+1−1
@@ -138,7 +138,7 @@ export const normalizeMediaType = (mediaType: string | null | undefined): string · 137 unmodified lines
138 138
139/** Media types whose bodies are newline-delimited JSON documents. The invoke139/** Media types whose bodies are newline-delimited JSON documents. The invoke
140 * path collects these streams and returns an ARRAY of parsed lines, so every140 * path collects these streams and returns an ARRAY of parsed lines, so every
141 * schema surface must describe that array — the spec convention is to declare141 * schema surface must describe that array: the spec convention is to declare
142 * the schema of ONE line (e.g. Vercel's runtime-logs endpoint). */142 * the schema of ONE line (e.g. Vercel's runtime-logs endpoint). */
143export const NDJSON_MEDIA_TYPES: ReadonlySet<string> = new Set([143export const NDJSON_MEDIA_TYPES: ReadonlySet<string> = new Set([
144 "application/stream+json",144 "application/stream+json",
packages/plugins/openapi/src/sdk/streaming-response.test.ts+1−1
@@ -279,7 +279,7 @@ describe("OpenAPI streaming responses", () => { · 278 unmodified lines
279 // The spec declares the schema of ONE line (Vercel's runtime-logs279 // The spec declares the schema of ONE line (Vercel's runtime-logs
280 // convention); the runtime returns an array of parsed lines. The280 // convention); the runtime returns an array of parsed lines. The
281 // advertised output schema must describe that array on BOTH serve281 // advertised output schema must describe that array on BOTH serve
282 // paths — the add-time compile and the stored-binding rebuild — or282 // paths (the add-time compile and the stored-binding rebuild) or
283 // agents write code against a shape that never comes back.283 // agents write code against a shape that never comes back.
284 const lineSchema = {284 const lineSchema = {
285 type: "object",285 type: "object",