|
|
@@ -143,12 +143,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
const remove = toolAt(api.tools, "users.remove")
|
|
|
|
|
|
expect(api.skipped).toEqual([])
|
|
|
- if (
|
|
|
- !Tool.isDefinition(get) ||
|
|
|
- !Tool.isDefinition(create) ||
|
|
|
- !Tool.isDefinition(search) ||
|
|
|
- !Tool.isDefinition(remove)
|
|
|
- ) {
|
|
|
+ if (!Tool.isTool(get) || !Tool.isTool(create) || !Tool.isTool(search) || !Tool.isTool(remove)) {
|
|
|
throw new Error("happy-path fixture did not generate every operation")
|
|
|
}
|
|
|
expect(inputTypeScript(get)).toBe(
|
|
|
@@ -241,23 +236,23 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
expect(toolAt(result.tools, "v2.session.create")).not.toBeUndefined()
|
|
|
|
|
|
const sessionGet = toolAt(result.tools, "v2.session.get")
|
|
|
- expect(Tool.isDefinition(sessionGet)).toBe(true)
|
|
|
- if (!Tool.isDefinition(sessionGet)) throw new Error("v2.session.get was not generated")
|
|
|
+ expect(Tool.isTool(sessionGet)).toBe(true)
|
|
|
+ if (!Tool.isTool(sessionGet)) throw new Error("v2.session.get was not generated")
|
|
|
expect(inputTypeScript(sessionGet)).toBe("{ sessionID: string }")
|
|
|
expect(outputTypeScript(sessionGet)).toContain("id: string")
|
|
|
expect(outputTypeScript(sessionGet)).toContain("additions: number")
|
|
|
|
|
|
const switchAgent = toolAt(result.tools, "v2.session.switchAgent")
|
|
|
- expect(Tool.isDefinition(switchAgent)).toBe(true)
|
|
|
- if (!Tool.isDefinition(switchAgent)) throw new Error("v2.session.switchAgent was not generated")
|
|
|
+ expect(Tool.isTool(switchAgent)).toBe(true)
|
|
|
+ if (!Tool.isTool(switchAgent)) throw new Error("v2.session.switchAgent was not generated")
|
|
|
expect(inputTypeScript(switchAgent)).toBe("{ sessionID: string; agent: string }")
|
|
|
|
|
|
const instructionPut = toolAt(result.tools, "v2.session.instructions.entry.put")
|
|
|
- expect(Tool.isDefinition(instructionPut)).toBe(true)
|
|
|
- if (!Tool.isDefinition(instructionPut)) throw new Error("v2.session.instructions.entry.put was not generated")
|
|
|
+ expect(Tool.isTool(instructionPut)).toBe(true)
|
|
|
+ if (!Tool.isTool(instructionPut)) throw new Error("v2.session.instructions.entry.put was not generated")
|
|
|
expect(inputTypeScript(instructionPut)).toBe("{ sessionID: string; key: string; value: unknown }")
|
|
|
expect(toolAt(result.tools, "v2_session_instructions_entry_put_2")).toBeUndefined()
|
|
|
- expect(Tool.isDefinition(toolAt(result.tools, "v2.pty.connect"))).toBe(false)
|
|
|
+ expect(Tool.isTool(toolAt(result.tools, "v2.pty.connect"))).toBe(false)
|
|
|
expect(toolAt(result.tools, "v2.session.log")).toBeUndefined()
|
|
|
expect(toolAt(result.tools, "v2.event.subscribe")).toBeUndefined()
|
|
|
expect(toolAt(result.tools, "v2.fs.read")).toBeUndefined()
|
|
|
@@ -278,9 +273,9 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
},
|
|
|
})
|
|
|
|
|
|
- expect(Tool.isDefinition(toolAt(result.tools, "group.item"))).toBe(true)
|
|
|
- expect(Tool.isDefinition(toolAt(result.tools, "group_item_2"))).toBe(true)
|
|
|
- expect(Tool.isDefinition(toolAt(result.tools, "group.operation.other"))).toBe(true)
|
|
|
+ expect(Tool.isTool(toolAt(result.tools, "group.item"))).toBe(true)
|
|
|
+ expect(Tool.isTool(toolAt(result.tools, "group_item_2"))).toBe(true)
|
|
|
+ expect(Tool.isTool(toolAt(result.tools, "group.operation.other"))).toBe(true)
|
|
|
})
|
|
|
|
|
|
test("synthesizes flat operation IDs from methods and paths", () => {
|
|
|
@@ -305,7 +300,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
"deleteUsersById",
|
|
|
"getOrganizationsByOrganizationidUsersById",
|
|
|
]) {
|
|
|
- expect(Tool.isDefinition(toolAt(tools, path))).toBe(true)
|
|
|
+ expect(Tool.isTool(toolAt(tools, path))).toBe(true)
|
|
|
}
|
|
|
})
|
|
|
|
|
|
@@ -330,7 +325,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
"test",
|
|
|
)
|
|
|
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
expect(inputTypeScript(tool)).toBe("{ limit: number }")
|
|
|
})
|
|
|
|
|
|
@@ -358,8 +353,8 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
})
|
|
|
const search = toolAt(result.tools, "search")
|
|
|
|
|
|
- expect(Tool.isDefinition(search)).toBe(true)
|
|
|
- if (!Tool.isDefinition(search)) throw new Error("search was not generated")
|
|
|
+ expect(Tool.isTool(search)).toBe(true)
|
|
|
+ if (!Tool.isTool(search)) throw new Error("search was not generated")
|
|
|
expect(inputTypeScript(search)).toBe("{ value?: string | null }")
|
|
|
const schema: unknown = search.input
|
|
|
const input = isRecord(schema) ? schema : {}
|
|
|
@@ -397,14 +392,14 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
"test",
|
|
|
)
|
|
|
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.output)) throw new Error("test output was not generated")
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.output)) throw new Error("test output was not generated")
|
|
|
expect(tool.output.$defs).toMatchObject({ Local: { type: "string" }, Global: { type: "number" } })
|
|
|
})
|
|
|
|
|
|
test("projects read-only and write-only properties by schema direction", () => {
|
|
|
for (const version of ["3.0.3", "3.1.0"]) {
|
|
|
const tool = toolAt(OpenAPI.fromSpec({ baseUrl, spec: directionalSpec(version) }).tools, "users.create")
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.input) || !isRecord(tool.output)) {
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.input) || !isRecord(tool.output)) {
|
|
|
throw new Error(`users.create was not generated for OpenAPI ${version}`)
|
|
|
}
|
|
|
|
|
|
@@ -467,7 +462,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
expect(inputTypeScript(tool)).toBe("{ name: string }")
|
|
|
})
|
|
|
@@ -518,7 +513,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
const properties = isRecord(tool.input.properties) ? tool.input.properties : {}
|
|
|
const record = isRecord(properties.record) ? properties.record : {}
|
|
|
const definitions = isRecord(tool.input.$defs) ? tool.input.$defs : {}
|
|
|
@@ -567,7 +562,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
expect(inputTypeScript(tool)).toBe("{ name: string }")
|
|
|
})
|
|
|
@@ -607,7 +602,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
const definitions = isRecord(tool.input.$defs) ? tool.input.$defs : {}
|
|
|
const node = isRecord(definitions.Node) ? definitions.Node : {}
|
|
|
|
|
|
@@ -648,7 +643,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
const definitions = isRecord(tool.input.$defs) ? tool.input.$defs : {}
|
|
|
const leaf = isRecord(definitions[`C${depth - 1}`]) ? definitions[`C${depth - 1}`] : {}
|
|
|
|
|
|
@@ -686,7 +681,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
expect(inputTypeScript(tool)).toBe("{ name: string }")
|
|
|
}
|
|
|
@@ -725,7 +720,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
const properties = isRecord(tool.input.properties) ? tool.input.properties : {}
|
|
|
const record: Record<string, unknown> = isRecord(properties.record) ? properties.record : {}
|
|
|
|
|
|
@@ -763,7 +758,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
const properties = isRecord(tool.input.properties) ? tool.input.properties : {}
|
|
|
const choice: Record<string, unknown> = isRecord(properties.choice) ? properties.choice : {}
|
|
|
const pick: Record<string, unknown> = isRecord(properties.pick) ? properties.pick : {}
|
|
|
@@ -807,7 +802,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
const properties = isRecord(tool.input.properties) ? tool.input.properties : {}
|
|
|
const record = isRecord(properties.record) ? properties.record : {}
|
|
|
|
|
|
@@ -836,7 +831,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
expect(inputTypeScript(tool)).toBe("{ filter: { state: string } }")
|
|
|
})
|
|
|
@@ -866,7 +861,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
expect(inputTypeScript(tool)).toBe("{ filter: { value: string } }")
|
|
|
})
|
|
|
@@ -901,7 +896,7 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool) || !isRecord(tool.input)) throw new Error("test was not generated")
|
|
|
const properties = isRecord(tool.input.properties) ? tool.input.properties : {}
|
|
|
const body = isRecord(properties.body) ? properties.body : {}
|
|
|
const allOf = Array.isArray(body.allOf) ? body.allOf : []
|
|
|
@@ -923,11 +918,11 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}),
|
|
|
)
|
|
|
const tool = toolAt(OpenAPI.fromSpec({ baseUrl, spec: directionalSpec("3.1.0") }).tools, "users.create")
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("users.create was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("users.create was not generated")
|
|
|
|
|
|
const result = await Effect.runPromise(
|
|
|
tool
|
|
|
- .run({
|
|
|
+ .execute({
|
|
|
id: "ignored-top-level",
|
|
|
generated: "ignored-generated",
|
|
|
name: "Ada",
|
|
|
@@ -1022,10 +1017,12 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
test("serializes deep-object query parameters from the opencode fixture", async () => {
|
|
|
const client = recordingClient(() => json({ directory: "/tmp" }))
|
|
|
const location = toolAt(OpenAPI.fromSpec({ spec: await opencodeSpec(), baseUrl }).tools, "v2.location.get")
|
|
|
- if (!Tool.isDefinition(location)) throw new Error("v2.location.get was not generated")
|
|
|
+ if (!Tool.isTool(location)) throw new Error("v2.location.get was not generated")
|
|
|
|
|
|
await Effect.runPromise(
|
|
|
- location.run({ location: { directory: "/tmp", workspace: "workspace-1" } }).pipe(Effect.provide(client.layer)),
|
|
|
+ location
|
|
|
+ .execute({ location: { directory: "/tmp", workspace: "workspace-1" } })
|
|
|
+ .pipe(Effect.provide(client.layer)),
|
|
|
)
|
|
|
|
|
|
const url = new URL(client.requests[0]!.url)
|
|
|
@@ -1058,11 +1055,11 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
},
|
|
|
})
|
|
|
const tool = toolAt(result.tools, "items")
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("items was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("items was not generated")
|
|
|
|
|
|
await Effect.runPromise(
|
|
|
tool
|
|
|
- .run({
|
|
|
+ .execute({
|
|
|
keys: ["a!", "b*"],
|
|
|
tags: ["x", "y"],
|
|
|
filter: { state: "open", page: 2 },
|
|
|
@@ -1081,9 +1078,9 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
expect(url.searchParams.get("nullable")).toBe("null")
|
|
|
expect(url.searchParams.get("constructor")).toBe("safe")
|
|
|
expect(client.requests[0]!.headers.meta).toBe("a=b,c=d")
|
|
|
- await expect(Effect.runPromise(tool.run({ keys: [undefined] }).pipe(Effect.provide(client.layer)))).rejects.toThrow(
|
|
|
- "unsupported nested value",
|
|
|
- )
|
|
|
+ await expect(
|
|
|
+ Effect.runPromise(tool.execute({ keys: [undefined] }).pipe(Effect.provide(client.layer))),
|
|
|
+ ).rejects.toThrow("unsupported nested value")
|
|
|
})
|
|
|
|
|
|
test("preserves ordered exploded and deep-object query parameters", async () => {
|
|
|
@@ -1101,11 +1098,11 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
await Effect.runPromise(
|
|
|
tool
|
|
|
- .run({
|
|
|
+ .execute({
|
|
|
tags: ["first value", "second&value"],
|
|
|
filter: { state: "open now", page: 2 },
|
|
|
location: { directory: "/tmp/a b", workspace: "work&1" },
|
|
|
@@ -1116,14 +1113,14 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
expect(client.requests[0]?.url).toBe(
|
|
|
`${baseUrl}/test?tags=first+value&tags=second%26value&state=open+now&page=2&location%5Bdirectory%5D=%2Ftmp%2Fa+b&location%5Bworkspace%5D=work%261`,
|
|
|
)
|
|
|
- await expect(Effect.runPromise(tool.run({ tags: [{}] }).pipe(Effect.provide(client.layer)))).rejects.toThrow(
|
|
|
+ await expect(Effect.runPromise(tool.execute({ tags: [{}] }).pipe(Effect.provide(client.layer)))).rejects.toThrow(
|
|
|
"Parameter 'tags' contains an unsupported nested value.",
|
|
|
)
|
|
|
await expect(
|
|
|
- Effect.runPromise(tool.run({ filter: { state: {} } }).pipe(Effect.provide(client.layer))),
|
|
|
+ Effect.runPromise(tool.execute({ filter: { state: {} } }).pipe(Effect.provide(client.layer))),
|
|
|
).rejects.toThrow("Query parameter 'filter' contains an unsupported nested value.")
|
|
|
await expect(
|
|
|
- Effect.runPromise(tool.run({ location: { directory: [] } }).pipe(Effect.provide(client.layer))),
|
|
|
+ Effect.runPromise(tool.execute({ location: { directory: [] } }).pipe(Effect.provide(client.layer))),
|
|
|
).rejects.toThrow("Deep-object parameter 'location' contains an unsupported nested value.")
|
|
|
expect(client.requests).toHaveLength(1)
|
|
|
})
|
|
|
@@ -1203,9 +1200,9 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"getTest",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
- await Effect.runPromise(tool.run({}).pipe(Effect.provide(client.layer)))
|
|
|
+ await Effect.runPromise(tool.execute({}).pipe(Effect.provide(client.layer)))
|
|
|
|
|
|
expect(inputTypeScript(tool)).toBe("{}")
|
|
|
expect(client.requests[0]!.headers.authorization).toBe("Bearer secret")
|
|
|
@@ -1240,9 +1237,9 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
authenticated([{ key: [] }], { key: { type: "apiKey", in: "query", name: "__proto__" } }).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(prototype)) throw new Error("prototype auth tool was not generated")
|
|
|
+ if (!Tool.isTool(prototype)) throw new Error("prototype auth tool was not generated")
|
|
|
|
|
|
- await Effect.runPromise(prototype.run({}).pipe(Effect.provide(client.layer)))
|
|
|
+ await Effect.runPromise(prototype.execute({}).pipe(Effect.provide(client.layer)))
|
|
|
expect(new URL(client.requests[0]!.url).searchParams.get("__proto__")).toBe("secret")
|
|
|
|
|
|
const duplicate = toolAt(
|
|
|
@@ -1252,8 +1249,8 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(duplicate)) throw new Error("duplicate auth tool was not generated")
|
|
|
- await expect(Effect.runPromise(duplicate.run({}).pipe(Effect.provide(client.layer)))).rejects.toThrow(
|
|
|
+ if (!Tool.isTool(duplicate)) throw new Error("duplicate auth tool was not generated")
|
|
|
+ await expect(Effect.runPromise(duplicate.execute({}).pipe(Effect.provide(client.layer)))).rejects.toThrow(
|
|
|
"multiple credentials",
|
|
|
)
|
|
|
|
|
|
@@ -1278,8 +1275,8 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
},
|
|
|
})
|
|
|
const alternativeTool = toolAt(alternative.tools, "test")
|
|
|
- if (!Tool.isDefinition(alternativeTool)) throw new Error("supported auth alternative was not generated")
|
|
|
- await Effect.runPromise(alternativeTool.run({}).pipe(Effect.provide(client.layer)))
|
|
|
+ if (!Tool.isTool(alternativeTool)) throw new Error("supported auth alternative was not generated")
|
|
|
+ await Effect.runPromise(alternativeTool.execute({}).pipe(Effect.provide(client.layer)))
|
|
|
expect(client.requests.at(-1)?.headers.authorization).toBe("Bearer secret")
|
|
|
})
|
|
|
|
|
|
@@ -1290,9 +1287,9 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
servers: [{ url: "https://document.example" }],
|
|
|
} satisfies Document
|
|
|
const tool = toolAt(OpenAPI.fromSpec({ spec }).tools, "test")
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
- await Effect.runPromise(tool.run({}).pipe(Effect.provide(client.layer)))
|
|
|
+ await Effect.runPromise(tool.execute({}).pipe(Effect.provide(client.layer)))
|
|
|
expect(client.requests[0]?.url).toBe("https://operation.example/v1/test")
|
|
|
|
|
|
const invalid = OpenAPI.fromSpec({ spec, baseUrl: "https://example.com/api?tenant=one" })
|
|
|
@@ -1363,10 +1360,10 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
await expect(
|
|
|
- Effect.runPromise(tool.run({ filter: { value: undefined } }).pipe(Effect.provide(client.layer))),
|
|
|
+ Effect.runPromise(tool.execute({ filter: { value: undefined } }).pipe(Effect.provide(client.layer))),
|
|
|
).rejects.toThrow("unsupported nested value")
|
|
|
expect(resolutions).toEqual([])
|
|
|
expect(client.requests).toEqual([])
|
|
|
@@ -1389,33 +1386,33 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
}).tools,
|
|
|
"test",
|
|
|
)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
|
|
|
- await Effect.runPromise(tool.run({ body: { name: "updated" } }).pipe(Effect.provide(client.layer)))
|
|
|
+ await Effect.runPromise(tool.execute({ body: { name: "updated" } }).pipe(Effect.provide(client.layer)))
|
|
|
expect(client.requests[0]!.headers["content-type"]).toBe("application/merge-patch+json")
|
|
|
const cyclic: Record<string, unknown> = {}
|
|
|
cyclic.self = cyclic
|
|
|
- await expect(Effect.runPromise(tool.run({ body: cyclic }).pipe(Effect.provide(client.layer)))).rejects.toThrow(
|
|
|
+ await expect(Effect.runPromise(tool.execute({ body: cyclic }).pipe(Effect.provide(client.layer)))).rejects.toThrow(
|
|
|
"Invalid JSON body",
|
|
|
)
|
|
|
})
|
|
|
|
|
|
test("rejects oversized and malformed JSON responses", async () => {
|
|
|
const tool = toolAt(OpenAPI.fromSpec({ baseUrl, spec: singleOperation({}) }).tools, "test")
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
const oversized = recordingClient(
|
|
|
() => new Response(null, { headers: { "content-length": String(50 * 1024 * 1024 + 1) } }),
|
|
|
)
|
|
|
const malformed = recordingClient(() => new Response("{", { headers: { "content-type": "application/json" } }))
|
|
|
const chunked = recordingClient(() => new Response(new Uint8Array(50 * 1024 * 1024 + 1)))
|
|
|
|
|
|
- await expect(Effect.runPromise(tool.run({}).pipe(Effect.provide(oversized.layer)))).rejects.toThrow(
|
|
|
+ await expect(Effect.runPromise(tool.execute({}).pipe(Effect.provide(oversized.layer)))).rejects.toThrow(
|
|
|
"response exceeds 50 MiB",
|
|
|
)
|
|
|
- await expect(Effect.runPromise(tool.run({}).pipe(Effect.provide(malformed.layer)))).rejects.toThrow(
|
|
|
+ await expect(Effect.runPromise(tool.execute({}).pipe(Effect.provide(malformed.layer)))).rejects.toThrow(
|
|
|
"returned malformed JSON",
|
|
|
)
|
|
|
- await expect(Effect.runPromise(tool.run({}).pipe(Effect.provide(chunked.layer)))).rejects.toThrow(
|
|
|
+ await expect(Effect.runPromise(tool.execute({}).pipe(Effect.provide(chunked.layer)))).rejects.toThrow(
|
|
|
"response exceeds 50 MiB",
|
|
|
)
|
|
|
})
|
|
|
@@ -1428,11 +1425,11 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
},
|
|
|
})
|
|
|
const tool = toolAt(OpenAPI.fromSpec({ baseUrl, spec }).tools, "test")
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error("test was not generated")
|
|
|
+ if (!Tool.isTool(tool)) throw new Error("test was not generated")
|
|
|
const client = recordingClient(() => new Response("123", { headers: { "content-type": "text/plain" } }))
|
|
|
|
|
|
expect(outputTypeScript(tool)).toBe("string | null")
|
|
|
- await expect(Effect.runPromise(tool.run({}).pipe(Effect.provide(client.layer)))).resolves.toBe("123")
|
|
|
+ await expect(Effect.runPromise(tool.execute({}).pipe(Effect.provide(client.layer)))).resolves.toBe("123")
|
|
|
})
|
|
|
|
|
|
test("fails missing required parameters before auth and network", async () => {
|
|
|
@@ -1497,13 +1494,13 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
const update = toolAt(tools, "things.update")
|
|
|
const echo = toolAt(tools, "echo")
|
|
|
|
|
|
- expect(Tool.isDefinition(update)).toBe(true)
|
|
|
- if (!Tool.isDefinition(update)) throw new Error("things.update was not generated")
|
|
|
+ expect(Tool.isTool(update)).toBe(true)
|
|
|
+ if (!Tool.isTool(update)) throw new Error("things.update was not generated")
|
|
|
expect(inputTypeScript(update)).toBe(
|
|
|
"{ path_id: string; query_id: string; path_id_2?: string; header_id: string; body_id: string }",
|
|
|
)
|
|
|
- expect(Tool.isDefinition(echo)).toBe(true)
|
|
|
- if (!Tool.isDefinition(echo)) throw new Error("echo was not generated")
|
|
|
+ expect(Tool.isTool(echo)).toBe(true)
|
|
|
+ if (!Tool.isTool(echo)) throw new Error("echo was not generated")
|
|
|
expect(inputTypeScript(echo)).toBe("{ body: string }")
|
|
|
|
|
|
const runtime = CodeMode.make({ tools })
|
|
|
@@ -1584,13 +1581,13 @@ describe("OpenAPI.fromSpec", () => {
|
|
|
|
|
|
for (const name of ["optional", "dictionary", "composed", "nullable"]) {
|
|
|
const tool = toolAt(tools, `body.${name}`)
|
|
|
- expect(Tool.isDefinition(tool)).toBe(true)
|
|
|
- if (!Tool.isDefinition(tool)) throw new Error(`body.${name} was not generated`)
|
|
|
+ expect(Tool.isTool(tool)).toBe(true)
|
|
|
+ if (!Tool.isTool(tool)) throw new Error(`body.${name} was not generated`)
|
|
|
const input = isRecord(tool.input) ? tool.input : {}
|
|
|
expect(Object.keys(isRecord(input.properties) ? input.properties : {})).toStrictEqual(["body"])
|
|
|
}
|
|
|
const optional = toolAt(tools, "body.optional")
|
|
|
- if (!Tool.isDefinition(optional)) throw new Error("body.optional was not generated")
|
|
|
+ if (!Tool.isTool(optional)) throw new Error("body.optional was not generated")
|
|
|
expect(inputTypeScript(optional)).toBe("{ body?: { name: string } }")
|
|
|
})
|
|
|
})
|