diff --git a/cli/index.js b/cli/index.js index 5e9885c..c8d029c 100755 --- a/cli/index.js +++ b/cli/index.js @@ -2,6 +2,7 @@ import { Claude } from '../index.js'; import inquirer from 'inquirer'; +import readline from 'readline' import chalk from 'chalk'; import ora from 'ora'; import * as marked from 'marked'; @@ -16,6 +17,7 @@ import "isomorphic-fetch"; import { File } from "@web-std/file"; import { exec } from 'child_process'; import open from 'open'; +import fetch from './tls.js'; marked.setOptions({ headerIds: false, mangle: false }) marked.setOptions({ @@ -116,7 +118,7 @@ const WELCOME_MESSAGE = chalk.bold.green('Welcome to the Claude CLI!'); let MODEL = 'claude-2' const claude = new Claude({ sessionKey: getKey(), - fetch: globalThis.fetch + fetch: fetch, }); async function main() { @@ -782,7 +784,6 @@ async function getPrompt(template, variables = {}) { } catch (e) { return { value: '', body: '' }; } - console.log("GOT SHELL RESULT", { result }); if (['shd', 'shelld', 'shelldisplay'].includes(command)) { return { value: result, @@ -795,12 +796,28 @@ async function getPrompt(template, variables = {}) { } } if (command === 'js' || ['jsdisplay', 'jsd'].includes(command)) { + if (SPINNER) { SPINNER.stop() } let pr; const BLACKLIST = ['void', 'var', 'let', 'const', 'private', 'public', 'window', 'body', 'document', 'globalThis', 'globals', 'import', 'class', 'async', 'function', 'this', 'return', 'yield', 'throw', 'catch', 'break', 'case', 'continue', 'default', 'do', 'else', 'finally', 'if', 'in', 'return', 'switch', 'throw', 'try', 'while', 'with', 'yield']; let p = new Promise(resolve => (pr = resolve)); - const EVAL_STR = (`((async ({${Object.keys(variables).filter(i => !BLACKLIST.includes(i)).join(', ')}}) => { - ${arg.split('\n').length === 1 ? `return ${arg}` : arg} - })(${JSON.stringify(variables)})).then(result => { + const ask = (q) => { + return new Promise(resolve => { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }) + rl.question(q, (a) => { + resolve(a); + }) + }) + } + const EVAL_STR = (` + const tempFunc = async ({${Object.keys(variables).filter(i => !BLACKLIST.includes(i)).join(', ')}}) => { + ${arg.split('\n').length === 1 ? `return ${arg}` : arg} + } + debugger; + tempFunc(${JSON.stringify({ variables })}).then(result => { + debugger; pr(result); })`); eval(EVAL_STR); diff --git a/cli/package.json b/cli/package.json index ffae2ef..9be790b 100644 --- a/cli/package.json +++ b/cli/package.json @@ -17,6 +17,7 @@ "@web-std/file": "^3.0.2", "chalk": "^5.3.0", "claude-ai": "^1.2.0", + "cycletls": "^1.0.21", "dotenv": "^16.3.1", "inquirer": "^9.2.7", "isomorphic-fetch": "^3.0.0", diff --git a/cli/pnpm-lock.yaml b/cli/pnpm-lock.yaml index 30816d0..41ecaed 100644 --- a/cli/pnpm-lock.yaml +++ b/cli/pnpm-lock.yaml @@ -14,6 +14,9 @@ dependencies: claude-ai: specifier: ^1.2.0 version: 1.2.0 + cycletls: + specifier: ^1.0.21 + version: 1.0.21 dotenv: specifier: ^16.3.1 version: 16.3.1 @@ -76,6 +79,10 @@ packages: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: false + /@types/node@17.0.45: + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + dev: false + /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: false @@ -342,6 +349,16 @@ packages: which: 2.0.2 dev: false + /cycletls@1.0.21: + resolution: {integrity: sha512-Ccox1s+3mhoc/SOlzAXH2EqyKPc3PlJ6WVvshgzBn99ihDSmp/GQJqPw7TKBLO5pJMZtrl9B7s8cMdrwOoORbQ==} + dependencies: + '@types/node': 17.0.45 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + /decamelize-keys@2.0.1: resolution: {integrity: sha512-nrNeSCtU2gV3Apcmn/EZ+aR20zKDuNDStV67jPiupokD3sOAFeMzslLMCFdKv1sPqzwoe5ZUhsSW9IAVgKSL/Q==} engines: {node: '>=14.16'} @@ -1360,6 +1377,19 @@ packages: strip-ansi: 6.0.1 dev: false + /ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: false diff --git a/cli/templates/code.txt b/cli/templates/code.txt index ee3da6d..d945a99 100644 --- a/cli/templates/code.txt +++ b/cli/templates/code.txt @@ -1,10 +1,10 @@ You are an expert software engineer at Google. Be concise! Your job is to implement the code designed and detailed in the uploaded file requirements.txt. This project is {prompt} -Make sure to use the latest syntax (e.g. ESM/ES6 imports and syntax in JavaScript, HTML5, CSS3), don't include debug or comments or empty lines. Include error handling to make sure it works properly. Make sure your code is readable and does not include any placeholders or psuedocode. +Make sure to use the latest syntax (e.g., ESM/ES6 imports and syntax in JavaScript, HTML5, CSS3), don't include debug or comments or empty lines. Include error handling to make sure it works properly. Make sure your code is readable and does not include any placeholders or pseudocode. -DONT INCLUDE ANY TODO COMMENTS. DONT INCLUDE PSUEDOCODE. DONT INCLUDE PLACEHOLDERS. Adhere to the user's request as closely as possible. Your code's output, variables and function should match the example output given in the design document exactly. +DON'T INCLUDE ANY TODO COMMENTS. DON'T INCLUDE PSUEDOCODE. DON'T INCLUDE PLACEHOLDERS. Adhere to the user's request as closely as possible. Your code's output, variables, and function should match the example output given in the design document exactly. -First write you initial implementation of the requirements, then write out 4 criticisms of it. Finally write your final code. Begin the final code with "FINAL:" +First write your initial implementation of the requirements, then write out 4 criticisms of it. Finally, write your final code. Begin the final code with "FINAL:" The requirements and design details of this project are located in the uploaded file requirements.txt diff --git a/cli/templates/flashcards.txt b/cli/templates/flashcards.txt index 0d15197..6fdb710 100644 --- a/cli/templates/flashcards.txt +++ b/cli/templates/flashcards.txt @@ -1,1068 +1,16 @@ -Generate flashcards and questions about {prompt} in the following format: +Generate markdown flashcards and questions about {prompt} in the following format: -``` -# Topic header +- Front :: back +- Reversable front ::: back -front : back - note attached indented by 2 spaces and will be shown after the flip side of the flashcard is revealed while practicing -``` +_Note: Flashcards are just markdown bullet points_ -Example with 2 flashcards and a topic header: -``` -# Cognitive biases - From https://www.titlemax.com/discovery-center/lifestyle/50-cognitive-biases-to-be-aware-of-so-you-can-be-the-very-best-version-of-you/ +Example -Fundamental Attribution Error: We judge others on their personality or fundamental character, but we judge ourselves on the situation. - Example: “Sally is late to class; she's lazy. You're late to class; it was a bad morning.” -Self-Serving Bias: Our failures are situational but our successes are our responsibility. - Example: “You won that award due to hard work rather than help or luck. Meanwhile, you failed a test because you hadn't gotten enough sleep.” -``` +## Terms +- Stoichiometry Definition::The study of quantitative relationships between reactants and products in a chemical reaction +- Quantitative Relationships:::Numerical connections between the amounts of substances involved in a reaction. -Your flashcards -Now generate 15 flashcards about {prompt}. Refer to transcript.txt for lesson transcript. Put your result in a code block. +_Note: Quantitative relationships card contains ":::" instead of "::" to signify that it can be studied reverse order, e.g. the back is shown, then the front_ -{#file transcript.txt} -WEBVTT FILE - -1 -00:00:11.339 --> 00:00:15.630 -Howdy and welcome back. This time we're -going to talk about a little bit more - -2 -00:00:15.630 --> 00:00:19.579 -naming than we did the last session. -We're going to talk this time about Covalin - -3 -00:00:19.579 --> 00:00:24.039 -compounds in about acids. So last -time we did ionic compounds. This time - -4 -00:00:24.039 --> 00:00:28.070 -we're going to do compounds that have -Covalin Bonds. What we're going to look - -5 -00:00:28.070 --> 00:00:32.060 -at this point is just looking at -the names and the formulas. A quick review. - -6 -00:00:32.070 --> 00:00:35.409 -I might throw some terms out there -that you might not remember, and that's - -7 -00:00:35.409 --> 00:00:39.189 -okay, because they're not really important -for this unit. But the more you - -8 -00:00:39.189 --> 00:00:43.460 -can hear things, the better off you will -be later on. So let's take a look - -9 -00:00:43.469 --> 00:00:47.700 -at first of all, just how we want -to go ahead and name things when you're - -10 -00:00:47.700 --> 00:00:52.070 -naming Covalin compounds. What we have to -look at here is we're not dealing - -11 -00:00:52.070 --> 00:00:56.990 -with charges anymore. We're dealing with -using prefixes to tell us how many - -12 -00:00:56.990 --> 00:01:04.590 -of each atom we're going to be looking -at. So we have prefixes and the prefixes - -13 -00:01:04.590 --> 00:01:14.110 -are pretty simple. Mono die, try -And here's where they get a little - -14 -00:01:14.110 --> 00:01:21.930 -different for is tetra five is -Penta like pent oxide Whatever you want to - -15 -00:01:21.930 --> 00:01:30.769 -call there Six hex a like a hexagon seven helped. - -16 -00:01:31.940 --> 00:01:41.629 -Eight is Oct like Octagon Like a stop -sign. Nine is non or Nana and 10 - -17 -00:01:41.709 --> 00:01:47.410 -is deck like a deck again 10 sided -figure. Okay, so some of these that kind - -18 -00:01:47.410 --> 00:01:50.310 -of end with a or you can -leave it off, depending upon what you're looking - -19 -00:01:50.310 --> 00:01:54.800 -for. So once you have these prefixes, -what you're looking at is each prefix - -20 -00:01:54.800 --> 00:01:59.230 -just tells you how many of each -Adam you're going to have within your compound - -21 -00:01:59.239 --> 00:02:04.270 -and again, prefix means it's happening -at the beginning of the word. So - -22 -00:02:04.270 --> 00:02:09.750 -when you're naming these compounds, you -have a prefix usually and then the - -23 -00:02:09.750 --> 00:02:15.250 -name of the element and then another -prefix, and then you change the ending - -24 -00:02:15.250 --> 00:02:19.199 -toe. I'd just like we did with -the Ionic Compounds. Let's take a look at - -25 -00:02:19.199 --> 00:02:25.580 -a few examples. So the examples I'm -going to do are actually the examples of - -26 -00:02:25.580 --> 00:02:30.400 -compounds that I've created up here. The -first one that we have is this - -27 -00:02:30.400 --> 00:02:35.910 -one right here. The yellow represents -a sulfur atom, and then the green - -28 -00:02:35.910 --> 00:02:44.860 -ones represent fluoride atoms. So this is -one sulfur, and then we have 123456 - -29 -00:02:45.039 --> 00:02:55.039 -fluoride atoms. So we have s f -six. This one we have one sulfur, six - -30 -00:02:55.039 --> 00:02:59.650 -florins. So the one time that we don't -use a prefix was going to be our very - -31 -00:02:59.650 --> 00:03:04.110 -first example here. We don't use -the prefix mono when you're talking about - -32 -00:03:04.110 --> 00:03:13.960 -the very first element in the system. -So this is just sulfur hex, a fluoride. - -33 -00:03:16.740 --> 00:03:21.610 -Okay, so one sulfur don't need the -prefix here for the first element. And - -34 -00:03:21.610 --> 00:03:26.930 -then six, the prefix hex a and -then fluoride notice we change the florin - -35 -00:03:26.930 --> 00:03:31.080 -to fluoride to be the end of the -word there. All right, let's take a look - -36 -00:03:31.080 --> 00:03:40.910 -at the next one. This particular compound is B F - -37 -00:03:40.920 --> 00:03:47.480 -or B H three. Sorry, It is -a plainer molecule. It's flat, which means it's - -38 -00:03:47.480 --> 00:03:51.650 -it's all in one plane here on -it's a triangle, So it's tribunal plainer. - -39 -00:03:51.660 --> 00:03:57.250 -It's kind of fun to think about it that -way, but the blue one is a B, and - -40 -00:03:57.250 --> 00:04:03.640 -the white ones are h is. So we -have one boron and three hydrogen. So this - -41 -00:04:03.640 --> 00:04:11.170 -is boron. Three is the prefix try. -And then when hydrogen is that second - -42 -00:04:11.170 --> 00:04:17.260 -element there we change it from -hydrogen toe hydride. So boron try hydride. - -43 -00:04:18.940 --> 00:04:26.990 -Let's hit one more example here. -How about water? We want to have something - -44 -00:04:26.990 --> 00:04:30.839 -that doesn't just have a single element in -the front of it. So we have water. - -45 -00:04:30.850 --> 00:04:36.950 -Everybody knows the formula for water. H -20 But the name for water is a - -46 -00:04:36.950 --> 00:04:41.490 -little bit different. So we know water. -That's its common name. But if we - -47 -00:04:41.490 --> 00:04:45.250 -set this thing up and we look at -it, we see that there are two hydrogen - -48 -00:04:45.250 --> 00:04:49.149 -and one oxygen. If we're going to -use the same naming convention that we've - -49 -00:04:49.149 --> 00:04:54.329 -been using, this has a really -different official name than the one we've - -50 -00:04:54.339 --> 00:05:03.490 -been giving it. So this is -to hydrogen. So that's di hydrogen mon - -51 -00:05:03.940 --> 00:05:11.520 -oxide. So there we go. Here's the -word. The mon comes into play. So again - -52 -00:05:11.520 --> 00:05:16.860 -we have a prefix and the word and -then a prefix. And then the word with - -53 -00:05:16.860 --> 00:05:21.850 -that I d. E ending at the end of -it. Let's do one or two going the other - -54 -00:05:21.850 --> 00:05:31.680 -direction. Here's one of my favorites Tetra - -55 -00:05:31.680 --> 00:05:41.410 -phosphorus deck oxide. All right, so -let's take this word apart and see - -56 -00:05:41.410 --> 00:05:45.990 -if we can create the formula from it. -So we have two things going on here. - -57 -00:05:46.000 --> 00:05:55.570 -We have Tetra which means four and -then we know the phosphorus is P. Then - -58 -00:05:55.570 --> 00:06:04.930 -we have deck or Deco. That means 10 and -the oxide is for Oh, so if we take - -59 -00:06:04.930 --> 00:06:12.770 -a look at this whole thing, we can -break everything apart. We get P 40 10. - -60 -00:06:13.240 --> 00:06:16.150 -What's kind of neat about this is when -you take this and you put it into - -61 -00:06:16.150 --> 00:06:23.440 -water. If you take this compound into -water, it turns into H three po four, - -62 -00:06:23.450 --> 00:06:31.360 -which we're going to use as a segue -into Let's talk about some acids. Assets - -63 -00:06:31.360 --> 00:06:38.320 -are pretty neat. So acids are -covalin compounds that in some ways behave - -64 -00:06:38.320 --> 00:06:44.080 -like ionic compounds. This is an example -of an acid. This is nitric acid. - -65 -00:06:44.090 --> 00:06:52.350 -It's h and then n in the middle. And -then 03 So H n 03 this is nitric acid. - -66 -00:06:52.540 --> 00:06:57.200 -What's cool about acids is these -air Allco violently bonded together. But - -67 -00:06:57.200 --> 00:07:02.140 -when I take this thing and I stick -it in the water, it loses this hydrogen - -68 -00:07:02.330 --> 00:07:08.970 -and this hydrogen goes off and attach -is to a water in a different place - -69 -00:07:09.740 --> 00:07:15.220 -to give me a nitrate ion and a -hydro Nia, my on. So you have this weird - -70 -00:07:15.220 --> 00:07:21.430 -chemical reaction where a covalin compound -ends up having a charge. This - -71 -00:07:21.430 --> 00:07:25.670 -becomes the nitrate ion and a three -minus. And this becomes the hydro Nia, - -72 -00:07:25.670 --> 00:07:30.840 -my on h 30 plus, What's kind -of need about these things is because they - -73 -00:07:30.840 --> 00:07:34.260 -have different behaviors. So even though -they're co violent, they have different - -74 -00:07:34.260 --> 00:07:39.420 -behaviors. So they have different naming -schemes to assets are a little - -75 -00:07:39.420 --> 00:07:44.920 -bit more challenging to work with. -All right, our first example with our - -76 -00:07:44.920 --> 00:07:50.140 -acids, we're going to look at our binary -acids. So just like binary ionic compounds - -77 -00:07:50.160 --> 00:07:54.120 -or binary coagulant compounds, we're only -dealing with two kinds of atoms - -78 -00:07:54.120 --> 00:08:01.360 -here. So for our binary acids, what -we're looking at is to write the formula - -79 -00:08:03.740 --> 00:08:09.250 -you're going to use some number of h -is that are going to kind of act as - -80 -00:08:09.250 --> 00:08:13.700 -a positive charge even though there -it's a covalin bond. And then you're - -81 -00:08:13.700 --> 00:08:19.660 -going to pair that with an ion, which, -if you don't remember that is a negative - -82 -00:08:19.660 --> 00:08:28.340 -ion from the periodic table. So these -were going to be things that are non - -83 -00:08:28.340 --> 00:08:34.620 -metals sulfide oxide, fluoride chloride. Any -of those air going to be paired - -84 -00:08:34.620 --> 00:08:38.510 -up here? So that's how we're going to -write the formula you want to balance - -85 -00:08:38.510 --> 00:08:44.090 -out The quote charges when we write -the name for a binary ionic camp are - -86 -00:08:44.090 --> 00:08:49.460 -a binary acid. What we're dealing with -here is you're going to use the prefix - -87 -00:08:49.470 --> 00:08:56.549 -hydro than the root word, and then -you're going to have a Suffolk's IQ and - -88 -00:08:56.549 --> 00:09:01.650 -then the word acid. So hydro something -ic acid. If I just said that your - -89 -00:09:01.650 --> 00:09:05.390 -brain probably went hydrochloric acid because -that's the only one you know, - -90 -00:09:05.400 --> 00:09:08.880 -right, that's the only one that we -always think of. So you might have put - -91 -00:09:08.880 --> 00:09:12.540 -some of that in your pool, or you -might have heard about it from a different - -92 -00:09:12.540 --> 00:09:16.590 -chemistry class. But that's probably the -most common binary acid that we - -93 -00:09:16.590 --> 00:09:22.080 -all hear about. And so let's use -that as our first example. Chloride - -94 -00:09:22.080 --> 00:09:26.880 -ion, if you go back to your periodic -table, is in Group seven, so it has - -95 -00:09:26.880 --> 00:09:33.120 -a negative one charge. Hydrogen can have -either a positive one or a negative - -96 -00:09:33.120 --> 00:09:37.070 -one charge. So since the chloride is -a negative one, that clearly has to - -97 -00:09:37.070 --> 00:09:43.840 -be the positive. And so we have our -compound of HCL, and we use the chloral - -98 -00:09:43.850 --> 00:09:50.960 -components to help fill in the gap -for the name and we have hydro chloral - -99 -00:09:50.960 --> 00:09:58.870 -IQ acid. And there's our first example. Let's do one more. - -100 -00:10:03.140 --> 00:10:09.490 -Let's do hte to s. And I'm going to -make a point about writing a quiz here - -101 -00:10:09.490 --> 00:10:14.510 -after this particular molecule. And the -reason for that is without water - -102 -00:10:14.520 --> 00:10:22.910 -and acid is just a covalin molecule. So -if I had hte us gas, I would call - -103 -00:10:22.910 --> 00:10:32.700 -this di hydrogen sulfide or die -hydrogen mono sulfide is probably more - -104 -00:10:32.700 --> 00:10:37.320 -appropriate. Okay, But as soon as I take -that and I put it into water, it - -105 -00:10:37.320 --> 00:10:41.880 -goes through a chemical reaction and -it dissociates. And so it's behavior - -106 -00:10:41.880 --> 00:10:45.830 -becomes that oven acid. It's different. And -so now when I take a look at - -107 -00:10:45.830 --> 00:10:54.750 -this thing now it's an acid, -and I'm going to say hydro sulfuric - -108 -00:10:55.540 --> 00:11:04.000 -acid. There's the route. There's the -prefix. There's the Suffolk six. So - -109 -00:11:04.000 --> 00:11:11.060 -there's the whole thing. Other assets that -you might get that are, um, binary - -110 -00:11:11.060 --> 00:11:16.600 -acids would be like Hydrofluoric hydro. -I otik hydro nitric. There are very - -111 -00:11:16.600 --> 00:11:24.990 -few, um, acids that are binary that -we use other than the halogen, so that - -112 -00:11:24.990 --> 00:11:31.420 -makes it a little bit easier for us. -Okay, so up next we have turn Eri acids - -113 -00:11:31.420 --> 00:11:34.790 -and there's going to be two different -types of coronary acids. All the turn - -114 -00:11:34.790 --> 00:11:40.630 -Eri acids are based on which Polly -Atomic Ion are we working with And what - -115 -00:11:40.630 --> 00:11:44.590 -does it end with? So we have we're -going to kind of split this up so that we - -116 -00:11:44.590 --> 00:11:49.660 -can see it. So if the an eye on ends with ICT, - -117 -00:11:55.140 --> 00:11:59.030 -What we're going to do with that is -that the name is going to become we're - -118 -00:11:59.030 --> 00:12:07.220 -going to have the route and then it's -going to become owe us acid. Whereas if - -119 -00:12:07.220 --> 00:12:17.160 -the an ion ends with eight, then -we're gonna have the route, and it's beginning - -120 -00:12:17.160 --> 00:12:25.540 -to become an I C. Acid or an -IQ acid. The same charge rules apply. You're - -121 -00:12:25.540 --> 00:12:29.640 -still gonna balance out whatever the -negative charges on the anti on with - -122 -00:12:29.650 --> 00:12:34.400 -the H is being positive. So let's do -an example for each one of these. So - -123 -00:12:34.400 --> 00:12:39.180 -let's use we use sulfur as an -example for our hydro sulfuric acid. So let's - -124 -00:12:39.180 --> 00:12:46.460 -use the next two possible ions. Here -we have the sole fight Ion. So that's - -125 -00:12:46.470 --> 00:12:53.890 -s 03 minus two. And then over here -we have the sulfate ion notice the eight - -126 -00:12:53.890 --> 00:12:57.800 -has one more oxygen than the -height. That becomes an important factor a - -127 -00:12:57.800 --> 00:13:02.380 -little bit later on. To get our formula, -we just have to look at the charges - -128 -00:13:02.380 --> 00:13:06.790 -and balance them out with h is Each -of these has a negative to charge on - -129 -00:13:06.790 --> 00:13:11.350 -the Poly Atomic Ion. And so what -we need there is just to balance those - -130 -00:13:11.350 --> 00:13:18.620 -out with h is. So we're gonna need -to h is to balance out the negative to - -131 -00:13:18.620 --> 00:13:24.290 -over here and same thing on this side -over here. So on this side we have - -132 -00:13:24.290 --> 00:13:29.370 -H two s 03 on this side. We have -H two s 04 Same number of H is because - -133 -00:13:29.370 --> 00:13:33.310 -they both have the same charge now -they were They get really different is - -134 -00:13:33.310 --> 00:13:41.080 -how we name them. So we change the -ICT ending to oh us, and it becomes so - -135 -00:13:41.080 --> 00:13:50.270 -furious acid. And then on this side, -we change the eight ending toe. I - -136 -00:13:50.270 --> 00:13:57.920 -see, and it becomes sulfuric acid. -There's a good chance you've heard of - -137 -00:13:57.920 --> 00:14:02.760 -sulfuric acid, but maybe not sulfurous -acid. This one's used a little bit - -138 -00:14:02.760 --> 00:14:07.380 -more commonly and like cleaning -products and in industrial processes. So - -139 -00:14:07.380 --> 00:14:12.150 -you're going to be more likely to come -across sulfuric acid than you are. It's - -140 -00:14:12.150 --> 00:14:16.880 -one less oxygen counterpart. So we -have these two things sitting here, and - -141 -00:14:16.880 --> 00:14:19.960 -you're like, Oh, my gosh, How doe I -remember all of this. Well, I have this - -142 -00:14:19.960 --> 00:14:25.710 -really silly little thing that I tell -my kids, Um, and to know I'm telling - -143 -00:14:25.710 --> 00:14:35.670 -you because you're my kids and it's -a little sentence. So I ate IQ and - -144 -00:14:35.670 --> 00:14:45.670 -got the aight us. So, you know, it's a little bit - -145 -00:14:45.670 --> 00:14:50.270 -silly, but it works because you keep -the eight and the it together. So you - -146 -00:14:50.270 --> 00:14:55.190 -have I ate it like, Oh, it's something -bad and they got the itis. So when - -147 -00:14:55.190 --> 00:14:58.510 -you get sick, what do you get? -If you have a pancreatic infection, you get - -148 -00:14:58.510 --> 00:15:04.390 -pancreatitis. If you have a lung -infection, you get bronchitis. So you know, - -149 -00:15:04.390 --> 00:15:09.430 -you have this something. You ate something -bad, and it caused this to happen. - -150 -00:15:09.430 --> 00:15:15.780 -So I ate it and I got the -itis and it keeps together. The Poly Atomic ion - -151 -00:15:15.780 --> 00:15:20.010 -comes first, and then the Suffolk's for -your acid comes after it. So if - -152 -00:15:20.010 --> 00:15:25.210 -the Poly Atomic ion ends in eight, -your Suffolk's is it. If the Poly atomic - -153 -00:15:25.210 --> 00:15:30.260 -ion ends in ICT, your Suffolk's is us. -So let's go backwards so we can see - -154 -00:15:30.260 --> 00:15:37.070 -what that's going to look like. A Well, -here's our next two examples. We have - -155 -00:15:37.080 --> 00:15:46.530 -H three p 04 and H three p -03 So again, notice there's a single oxygen difference - -156 -00:15:46.530 --> 00:15:49.290 -between these two molecules, and -that's going to be something that's important - -157 -00:15:49.300 --> 00:15:52.850 -in a little while. We need to go -back to our reference sheet, and we need - -158 -00:15:52.850 --> 00:15:58.850 -to figure out what the name of each -of these poly atomic ions is. So you - -159 -00:15:58.850 --> 00:16:02.220 -go back to your handy dandy little -Polly Atomic I in reference sheet. Do - -160 -00:16:02.220 --> 00:16:11.360 -that now and you'll see that this is -the Foss fate I on while this is the - -161 -00:16:11.650 --> 00:16:18.830 -Foss fight I on. So this one ends -in eight. This one ends tonight. And as - -162 -00:16:18.830 --> 00:16:24.070 -you take a look at this, you're like, -Okay, I remember this. I ate IQ, so - -163 -00:16:24.070 --> 00:16:30.010 -I got the ICT us. So we're -going to take this phosphorus part right here, and - -164 -00:16:30.010 --> 00:16:39.050 -we're going to change that into an -I C. So we have phosphoric acid, - -165 -00:16:39.840 --> 00:16:49.190 -and over here the ICT becomes O U s. So we have Foss for us - -166 -00:16:50.140 --> 00:16:54.220 -acid, and I'm just going to say I -can't believe I made the words fit where - -167 -00:16:54.220 --> 00:16:58.010 -they were supposed to go. That was -kind of a miracle. All right, so you - -168 -00:16:58.010 --> 00:17:05.150 -got those down. Let's throw some together. -All right, so here we go. Here's - -169 -00:17:05.150 --> 00:17:13.490 -a couple of them H N 02 We need -to take a look. We need to know what this - -170 -00:17:13.490 --> 00:17:19.109 -Polly Atomic ion is. So we go back to -our sheet, I take a look at it. I - -171 -00:17:19.109 --> 00:17:27.800 -go. Oh, that's n o to minus, which -is the nitrite ion. So I know that ICT - -172 -00:17:27.810 --> 00:17:36.890 -becomes oh, us. And I know that -this becomes nitrous acid. All well and - -173 -00:17:36.890 --> 00:17:40.890 -good. I bet you got it. But there's -one more I want to show you because - -174 -00:17:40.890 --> 00:17:44.760 -it's kind of a weird one. It -doesn't follow the rules just like a whole - -175 -00:17:44.760 --> 00:17:54.450 -lot of things in chemistry. And here it is. -H c n. This is a very odd ball - -176 -00:17:54.450 --> 00:18:03.850 -little thing because it contains a poly -atomic ion. But that ion ends in - -177 -00:18:04.440 --> 00:18:10.860 -I d. E. So this is like the -one random example where we actually have to - -178 -00:18:10.860 --> 00:18:16.760 -go back to treating this almost a -ziff. It was a binary acid. So because - -179 -00:18:16.760 --> 00:18:21.130 -it ends an I d. It doesn't end -a night. It doesn't end in eight. This actually - -180 -00:18:21.130 --> 00:18:30.950 -becomes hydro scion IQ acid. So -that's the sort of one seriously random - -181 -00:18:30.950 --> 00:18:35.160 -exception. And then the last thing I -want to show you with our acids are - -182 -00:18:35.160 --> 00:18:43.400 -the I guess I would call them -the stepwise acids. And they are probably - -183 -00:18:43.400 --> 00:18:47.520 -atomic ions that have increasing numbers -of oxygens. And so we're going to - -184 -00:18:47.520 --> 00:18:54.610 -start download. We're going to start with -Cielo minus and then Cielo to minus - -185 -00:18:55.440 --> 00:19:02.680 -cielo three minus and Cielo four -minus. These, if you notice, have increasing - -186 -00:19:02.680 --> 00:19:07.060 -numbers of oxygen's as you go up. So -what happens is each one of these has - -187 -00:19:07.060 --> 00:19:12.280 -to have a slightly different name. -On DSO. We had prefixes and suffixes. - -188 -00:19:12.280 --> 00:19:16.590 -In addition to what we already had. -We already saw twice that eight had - -189 -00:19:16.590 --> 00:19:21.830 -one more oxygen than I and that's -the case here. So what happens is this - -190 -00:19:21.830 --> 00:19:28.800 -one with the Cielo three. That's the -chlorate ion. And so one less is the - -191 -00:19:28.800 --> 00:19:32.820 -chloride ion. Well, now you're like, -Well, there's one less and there's - -192 -00:19:32.820 --> 00:19:37.940 -one more. So what do I do with -those? So have you ever heard of diabetes - -193 -00:19:37.950 --> 00:19:43.180 -about the answer is yes. Have you -ever heard of the word hypoglycemia? Do - -194 -00:19:43.180 --> 00:19:47.840 -you know what it means? Yep. It -means low blood sugar. So when the blood - -195 -00:19:47.840 --> 00:19:54.400 -sugar gets low, you have a hypo glassy -mia. So we use that same prefix here - -196 -00:19:54.400 --> 00:20:02.730 -to represent a low number of oxygen's. -So this becomes the hypo Clo, right? - -197 -00:20:02.970 --> 00:20:08.360 -Ion. Unfortunately, my diabetes example does -not work in the other direction. - -198 -00:20:08.370 --> 00:20:12.200 -But there's something even more fun to -help you with this one. We keep Arklow - -199 -00:20:12.200 --> 00:20:20.210 -rate for this Cielo four. But now we -add the prefix Per so it's per chlorate. - -200 -00:20:20.220 --> 00:20:24.100 -Ion and I totally admit that one of -my kids came up with this, but you can - -201 -00:20:24.100 --> 00:20:29.980 -all enjoy the effects of it. You -always have a very happy kitty cat when - -202 -00:20:29.980 --> 00:20:37.540 -it has four legs. So it pers, I -know it's really bad, but the per does help - -203 -00:20:37.540 --> 00:20:41.360 -you remember that is supposed to be -with you. Have something with 04 on - -204 -00:20:41.360 --> 00:20:48.110 -it. It's going to be the per eight -ion. Um, this pattern applies for all of - -205 -00:20:48.110 --> 00:20:56.580 -the halogen, so you can have x -cielo four minus ex Cielo three minus ex - -206 -00:20:56.590 --> 00:21:03.660 -cielo to minus and ex Cielo minus, and -you can replace that X with any halogen. - -207 -00:21:07.640 --> 00:21:14.160 -However, the cool ride ones are the -most commonly seen. I think that's probably - -208 -00:21:14.160 --> 00:21:18.350 -enough for the moment. You've gotten -a lot of good experience with your - -209 -00:21:18.360 --> 00:21:23.720 -with your covalin compounds in your acids -here, and I hope to see you next - -210 -00:21:23.720 --> 00:21:24.960 -time. Take care. -{/file} \ No newline at end of file +Now generate 15 flashcards about {prompt}. First outline the important topics, definitions and subjects of {prompt} then write 15 flashcards in markdown bullet points. Use H3 to separate sections of flashcards ("###"). Use simple language and include 2 permutations of each flashcard asking for different details to help remember. diff --git a/cli/templates/shell.txt b/cli/templates/shell.txt new file mode 100644 index 0000000..becc036 --- /dev/null +++ b/cli/templates/shell.txt @@ -0,0 +1,31 @@ +Your job is to translate plain english into runnable shell commands. Output a single shell command in a code block. + +``` +ENVIRONMENT: +{#shelldisplay} +$SHELL --version +{/shelldisplay} + +PATH: +{#shelldisplay} +echo $PATH +{/shelldisplay} + +CURRENT DIR: +{#shelldisplay} +pwd +{/shelldisplay} + +FILES: +{#shelldisplay} +ls -l | head -10 +{/shelldisplay} +``` + +Now output a single shell command in a code block based on the following request: +{prompt} +{#every} + {#jsd} + console.log("hello" + await ask('Who are you')) + {/jsd} +{/every} \ No newline at end of file diff --git a/cli/templates/writing.txt b/cli/templates/writing.txt new file mode 100644 index 0000000..f5b6afb --- /dev/null +++ b/cli/templates/writing.txt @@ -0,0 +1,57 @@ +{__silent=true} +{#jsd} +function getPrompt(text, purpose) { + const sentences = getSentences(text); + return `Suggest some improvements for this text in bullet points. Don't give any actual suggestions for rephrasing, etc, instead just use bullet point suggestions. Give specific actionable advice to make the writing stronger, more interesting to read and solid overall. These suggestions can be to remove sections, add sections, rephrase things, or add in ideas/important topics. Focus on the purpose (given below): + ${sentences.map((i, idx) => `${i.trim()} [${idx + 1}]`).join('. ')} + + Your suggestions should be in the following format: + - [Priority level (1-3) - 1 is highest][SENTENCE NUMBER] Suggestion in plain text + + Example suggestion: + - [2][4] Rephrase to be more clear and remove run-ons. + + Output 10 suggestions. Each suggestion should pertain to only 1 sentence. Be concise. + +Purpose: ` + purpose +} + +function getSentences(text) { + return text.split(/[\!\.\?]/).filter(i => i.trim().length); +} + +return getPrompt(variables.prompt, "Convey an effective and professional scientific abstract in 250 words.") +{/jsd} +{#followup} +{#js} +let sentences = getSentences(variables.prompt); +let list = variables.claude_response.completion.split('\n').map(i => i.trim()).filter(i => i.startsWith('*') || i.startsWith('-')).map(i => { + const { groups: { priority, sentence, suggestion } } = i.match(/[\-\*]\s*\[(?[0-9])\]\s*\[(?[0-9])\]\s*(?.+)/); + + return { + priority: parseInt(priority), + sentenceIndex: parseInt(sentence), + sentence: sentences[parseInt(sentence) - 1], + suggestion: suggestion, + } +}); + +list = list.sort((a, b) => a.sentenceIndex - b.sentenceIndex); + +console.log(sentences.map((i, idx) => `${chalk.bold.blue('"' + i.trim() + '"')}\n${list.filter(i => i.sentenceIndex === idx).sort((a, b) => a.priority - b.priority).map(i => { + i.suggestion = i.suggestion.trim(); + if (i.priority === 1) { + return chalk.bold.red(i.suggestion); + } else if (i.priority === 2) { + return chalk.bold.yellow(i.suggestion); + } else { + return chalk.bold.gray(i.suggestion) + } +}).map(i => '\t- ' + i).join('\n')}`).join('\n\n')); + +process.exit(0); +function getSentences(text) { + return text.split(/[\!\.\?]/).filter(i => i.trim().length); +} +{/js} +{/followup} \ No newline at end of file diff --git a/cli/tls.js b/cli/tls.js new file mode 100644 index 0000000..f93124e --- /dev/null +++ b/cli/tls.js @@ -0,0 +1,95 @@ +import tls from 'cycletls'; + +const CONSTANTS = { + domain: 'claude.ai', +} + +export const CLIENTS = [ + { + name: 'My Web Browser (lol)', + userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36', + ja3: '771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,17513-16-13-18-43-45-11-10-35-0-65281-23-51-5-27-21,29-23-24,0', + ja3n: '771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-5-10-11-13-16-18-21-23-27-35-43-45-51-17513-65281,29-23-24,0', + headers: { + "accept-language": "en-US,en;q=0.9", + "sec-ch-ua": "\"Not)A;Brand\";v=\"24\", \"Chromium\";v=\"116\"", + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": "\"macOS\"", + "sec-fetch-dest": "empty", + "sec-fetch-mode": "cors", + "sec-fetch-site": "same-origin", + "x-requested-with": "XMLHttpRequest", + } + } +] + +let initPRes; +const initP = new Promise(r => (initPRes = r)); +let cycleTLS; +tls().then(r => { + cycleTLS = r + initPRes(r) +}) +export default async function fetch(url, options) { + await initP; + const client = CLIENTS[0]; + let cookies = []; + if (options.headers?.cookie) { + cookies = Object.entries(getCookies(options.headers.cookie)).map(([key, value]) => { + return { + name: key, + value, + domain: CONSTANTS.domain, + httpOnly: true, + } + }); + delete options.headers.cookie; + } + const OPTIONS = { + headers: { + ...(options.headers || {}), + ...client.headers, + "Referer": `https://${CONSTANTS.domain}/`, + }, + Cookies: cookies, + method: options.method || 'get', + userAgent: client.userAgent, + ja3: client.ja3, + body: options.body || undefined, + } + let res = await cycleTLS(url, OPTIONS) + const fakeResponse = { + status: res.status, + headers: res.headers, + text: Promise.resolve(res.body), + ok: res.status >= 200 && res.status < 300, + json: () => { + return new Promise((resolve, reject) => { + if (typeof res.body === 'object') { + resolve(res.body); + } + try { + resolve(JSON.parse(res.body)); + } catch (e) { + console.log({ body: res.body, type: typeof res.body }); + reject(e); + } + }) + }, + blob: Promise.resolve(new Blob([res.body])), + }; + return { + ...fakeResponse, clone: () => ({ ...fakeResponse }) + }; +} + +function getCookies(cookiesString) { + return cookiesString.split(";") + .map(function (cookieString) { + return cookieString.trim().split("="); + }) + .reduce(function (acc, curr) { + acc[curr[0]] = curr[1]; + return acc; + }, {}); +} \ No newline at end of file diff --git a/index.d.ts b/index.d.ts index d83d1d4..b6fcfc0 100644 --- a/index.d.ts +++ b/index.d.ts @@ -77,15 +77,23 @@ export class Claude { * @property {Object} messageLimit If you're within the message limit * @param {String} messageLimit.type The type of message limit ("within_limit") */ + /** + * @typdef {Object} SendMessageParamsStart + * @extends SendMessageParams + * @property {Conversation} [conversation] An optional conversation to continue/send the message to. + * If omitted, then a new conversation will be started + * @property {Boolean} [temporary=true] If the conversation is temporary or not. + * If temporary, then the convo in question will be deleted after response is gained + */ /** * Send a message to a new or existing conversation. * @param {string} message - Initial message - * @param {SendMessageParams} [params] - Additional parameters + * @param {SendMessageParamsStart} [params] - Additional parameters * @param {string} [params.conversation] - Existing conversation ID * @param {boolean} [params.temporary=true] - Delete after getting response * @returns {Promise} Result message */ - sendMessage(message: string, { conversation, temporary, ...params }?: SendMessageParams): Promise<{ + sendMessage(message: string, { conversation, temporary, ...params }?: SendMessageParamsStart): Promise<{ /** * The markdown text completion for this response */ @@ -193,11 +201,11 @@ export class Claude { */ clearConversations(): Promise; /** - * @callback doneCallback + * @callback {Function} doneCallback * @param {MessageStreamChunk} a The completed response */ /** - * @callback progressCallback + * @callback {Function} progressCallback * @param {MessageStreamChunk} a The response in progress */ /** @@ -300,7 +308,7 @@ export class Conversation { * @param {String} [options.updated_at] - Conversation updated at * @param {String} [options.model] - Claude model */ - constructor(claude: Claude, { model, conversationId, name, summary, created_at, updated_at }: { + constructor(claude: Claude, { model, conversationId, name, summary, created_at, updated_at }?: { conversationId: string; name?: string; summary?: string; @@ -452,7 +460,7 @@ export class Conversation { * @property {String} created_at The message created at * @property {String} updated_at The message updated at * @property {String | null} edited_at When the message was last edited (no editing support via api/web client) - * @property {Any | null} chat_feedback Feedback + * @property {string | null} chat_feedback Feedback * @property {Attachment[]} attachments The attachments */ /** @@ -521,7 +529,7 @@ export class Conversation { /** * Feedback */ - chat_feedback: Any | null; + chat_feedback: string | null; /** * The attachments */ @@ -606,7 +614,7 @@ export class Message { /** * Feedback */ - chat_feedback: any; + chat_feedback: string; /** * The attachments */ @@ -641,7 +649,7 @@ export class Message { index: any; updated_at: string; edited_at: string; - chat_feedback: any; + chat_feedback: string; attachments: { /** * The file name @@ -694,7 +702,7 @@ export class Message { /** * Feedback */ - chat_feedback: any; + chat_feedback: string; /** * The attachments */ @@ -819,61 +827,11 @@ export type SendMessageParams = { /** * Callback when done receiving the message response */ - done?: (a: { - /** - * The markdown text completion for this response - */ - completion: string; - /** - * The reason for the response stop (if any) - */ - stop_reason: string; - /** - * The model used - */ - model: string; - /** - * The string at which Claude stopped responding at, e.g. "\n\nHuman:" - */ - stop: string; - /** - * A logging ID - */ - log_id: string; - /** - * If you're within the message limit - */ - messageLimit: any; - }) => any; + done?: doneCallback; /** * Callback on message response progress */ - progress?: (a: { - /** - * The markdown text completion for this response - */ - completion: string; - /** - * The reason for the response stop (if any) - */ - stop_reason: string; - /** - * The model used - */ - model: string; - /** - * The string at which Claude stopped responding at, e.g. "\n\nHuman:" - */ - stop: string; - /** - * A logging ID - */ - log_id: string; - /** - * If you're within the message limit - */ - messageLimit: any; - }) => any; + progress?: progressCallback; /** * The model to use */ diff --git a/index.js b/index.js index 1af950c..020ac93 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,14 @@ * @classdesc Creates an instance of the Claude API client. */ export class Claude { + /** + * @typdef SendMessageParamsStart + * @extends SendMessageParams + * @property {Conversation} [conversation] An optional conversation to continue/send the message to. + * If omitted, then a new conversation will be started + * @property {Boolean} [temporary=true] If the conversation is temporary or not. + * If temporary, then the convo in question will be deleted after response is gained + */ /** * If the Claude client has initialized yet (call `init()` if you haven't and this is false) * @property {boolean} @@ -25,6 +33,7 @@ export class Claude { * @property {string} */ sessionKey; + /** * A UUID string * @typedef UUID @@ -33,7 +42,7 @@ export class Claude { /** * Create a new Claude API client instance. * @param {Object} options - Options - * @param {string} options.sessionKey - Claude session key + * @param {string} options.sessionKey - Claude session key * @param {string|function} [options.proxy] - Proxy URL or proxy function * @param {function} [options.fetch] - Fetch function * @example @@ -41,15 +50,15 @@ export class Claude { * sessionKey: 'sk-ant-sid01-*****', * fetch: globalThis.fetch * }) - * + * * await claude.init(); * claude.sendMessage('Hello world').then(console.log) */ - constructor({ sessionKey, proxy, fetch }) { + constructor({sessionKey, proxy, fetch}) { this.ready = false; if (typeof proxy === 'string') { const HOST = proxy; - this.proxy = ({ endpoint, options }) => ({ endpoint: HOST + endpoint, options }) + this.proxy = ({endpoint, options}) => ({endpoint: HOST + endpoint, options}) } else if (typeof proxy === 'function') { this.proxy = proxy; } else if (proxy) { @@ -58,7 +67,7 @@ export class Claude { throw new Error('Proxy must be a string (host) or a function'); } if (!this.proxy) { - this.proxy = ({ endpoint, options }) => ({ endpoint: 'https://claude.ai' + endpoint, options }); + this.proxy = ({endpoint, options}) => ({endpoint: 'https://claude.ai' + endpoint, options}); } if (!sessionKey) { throw new Error('Session key required'); @@ -66,9 +75,12 @@ export class Claude { if (!sessionKey.startsWith('sk-ant-sid01')) { throw new Error('Session key invalid: Must be in the format sk-ant-sid01-*****'); } - if (fetch) { this.fetch = fetch } + if (fetch) { + this.fetch = fetch + } this.sessionKey = sessionKey; } + /** * Get available Claude models. * @returns {string[]} Array of model names @@ -76,6 +88,7 @@ export class Claude { models() { return ['claude-2', 'claude-1.3', 'claude-instant', 'claude-instant-100k'] } + /** * Get total token count for a Claude model. * @param {string} [model] - Claude model name @@ -84,13 +97,11 @@ export class Claude { totalTokens(model) { // TODO: Figure out if this is correct, the blog article said "We’ve expanded Claude’s context window from 9K to 100K tokens" const TOKENS = { - "claude-2": 100_000, - "claude-1.3": 9000, - "claude-instant": 9000, - "claude-instant-100k": 100_000 + "claude-2": 100_000, "claude-1.3": 9000, "claude-instant": 9000, "claude-instant-100k": 100_000 } return TOKENS[model || this.defaultModel()]; } + /** * Get the default Claude model. * @returns {string} Default model name @@ -98,6 +109,7 @@ export class Claude { defaultModel() { return this.models()[0]; } + /** * A partial or total completion for a message. * @typedef MessageStreamChunk @@ -109,27 +121,29 @@ export class Claude { * @property {Object} messageLimit If you're within the message limit * @param {String} messageLimit.type The type of message limit ("within_limit") */ + /** * Send a message to a new or existing conversation. * @param {string} message - Initial message - * @param {SendMessageParams} [params] - Additional parameters + * @param {SendMessageParamsStart} [params] - Additional parameters * @param {string} [params.conversation] - Existing conversation ID * @param {boolean} [params.temporary=true] - Delete after getting response * @returns {Promise} Result message */ - async sendMessage(message, { conversation = null, temporary = true, ...params }) { + async sendMessage(message, {conversation = null, temporary = true, ...params} = {}) { if (!conversation) { let out; let convo = await this.startConversation(message, { - ...params, - done: (a) => { + ...params, done: (a) => { if (params.done) { params.done(a); } out = a; } }) - if (temporary) { await convo.delete(); } + if (temporary) { + await convo.delete(); + } return out; } else { return (await this.getConversation(conversation)).sendMessage(message, { @@ -137,6 +151,7 @@ export class Claude { }) } } + /** * Make an API request. * @param {string} endpoint - API endpoint @@ -151,15 +166,16 @@ export class Claude { throw new Error(`No fetch available in your environment. Use node-18 or later, a modern browser, or add the following code to your project:\n\nimport "isomorphic-fetch";\nconst claude = new Claude({fetch: fetch, sessionKey: "sk-ant-sid01-*****"});`); } if (!this.proxy) { - this.proxy = ({ endpoint, options }) => ({ endpoint: 'https://claude.ai' + endpoint, options }); + this.proxy = ({endpoint, options}) => ({endpoint: 'https://claude.ai' + endpoint, options}); } if (typeof this.proxy === 'string') { const HOST = this.proxy; - this.proxy = ({ endpoint, options }) => ({ endpoint: HOST + endpoint, options }) + this.proxy = ({endpoint, options}) => ({endpoint: HOST + endpoint, options}) } - const proxied = this.proxy({ endpoint, options }); + const proxied = this.proxy({endpoint, options}); return (this.fetch || globalThis.fetch)(proxied.endpoint, proxied.options); } + /** * Initialize the client. * @async @@ -174,6 +190,7 @@ export class Claude { this.recent_conversations = await this.getConversations(); this.ready = true; } + /** * An organization * @typedef Organization @@ -198,12 +215,12 @@ export class Claude { async getOrganizations() { const response = await this.request("/api/organizations", { headers: { - "content-type": "application/json", - "cookie": `sessionKey=${this.sessionKey}` + "content-type": "application/json", "cookie": `sessionKey=${this.sessionKey}` } }); return await response.json().catch(errorHandle("getOrganizations")); } + /** * Delete all conversations * @async @@ -216,12 +233,14 @@ export class Claude { const convos = await this.getConversations(); return Promise.all(convos.map(i => i.delete())) } + /** - * @callback doneCallback + * @callback {Function} doneCallback * @param {MessageStreamChunk} a The completed response */ + /** - * @callback progressCallback + * @callback {Function} progressCallback * @param {MessageStreamChunk} a The response in progress */ /** @@ -238,34 +257,30 @@ export class Claude { if (!this.ready) { await this.init(); } - const { uuid: convoID, name, summary, created_at, updated_at } = await this.request(`/api/organizations/${this.organizationId}/chat_conversations`, { + const { + uuid: convoID, name, summary, created_at, updated_at + } = await this.request(`/api/organizations/${this.organizationId}/chat_conversations`, { headers: { - "content-type": "application/json", - "cookie": `sessionKey=${this.sessionKey}` - }, - method: 'POST', - body: JSON.stringify({ - name: '', - uuid: uuid(), + "content-type": "application/json", "cookie": `sessionKey=${this.sessionKey}` + }, method: 'POST', body: JSON.stringify({ + name: '', uuid: uuid(), }) }).then(r => r.json()).catch(errorHandle("startConversation create")); - const convo = new Conversation(this, { conversationId: convoID, name, summary, created_at, updated_at }); + const convo = new Conversation(this, {conversationId: convoID, name, summary, created_at, updated_at}); await convo.sendMessage(message, params) await this.request(`/api/generate_chat_title`, { headers: { - "content-type": "application/json", - "cookie": `sessionKey=${this.sessionKey}` - }, - body: JSON.stringify({ + "content-type": "application/json", "cookie": `sessionKey=${this.sessionKey}` + }, body: JSON.stringify({ organization_uuid: this.organizationId, conversation_uuid: convoID, message_content: message, recent_titles: this.recent_conversations.map(i => i.name), - }), - method: 'POST' + }), method: 'POST' }).then(r => r.json()).catch(errorHandle("startConversation generate_chat_title")); return convo; } + /** * Get a conversation by its ID * @param {UUID} id The uuid of the conversation (Conversation.uuid or Conversation.conversationId) @@ -276,27 +291,28 @@ export class Claude { */ async getConversation(id) { if (id instanceof Conversation || id.conversationId) { - return new Conversation(this, { conversationId: id.conversationId }) + return new Conversation(this, {conversationId: id.conversationId}) } - return new Conversation(this, { conversationId: id }) + return new Conversation(this, {conversationId: id}) } + /** * Get all conversations * @async * @returns {Promise} A list of conversations * @example - * console.log(`You have ${await claude.getConversations().length} conversations:`); + * console.log(`You have ${await claude.getConversations().length} conversations:`); */ async getConversations() { const response = await this.request(`/api/organizations/${this.organizationId}/chat_conversations`, { headers: { - "content-type": "application/json", - "cookie": `sessionKey=${this.sessionKey}` + "content-type": "application/json", "cookie": `sessionKey=${this.sessionKey}` } }); const json = await response.json(); - return json.map(convo => new Conversation(this, { conversationId: convo.uuid, ...convo })); + return json.map(convo => new Conversation(this, {conversationId: convo.uuid, ...convo})); } + /** * The response from uploading a file (an attachment) * @typedef Attachment @@ -320,14 +336,11 @@ export class Claude { * })) */ async uploadFile(file) { - const { content, isText } = await readAsText(file); + const {content, isText} = await readAsText(file); if (isText) { console.log(`Extracted ${content.length} characters from ${file.name}`); return { - "file_name": file.name, - "file_type": file.type, - "file_size": file.size, - "extracted_content": content, + "file_name": file.name, "file_type": file.type, "file_size": file.size, "extracted_content": content, } } const fd = new FormData(); @@ -336,9 +349,7 @@ export class Claude { const response = await this.request('/api/convert_document', { headers: { "cookie": `sessionKey=${this.sessionKey}`, - }, - method: 'POST', - body: fd + }, method: 'POST', body: fd }); let json; try { @@ -371,14 +382,14 @@ export class Claude { */ /** * A Claude conversation instance. - * @class + * @class * @typedef Conversation * @classdesc Represents an active Claude conversation. */ export class Conversation { /** * The conversation ID - * @property {string} + * @property {string} */ conversationId; @@ -441,9 +452,10 @@ export class Conversation { * @property {Function} */ fetch; + /** * Create a Conversation instance. - * @param {Claude} claude - Claude client instance + * @param {Claude} claude - Claude client instance * @param {Object} options - Options * @param {String} options.conversationId - Conversation ID * @param {String} [options.name] - Conversation name @@ -452,10 +464,13 @@ export class Conversation { * @param {String} [options.updated_at] - Conversation updated at * @param {String} [options.model] - Claude model */ - constructor(claude, { model = "default", conversationId, name = "", summary = "", created_at, updated_at }) { + constructor(claude, {model = "default", conversationId, name = "", summary = "", created_at, updated_at} = {}) { this.claude = claude; this.conversationId = conversationId; this.request = claude.request; + this.proxy = claude.proxy; + this.fetch = claude.fetch; + this.ready = claude.ready; if (!this.claude) { throw new Error('Claude not initialized'); } @@ -469,8 +484,14 @@ export class Conversation { model = this.claude.defaultModel(); } this.model = model || this.claude.defaultModel(); - Object.assign(this, { name, summary, created_at: created_at || new Date().toISOString(), updated_at: updated_at || new Date().toISOString() }) + Object.assign(this, { + name, + summary, + created_at: created_at || new Date().toISOString(), + updated_at: updated_at || new Date().toISOString() + }) } + /** * Convert the conversation to a JSON object * @returns {Conversation} The serializable object @@ -486,22 +507,29 @@ export class Conversation { model: this.model, } } + /** * Retry the last message in the conversation - * @param {SendMessageParams} [params={}] + * @param {SendMessageParams} [params={}] * @returns {Promise} */ async retry(params) { - return this.sendMessage("", { ...params, retry: true }); + return this.sendMessage("", {...params, retry: true}); } + /** * Send a message to this conversation - * @param {String} message + * @param {String} message * @async * @param {SendMessageParams} params The parameters to send along with the message * @returns {Promise} */ - async sendMessage(message, { retry = false, timezone = "America/New_York", attachments = [], model = 'default', done = () => { }, progress = () => { }, rawResponse = () => { } } = {}) { + async sendMessage(message, { + retry = false, timezone = "America/New_York", attachments = [], model = 'default', done = () => { + }, progress = () => { + }, rawResponse = () => { + } + } = {}) { if (model === 'default') { model = this.claude.defaultModel(); } @@ -511,20 +539,19 @@ export class Conversation { text: message, attachments, completion: { - prompt: message, - timezone, - model: model || this.model || this.claude.defaultModel(), + prompt: message, timezone, model: model || this.model || this.claude.defaultModel(), } }; const response = await this.request(`/api/${retry ? "retry_message" : "append_message"}`, { - method: "POST", - headers: { - "accept": "text/event-stream,text/event-stream", - "content-type": "application/json", - "cookie": `sessionKey=${this.claude.sessionKey}` - }, - body: JSON.stringify(body) + method: "POST", headers: { + "accept": "text/event-stream, text/event-stream", + }, body: JSON.stringify(body) }); + if (!response.ok) { + errorHandle('Response not OK')(response); + console.log(await response.text()) + return; + } let resolve; let returnPromise = new Promise(r => (resolve = r)); let parsed; @@ -555,6 +582,7 @@ export class Conversation { }) return returnPromise; } + /** * Rename the current conversation * @async @@ -566,17 +594,14 @@ export class Conversation { throw new Error('Title required'); } return await this.request('/api/rename_chat', { - method: 'POST', - headers: { + method: 'POST', headers: { "cookie": `sessionKey=${this.claude.sessionKey}` - }, - body: JSON.stringify({ - conversation_uuid: this.conversationId, - organization_uuid: this.claude.organizationId, - title, + }, body: JSON.stringify({ + conversation_uuid: this.conversationId, organization_uuid: this.claude.organizationId, title, }) }).catch(errorHandle("Rename conversation " + this.conversationId)); } + /** * Delete the conversation * @async @@ -586,10 +611,10 @@ export class Conversation { return await this.request(`/api/organizations/${this.claude.organizationId}/chat_conversations/${this.conversationId}`, { headers: { "cookie": `sessionKey=${this.claude.sessionKey}` - }, - method: 'DELETE' + }, method: 'DELETE' }).catch(errorHandle("Delete conversation " + this.conversationId)); } + /** * @typedef Message * @property {UUID} uuid The message UUID @@ -597,9 +622,10 @@ export class Conversation { * @property {String} created_at The message created at * @property {String} updated_at The message updated at * @property {String | null} edited_at When the message was last edited (no editing support via api/web client) - * @property {Any | null} chat_feedback Feedback + * @property {string | null} chat_feedback Feedback * @property {Attachment[]} attachments The attachments */ + /** * @typedef ConversationInfo * @extends Conversation @@ -612,12 +638,12 @@ export class Conversation { async getInfo() { const response = await this.request(`/api/organizations/${this.claude.organizationId}/chat_conversations/${this.conversationId}`, { headers: { - "content-type": "application/json", - "cookie": `sessionKey=${this.claude.sessionKey}` + "content-type": "application/json", "cookie": `sessionKey=${this.claude.sessionKey}` } }); return await response.json().then(this.#formatMessages('chat_messages')).catch(errorHandle("getInfo")); } + /** * Get all the files from this conversation * @async @@ -626,6 +652,7 @@ export class Conversation { getFiles() { return this.getMessages().then(r => r.map(i => i.attachments)).then(r => r.flat()).catch(errorHandle('getFiles')); } + /** * Get all messages in the conversation * @async @@ -634,6 +661,7 @@ export class Conversation { getMessages() { return this.getInfo().then((a) => a.chat_messages).catch(errorHandle("getMessages")); } + /** * Internal method for converting a JSON response to contain Message objects * @param {String} message_key The message key in the object @@ -645,8 +673,9 @@ export class Conversation { return response; } return { - ...response, - [message_key]: response[message_key].map(i => new Message({ claude: this.claude, conversation: this }, { ...i })), + ...response, [message_key]: response[message_key].map(i => new Message({ + claude: this.claude, conversation: this + }, {...i})), } } } @@ -665,7 +694,7 @@ async function readStream(response, progressCallback) { let chunks = []; let loading = true; while (loading) { - const { done, value } = await reader.read(); + const {done, value} = await reader.read(); if (done) { loading = false; break; @@ -681,7 +710,9 @@ async function readStream(response, progressCallback) { position += chunk.length; } - if (value) { progressCallback(new TextDecoder('utf-8').decode(value), new TextDecoder('utf-8').decode(full)); } + if (value) { + progressCallback(new TextDecoder('utf-8').decode(value), new TextDecoder('utf-8').decode(full)); + } } let body = new Uint8Array(received); @@ -706,8 +737,7 @@ async function readAsText(file) { // const allow = ['text', 'javascript', 'json', 'html', 'sh', 'xml', 'latex', 'ecmascript'] const notText = ['doc', 'pdf', 'ppt', 'xls'] return { - content: new TextDecoder('utf-8').decode(buf), - isText: !notText.find(i => file.name.includes(i)) + content: new TextDecoder('utf-8').decode(buf), isText: !notText.find(i => file.name.includes(i)) } } @@ -736,7 +766,8 @@ function uuid() { var u = '', i = 0, rb = Math.random() * 0xffffffff | 0; while (i++ < 36) { var c = k[i - 1], r = rb & 0xf, v = c == 'x' ? r : (r & 0x3 | 0x8); - u += (c == '-' || c == '4') ? c : h[v]; rb = i % 8 == 0 ? Math.random() * 0xffffffff | 0 : rb >> 4 + u += (c == '-' || c == '4') ? c : h[v]; + rb = i % 8 == 0 ? Math.random() * 0xffffffff | 0 : rb >> 4 } return u } @@ -770,18 +801,21 @@ export class Message { * @param {Claude} params.claude - Claude instance * @param {Message} message - Message data */ - constructor({ conversation, claude }, { uuid, text, sender, index, updated_at, edited_at, chat_feedback, attachments }) { + constructor({conversation, claude}, { + uuid, text, sender, index, updated_at, edited_at, chat_feedback, attachments + }) { if (!claude) { throw new Error('Claude not initialized'); } if (!conversation) { throw new Error('Conversation not initialized'); } - Object.assign(this, { conversation, claude }); + Object.assign(this, {conversation, claude}); this.request = claude.request; - this.json = { uuid, text, sender, index, updated_at, edited_at, chat_feedback, attachments }; + this.json = {uuid, text, sender, index, updated_at, edited_at, chat_feedback, attachments}; Object.assign(this, this.json); } + /** * Convert this message to a JSON representation * Necessary to prevent circular JSON errors @@ -790,6 +824,7 @@ export class Message { toJSON() { return this.json; } + /** * Returns the value of the "created_at" property as a Date object. * @@ -798,6 +833,7 @@ export class Message { get createdAt() { return new Date(this.json.created_at); } + /** * Returns the value of the "updated_at" property as a Date object. * @@ -806,6 +842,7 @@ export class Message { get updatedAt() { return new Date(this.json.updated_at); } + /** * Returns the value of the "edited_at" property as a Date object. * @@ -814,6 +851,7 @@ export class Message { get editedAt() { return new Date(this.json.edited_at); } + /** * Get if message is from the assistant. * @type {boolean} @@ -821,6 +859,7 @@ export class Message { get isBot() { return this.sender === "assistant"; } + /** * @typedef MessageFeedback * @property {UUID} uuid - Message UUID @@ -833,7 +872,7 @@ export class Message { * Send feedback on the message. * @param {string} type - Feedback type * @param {string} [reason] - Feedback reason - * @returns {Promise} Response + * @returns {Promise} Response */ async sendFeedback(type, reason = "") { const FEEDBACK_TYPES = ["flag/bug", "flag/harmful", "flag/other"]; @@ -843,12 +882,9 @@ export class Message { return await this.request(`/api/organizations/${this.claude.organizationId}/chat_conversations/${this.conversation.conversationId}/chat_messages/${this.uuid}/chat_feedback`, { "headers": { "cookie": `sessionKey=${this.claude.sessionKey}` - }, - "body": JSON.stringify({ - type, - reason, - }), - "method": "POST", + }, "body": JSON.stringify({ + type, reason, + }), "method": "POST", }).catch(errorHandle("Send feedback")); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8cb317e..9a97929 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,6 +13,9 @@ devDependencies: '@babel/preset-env': specifier: ^7.22.9 version: 7.22.9(@babel/core@7.22.9) + body-parser: + specifier: ^1.20.2 + version: 1.20.2 dotenv: specifier: ^16.3.1 version: 16.3.1 @@ -1281,6 +1284,26 @@ packages: - supports-color dev: true + /body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /browserslist@4.21.9: resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -1292,6 +1315,18 @@ packages: update-browserslist-db: 1.0.11(browserslist@4.21.9) dev: true + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: true + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + dev: true + /caniuse-lite@1.0.30001516: resolution: {integrity: sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==} dev: true @@ -1315,6 +1350,11 @@ packages: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} dev: true + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: true + /convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} dev: true @@ -1325,6 +1365,17 @@ packages: browserslist: 4.21.9 dev: true + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -1337,11 +1388,25 @@ packages: ms: 2.1.2 dev: true + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: true + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: true + /dotenv@16.3.1: resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} engines: {node: '>=12'} dev: true + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: true + /electron-to-chromium@1.4.461: resolution: {integrity: sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==} dev: true @@ -1370,6 +1435,15 @@ packages: engines: {node: '>=6.9.0'} dev: true + /get-intrinsic@1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-proto: 1.0.1 + has-symbols: 1.0.3 + dev: true + /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -1380,6 +1454,16 @@ packages: engines: {node: '>=4'} dev: true + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + /has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} @@ -1387,6 +1471,28 @@ packages: function-bind: 1.1.1 dev: true + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + /is-core-module@2.12.1: resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} dependencies: @@ -1433,6 +1539,27 @@ packages: yallist: 3.1.1 dev: true + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -1453,6 +1580,17 @@ packages: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: true + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: true + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: true + /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true @@ -1461,6 +1599,23 @@ packages: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: true + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + /regenerate-unicode-properties@10.1.0: resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} engines: {node: '>=4'} @@ -1510,11 +1665,32 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true dev: true + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + object-inspect: 1.12.3 + dev: true + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: true + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -1532,10 +1708,23 @@ packages: engines: {node: '>=4'} dev: true + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: true + /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: false + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: true + /typescript@5.1.6: resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} engines: {node: '>=14.17'} @@ -1565,6 +1754,11 @@ packages: engines: {node: '>=4'} dev: true + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: true + /update-browserslist-db@1.0.11(browserslist@4.21.9): resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} hasBin: true