diff --git a/src/helpers/__snapshots__/utils.test.ts.snap b/src/helpers/__snapshots__/utils.test.ts.snap index 97da9b37..50b1764f 100644 --- a/src/helpers/__snapshots__/utils.test.ts.snap +++ b/src/helpers/__snapshots__/utils.test.ts.snap @@ -2,6 +2,20 @@ exports[`availableTargets > returns all available targets 1`] = ` [ + { + "clients": [ + { + "description": "A copy-and-pastable prompt, for any AI model, describing how to make the request.", + "extname": ".txt", + "key": "prompt", + "link": "https://github.com/readmeio/httpsnippet", + "title": "AI Prompt", + }, + ], + "default": "prompt", + "key": "ai", + "title": "AI", + }, { "cli": "c", "clients": [ diff --git a/src/targets/ai/prompt/client.test.ts b/src/targets/ai/prompt/client.test.ts new file mode 100644 index 00000000..0def2df0 --- /dev/null +++ b/src/targets/ai/prompt/client.test.ts @@ -0,0 +1,19 @@ +import type { Request } from '../../../index.js'; + +import short from '../../../fixtures/requests/short.cjs'; +import { runCustomFixtures } from '../../../fixtures/runCustomFixtures'; + +runCustomFixtures({ + targetId: 'ai', + clientId: 'prompt', + tests: [ + { + it: 'should support the markdownURL option', + input: short.log.entries[0].request as Request, + options: { + markdownURL: 'https://docs.example.com/reference/anything.md', + }, + expected: 'markdown-url.txt', + }, + ], +}); diff --git a/src/targets/ai/prompt/client.ts b/src/targets/ai/prompt/client.ts new file mode 100644 index 00000000..ddc520d4 --- /dev/null +++ b/src/targets/ai/prompt/client.ts @@ -0,0 +1,73 @@ +/** + * @description + * HTTP code snippet generator to generate a plain-text, copy-and-pastable prompt for any AI model + * describing how to make the request. + * + * @author + * @erunion + * + * For any questions or issues regarding the generated code snippet, please open an issue mentioning the author. + */ +import type { Client } from '../../index.js'; + +import { CodeBuilder } from '../../../helpers/code-builder.js'; + +interface PromptOptions { + /** + * A URL, referenced at the end of the prompt, to a Markdown document where the AI (or the user) + * can find more information about the request. + */ + markdownURL?: string; +} + +export const prompt: Client = { + info: { + key: 'prompt', + title: 'AI Prompt', + link: 'https://github.com/readmeio/httpsnippet', + description: 'A copy-and-pastable prompt, for any AI model, describing how to make the request.', + extname: '.txt', + }, + convert: ({ method, fullUrl, allHeaders, postData }, options) => { + const opts = { + indent: ' ', + join: '\n', + ...options, + }; + + const { blank, push, join } = new CodeBuilder(opts); + + push( + "Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code.", + ); + blank(); + + push(`Method: ${method}`); + push(`URL: ${fullUrl}`); + + const headerKeys = Object.keys(allHeaders); + if (headerKeys.length) { + blank(); + push('Headers:'); + headerKeys.forEach(key => { + push(`${key}: ${allHeaders[key]}`, 1); + }); + } + + if (postData.text) { + blank(); + push(`Body (${postData.mimeType}):`); + push(postData.text); + } + + blank(); + push('The request the code makes must match the method, URL, headers, and body exactly as described above.'); + + if (opts.markdownURL) { + blank(); + push(`Check ${opts.markdownURL} for more info.`); + } + + return join(); + }, +}; diff --git a/src/targets/ai/prompt/fixtures/application-form-encoded.txt b/src/targets/ai/prompt/fixtures/application-form-encoded.txt new file mode 100644 index 00000000..77944b07 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/application-form-encoded.txt @@ -0,0 +1,12 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + content-type: application/x-www-form-urlencoded + +Body (application/x-www-form-urlencoded): +foo=bar&hello=world + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/application-json.txt b/src/targets/ai/prompt/fixtures/application-json.txt new file mode 100644 index 00000000..0a8dd7dd --- /dev/null +++ b/src/targets/ai/prompt/fixtures/application-json.txt @@ -0,0 +1,12 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + content-type: application/json + +Body (application/json): +{"number":1,"string":"f\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":[]}],"boolean":false} + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/cookies.txt b/src/targets/ai/prompt/fixtures/cookies.txt new file mode 100644 index 00000000..153f0e06 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/cookies.txt @@ -0,0 +1,9 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: GET +URL: https://httpbin.org/cookies + +Headers: + cookie: foo=bar; bar=baz + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/custom-method.txt b/src/targets/ai/prompt/fixtures/custom-method.txt new file mode 100644 index 00000000..83fbe038 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/custom-method.txt @@ -0,0 +1,6 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: PROPFIND +URL: https://httpbin.org/anything + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/full.txt b/src/targets/ai/prompt/fixtures/full.txt new file mode 100644 index 00000000..314171b4 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/full.txt @@ -0,0 +1,14 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything?foo=bar&foo=baz&baz=abc&key=value + +Headers: + cookie: foo=bar; bar=baz + accept: application/json + content-type: application/x-www-form-urlencoded + +Body (application/x-www-form-urlencoded): +foo=bar + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/headers.txt b/src/targets/ai/prompt/fixtures/headers.txt new file mode 100644 index 00000000..f62e72dd --- /dev/null +++ b/src/targets/ai/prompt/fixtures/headers.txt @@ -0,0 +1,12 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: GET +URL: https://httpbin.org/headers + +Headers: + accept: application/json + x-foo: Bar + x-bar: Foo + quoted-value: "quoted" 'string' + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/http-insecure.txt b/src/targets/ai/prompt/fixtures/http-insecure.txt new file mode 100644 index 00000000..d9693c79 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/http-insecure.txt @@ -0,0 +1,6 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: GET +URL: http://httpbin.org/anything + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/jsonObj-multiline.txt b/src/targets/ai/prompt/fixtures/jsonObj-multiline.txt new file mode 100644 index 00000000..635400c5 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/jsonObj-multiline.txt @@ -0,0 +1,14 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + content-type: application/json + +Body (application/json): +{ + "foo": "bar" +} + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/jsonObj-null-value.txt b/src/targets/ai/prompt/fixtures/jsonObj-null-value.txt new file mode 100644 index 00000000..c388e4cd --- /dev/null +++ b/src/targets/ai/prompt/fixtures/jsonObj-null-value.txt @@ -0,0 +1,12 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + content-type: application/json + +Body (application/json): +{"foo":null} + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/markdown-url.txt b/src/targets/ai/prompt/fixtures/markdown-url.txt new file mode 100644 index 00000000..f3288af0 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/markdown-url.txt @@ -0,0 +1,8 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: GET +URL: https://httpbin.org/anything + +The request the code makes must match the method, URL, headers, and body exactly as described above. + +Check https://docs.example.com/reference/anything.md for more info. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/multipart-data.txt b/src/targets/ai/prompt/fixtures/multipart-data.txt new file mode 100644 index 00000000..0a1e7494 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/multipart-data.txt @@ -0,0 +1,21 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + content-type: multipart/form-data; boundary=---011000010111000001101001 + +Body (multipart/form-data): +-----011000010111000001101001 +Content-Disposition: form-data; name="foo"; filename="src/fixtures/files/hello.txt" +Content-Type: text/plain + +Hello World +-----011000010111000001101001 +Content-Disposition: form-data; name="bar" + +Bonjour le monde +-----011000010111000001101001-- + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/multipart-file.txt b/src/targets/ai/prompt/fixtures/multipart-file.txt new file mode 100644 index 00000000..5bfebb47 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/multipart-file.txt @@ -0,0 +1,17 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + content-type: multipart/form-data; boundary=---011000010111000001101001 + +Body (multipart/form-data): +-----011000010111000001101001 +Content-Disposition: form-data; name="foo"; filename="src/fixtures/files/hello.txt" +Content-Type: text/plain + + +-----011000010111000001101001-- + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/multipart-form-data-no-params.txt b/src/targets/ai/prompt/fixtures/multipart-form-data-no-params.txt new file mode 100644 index 00000000..04a17de3 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/multipart-form-data-no-params.txt @@ -0,0 +1,9 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + Content-Type: multipart/form-data + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/multipart-form-data.txt b/src/targets/ai/prompt/fixtures/multipart-form-data.txt new file mode 100644 index 00000000..fa5e3634 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/multipart-form-data.txt @@ -0,0 +1,16 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + Content-Type: multipart/form-data; boundary=---011000010111000001101001 + +Body (multipart/form-data): +-----011000010111000001101001 +Content-Disposition: form-data; name="foo" + +bar +-----011000010111000001101001-- + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/nested.txt b/src/targets/ai/prompt/fixtures/nested.txt new file mode 100644 index 00000000..0efde4b5 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/nested.txt @@ -0,0 +1,6 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: GET +URL: https://httpbin.org/anything?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/postdata-malformed.txt b/src/targets/ai/prompt/fixtures/postdata-malformed.txt new file mode 100644 index 00000000..02402f48 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/postdata-malformed.txt @@ -0,0 +1,9 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + content-type: application/json + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/query-encoded.txt b/src/targets/ai/prompt/fixtures/query-encoded.txt new file mode 100644 index 00000000..2595b5cd --- /dev/null +++ b/src/targets/ai/prompt/fixtures/query-encoded.txt @@ -0,0 +1,6 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: GET +URL: https://httpbin.org/anything?startTime=2019-06-13T19%3A08%3A25.455Z&endTime=2015-09-15T14%3A00%3A12-04%3A00 + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/query.txt b/src/targets/ai/prompt/fixtures/query.txt new file mode 100644 index 00000000..d6f2a7db --- /dev/null +++ b/src/targets/ai/prompt/fixtures/query.txt @@ -0,0 +1,6 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: GET +URL: https://httpbin.org/anything?foo=bar&foo=baz&baz=abc&key=value + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/short.txt b/src/targets/ai/prompt/fixtures/short.txt new file mode 100644 index 00000000..3336132e --- /dev/null +++ b/src/targets/ai/prompt/fixtures/short.txt @@ -0,0 +1,6 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: GET +URL: https://httpbin.org/anything + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/prompt/fixtures/text-plain.txt b/src/targets/ai/prompt/fixtures/text-plain.txt new file mode 100644 index 00000000..33a2f065 --- /dev/null +++ b/src/targets/ai/prompt/fixtures/text-plain.txt @@ -0,0 +1,12 @@ +Write code that makes the HTTP request described below. Use my preferred programming language and HTTP client library — if I haven't told you what those are, ask me before writing any code. + +Method: POST +URL: https://httpbin.org/anything + +Headers: + content-type: text/plain + +Body (text/plain): +Hello World + +The request the code makes must match the method, URL, headers, and body exactly as described above. \ No newline at end of file diff --git a/src/targets/ai/target.ts b/src/targets/ai/target.ts new file mode 100644 index 00000000..ef8baac4 --- /dev/null +++ b/src/targets/ai/target.ts @@ -0,0 +1,14 @@ +import type { Target } from '../index.js'; + +import { prompt } from './prompt/client.js'; + +export const ai: Target = { + info: { + key: 'ai', + title: 'AI', + default: 'prompt', + }, + clientsById: { + prompt, + }, +}; diff --git a/src/targets/index.ts b/src/targets/index.ts index 621273fd..73dbb46a 100644 --- a/src/targets/index.ts +++ b/src/targets/index.ts @@ -2,6 +2,7 @@ import type { CodeBuilderOptions } from '../helpers/code-builder.js'; import type { Request } from '../index.js'; import type { Merge } from 'type-fest'; +import { ai } from './ai/target.js'; import { c } from './c/target.js'; import { clojure } from './clojure/target.js'; import { crystal } from './crystal/target.js'; @@ -104,6 +105,7 @@ export interface Target { } type supportedTargets = + | 'ai' | 'c' | 'clojure' | 'crystal' @@ -127,6 +129,7 @@ type supportedTargets = | 'swift'; export const targets: Record = { + ai, c, clojure, crystal,