gptMemoryManagerREADME.md20 matches
1A simple Rest API that allows for you GPT to save and recall snippets of data (memories). You can read my blog post explaining it in detail here: [xkonti.tech](https://xkonti.tech/blog/giving-gpt-memory/)
23# Demonstration
7
89What GPT sent do the API:
1011```json
24# Setup
2526There are several steps to set up the API:
27- deploy and configure the API
28- create the API key for your GPT
29- add an action for the API in you GPT
30- add prompt section to your GPT so that it can use it properly
3132## Deploying the API on Val Town
3334Deploy your own memory API. You can fork the following Val to do it: https://www.val.town/v/xkonti/memoryApiExample
3536In the code configure the appropriate values:
3738- `apiName` the name of your API - used in the Privacy Policy (eg. `Memory API`)
39- `contactEmail` - the email to provide for contact in the Privacy Policy (eg. `some@email.com`)
40- `lastPolicyUpdate` - the date the Privacy Policy was last updated (eg. `2023-11-28`)
41- `blobKeyPrefix` - the prefix for the blob storage keys used by your API - more info below (eg. `gpt:memories:`)
42- `apiKeyPrefix` - the prefix for you API Keys secrets - more info below (eg. `GPTMEMORYAPI_KEY_`)
4344## Create API keys
4546The Memory API is designed to serve multiple GPTs at the same time. Each GPT should have it's own unique **name** and **API key**.
4748The **name** is used for identifying the specific GPT and appended to both:
49- `blobKeyPrefix`- to maintain separate memory storage from other GPTs
50- `apiKeyPrefix` - to maintain separate API key for each GPT
51521. Please pick a unique alphanumeric name for your GPT. For example `personaltrainer`.
532. Generate some alphanumeric API key for your GPT. For example `Wrangle-Chapped-Monkhood4-Domain-Suspend`
543. Add a new secret to your Val.town secrets storage. The Key should be the picked name prefixed by `apiKeyPrefix`. Using the default it would be `GPTMEMORYAPI_KEY_personaltrainer`. The value of the secret should be the API key itself.
5556The memories of the GPT will be stored in the blob storage under the key `blobKeyPrefix + name`, for example: `gpt:memories:personaltrainer`.
59601. Add a new action in your GPT.
612. Get the OpenAPI spefication by calling the `/openapi` endpoint of your API
623. Change all `<APIURL>` instances within the specification to the url of your deployed API. For example `https://xkonti-memoryapiexample.web.val.run`
634. Set the authentication method to basic and provide a [base64 encoded](https://www.base64encode.org/) version of the `<name>:<apiKey>`. For example: `personaltrainer:Wrangle-Chapped-Monkhood4-Domain-Suspend` -> `cGVyc29uYWx0cmFpbmVyOldyYW5nbGUtQ2hhcHBlZC1Nb25raG9vZDQtRG9tYWluLVN1c3BlbmQ=`
645. Add the link to the privacy policy, which is the `/privacy` endpoint of your API. For example: `https://xkonti-memoryapiexample.web.val.run/privacy`
6566## Adding the prompt section
gptMemoryManagermain.tsx24 matches
1import * as uuid from "https://deno.land/std/uuid/mod.ts";
2import { blob } from "https://esm.town/v/std/blob";
3import { getPolicy } from "https://esm.town/v/xkonti/memoryApiPolicy";
4import { Hono } from "npm:hono@3";
56export const handleMemoryApiRequest = async (
7req: Request,
8apiName: string,
9contactEmail: string,
10lastPolicyUpdate: string,
11blobKeyPrefix: string,
12apiKeyPrefix: string,
13) => {
14// ==== HELPERS ====
2728const verifyRequest = (c): { memoriesKey: string; error: any } => {
29// Verify API key coming as a Bearer header
30const authHeader = c.req.headers.get("Authorization");
31if (!authHeader || !authHeader.startsWith("Basic ")) {
43return { memoriesKey: "", error: c.text("Forbidden", 403) };
44}
45const expectedKey = Deno.env.get(apiKeyPrefix + key) ?? null;
46if (token !== expectedKey) {
47console.error("Invalid API KEY header");
48return { memoriesKey: "", error: c.text("Forbidden", 403) };
49}
51};
5253// API
5455const app = new Hono();
209// PRIVACY POLICY
210app.get("/privacy", async (c) => {
211const policy = getPolicy(apiName, contactEmail, lastPolicyUpdate);
212c.header("Content-Type", "text/html");
213return c.html(policy);
214});
215216app.get("/openapi", async (c) => {
217const specification = `
218{
219"openapi": "3.1.0",
220"info": {
221"title": "Memories API",
222"description": "API for managing and storing long-term memories.",
223"version": "1.0.0"
224},
225"servers": [
226{
227"url": "<APIURL>"
228}
229],
238},
239"401": {
240"description": "Unauthorized - Missing or invalid API key."
241},
242"403": {
243"description": "Forbidden - Invalid API key."
244}
245},
272},
273"401": {
274"description": "Unauthorized - Missing or invalid API key."
275},
276"403": {
277"description": "Forbidden - Invalid API key."
278}
279},
328},
329"401": {
330"description": "Unauthorized - Missing or invalid API key."
331},
332"403": {
333"description": "Forbidden - Invalid API key."
334}
335},
375},
376"401": {
377"description": "Unauthorized - Missing or invalid API key."
378},
379"403": {
380"description": "Forbidden - Invalid API key."
381}
382},
406},
407"401": {
408"description": "Unauthorized - Missing or invalid API key."
409},
410"403": {
411"description": "Forbidden - Invalid API key."
412}
413},
gpt_memoryREADME.md20 matches
1A simple Rest API that allows for you GPT to save and recall snippets of data (memories). You can read my blog post explaining it in detail here: [xkonti.tech](https://xkonti.tech/blog/giving-gpt-memory/)
23# Demonstration
7
89What GPT sent do the API:
1011```json
24# Setup
2526There are several steps to set up the API:
27- deploy and configure the API
28- create the API key for your GPT
29- add an action for the API in you GPT
30- add prompt section to your GPT so that it can use it properly
3132## Deploying the API on Val Town
3334Deploy your own memory API. You can fork the following Val to do it: https://www.val.town/v/xkonti/memoryApiExample
3536In the code configure the appropriate values:
3738- `apiName` the name of your API - used in the Privacy Policy (eg. `Memory API`)
39- `contactEmail` - the email to provide for contact in the Privacy Policy (eg. `some@email.com`)
40- `lastPolicyUpdate` - the date the Privacy Policy was last updated (eg. `2023-11-28`)
41- `blobKeyPrefix` - the prefix for the blob storage keys used by your API - more info below (eg. `gpt:memories:`)
42- `apiKeyPrefix` - the prefix for you API Keys secrets - more info below (eg. `GPTMEMORYAPI_KEY_`)
4344## Create API keys
4546The Memory API is designed to serve multiple GPTs at the same time. Each GPT should have it's own unique **name** and **API key**.
4748The **name** is used for identifying the specific GPT and appended to both:
49- `blobKeyPrefix`- to maintain separate memory storage from other GPTs
50- `apiKeyPrefix` - to maintain separate API key for each GPT
51521. Please pick a unique alphanumeric name for your GPT. For example `personaltrainer`.
532. Generate some alphanumeric API key for your GPT. For example `Wrangle-Chapped-Monkhood4-Domain-Suspend`
543. Add a new secret to your Val.town secrets storage. The Key should be the picked name prefixed by `apiKeyPrefix`. Using the default it would be `GPTMEMORYAPI_KEY_personaltrainer`. The value of the secret should be the API key itself.
5556The memories of the GPT will be stored in the blob storage under the key `blobKeyPrefix + name`, for example: `gpt:memories:personaltrainer`.
59601. Add a new action in your GPT.
612. Get the OpenAPI spefication by calling the `/openapi` endpoint of your API
623. Change all `<APIURL>` instances within the specification to the url of your deployed API. For example `https://xkonti-memoryapiexample.web.val.run`
634. Set the authentication method to basic and provide a [base64 encoded](https://www.base64encode.org/) version of the `<name>:<apiKey>`. For example: `personaltrainer:Wrangle-Chapped-Monkhood4-Domain-Suspend` -> `cGVyc29uYWx0cmFpbmVyOldyYW5nbGUtQ2hhcHBlZC1Nb25raG9vZDQtRG9tYWluLVN1c3BlbmQ=`
645. Add the link to the privacy policy, which is the `/privacy` endpoint of your API. For example: `https://xkonti-memoryapiexample.web.val.run/privacy`
6566## Adding the prompt section
gptMemoryManagerREADME.md20 matches
1A simple Rest API that allows for you GPT to save and recall snippets of data (memories). You can read my blog post explaining it in detail here: [xkonti.tech](https://xkonti.tech/blog/giving-gpt-memory/)
23# Demonstration
7
89What GPT sent do the API:
1011```json
24# Setup
2526There are several steps to set up the API:
27- deploy and configure the API
28- create the API key for your GPT
29- add an action for the API in you GPT
30- add prompt section to your GPT so that it can use it properly
3132## Deploying the API on Val Town
3334Deploy your own memory API. You can fork the following Val to do it: https://www.val.town/v/xkonti/memoryApiExample
3536In the code configure the appropriate values:
3738- `apiName` the name of your API - used in the Privacy Policy (eg. `Memory API`)
39- `contactEmail` - the email to provide for contact in the Privacy Policy (eg. `some@email.com`)
40- `lastPolicyUpdate` - the date the Privacy Policy was last updated (eg. `2023-11-28`)
41- `blobKeyPrefix` - the prefix for the blob storage keys used by your API - more info below (eg. `gpt:memories:`)
42- `apiKeyPrefix` - the prefix for you API Keys secrets - more info below (eg. `GPTMEMORYAPI_KEY_`)
4344## Create API keys
4546The Memory API is designed to serve multiple GPTs at the same time. Each GPT should have it's own unique **name** and **API key**.
4748The **name** is used for identifying the specific GPT and appended to both:
49- `blobKeyPrefix`- to maintain separate memory storage from other GPTs
50- `apiKeyPrefix` - to maintain separate API key for each GPT
51521. Please pick a unique alphanumeric name for your GPT. For example `personaltrainer`.
532. Generate some alphanumeric API key for your GPT. For example `Wrangle-Chapped-Monkhood4-Domain-Suspend`
543. Add a new secret to your Val.town secrets storage. The Key should be the picked name prefixed by `apiKeyPrefix`. Using the default it would be `GPTMEMORYAPI_KEY_personaltrainer`. The value of the secret should be the API key itself.
5556The memories of the GPT will be stored in the blob storage under the key `blobKeyPrefix + name`, for example: `gpt:memories:personaltrainer`.
59601. Add a new action in your GPT.
612. Get the OpenAPI spefication by calling the `/openapi` endpoint of your API
623. Change all `<APIURL>` instances within the specification to the url of your deployed API. For example `https://xkonti-memoryapiexample.web.val.run`
634. Set the authentication method to basic and provide a [base64 encoded](https://www.base64encode.org/) version of the `<name>:<apiKey>`. For example: `personaltrainer:Wrangle-Chapped-Monkhood4-Domain-Suspend` -> `cGVyc29uYWx0cmFpbmVyOldyYW5nbGUtQ2hhcHBlZC1Nb25raG9vZDQtRG9tYWluLVN1c3BlbmQ=`
645. Add the link to the privacy policy, which is the `/privacy` endpoint of your API. For example: `https://xkonti-memoryapiexample.web.val.run/privacy`
6566## Adding the prompt section
gptMemoryManagermain.tsx24 matches
1import * as uuid from "https://deno.land/std/uuid/mod.ts";
2import { blob } from "https://esm.town/v/std/blob";
3import { getPolicy } from "https://esm.town/v/xkonti/memoryApiPolicy";
4import { Hono } from "npm:hono@3";
56export const handleMemoryApiRequest = async (
7req: Request,
8apiName: string,
9contactEmail: string,
10lastPolicyUpdate: string,
11blobKeyPrefix: string,
12apiKeyPrefix: string,
13) => {
14// ==== HELPERS ====
2728const verifyRequest = (c): { memoriesKey: string; error: any } => {
29// Verify API key coming as a Bearer header
30const authHeader = c.req.headers.get("Authorization");
31if (!authHeader || !authHeader.startsWith("Basic ")) {
43return { memoriesKey: "", error: c.text("Forbidden", 403) };
44}
45const expectedKey = Deno.env.get(apiKeyPrefix + key) ?? null;
46if (token !== expectedKey) {
47console.error("Invalid API KEY header");
48return { memoriesKey: "", error: c.text("Forbidden", 403) };
49}
51};
5253// API
5455const app = new Hono();
209// PRIVACY POLICY
210app.get("/privacy", async (c) => {
211const policy = getPolicy(apiName, contactEmail, lastPolicyUpdate);
212c.header("Content-Type", "text/html");
213return c.html(policy);
214});
215216app.get("/openapi", async (c) => {
217const specification = `
218{
219"openapi": "3.1.0",
220"info": {
221"title": "Memories API",
222"description": "API for managing and storing long-term memories.",
223"version": "1.0.0"
224},
225"servers": [
226{
227"url": "<APIURL>"
228}
229],
238},
239"401": {
240"description": "Unauthorized - Missing or invalid API key."
241},
242"403": {
243"description": "Forbidden - Invalid API key."
244}
245},
272},
273"401": {
274"description": "Unauthorized - Missing or invalid API key."
275},
276"403": {
277"description": "Forbidden - Invalid API key."
278}
279},
328},
329"401": {
330"description": "Unauthorized - Missing or invalid API key."
331},
332"403": {
333"description": "Forbidden - Invalid API key."
334}
335},
375},
376"401": {
377"description": "Unauthorized - Missing or invalid API key."
378},
379"403": {
380"description": "Forbidden - Invalid API key."
381}
382},
406},
407"401": {
408"description": "Unauthorized - Missing or invalid API key."
409},
410"403": {
411"description": "Forbidden - Invalid API key."
412}
413},
lightGrayCrowmain.tsx1 match
1// This cron emails Hacker News stories from its API every 3 days.
23import { email } from "https://esm.town/v/std/email";
hackerNewsDigestmain.tsx1 match
1// This cron emails Hacker News stories from its API every 3 days.
23import { email } from "https://esm.town/v/std/email";
bookReservationOnResymain.tsx7 matches
30}) => {
31const { z } = await import("npm:zod");
32const RESY_API_URL = "https://api.resy.com";
33const RESY_DEFAULT_HEADERS = {
34accept: "application/json, text/plain, */*",
35"accept-encoding": "gzip, deflate, br",
36"accept-language": "en-US,en;q=0.9",
37authorization: "ResyAPI api_key=\"VbWk7s3L4KiK5fzlO7JD3Q5EYolJI7n5\"",
38"x-origin": "https://resy.com",
39origin: "https://resy.com/",
145)
146}&password=${encodeURIComponent(params.password)}`;
147const response = await fetch(`${RESY_API_URL}/3/auth/password`, {
148method: "POST",
149body: body,
166seats: number;
167}) => {
168const url = `${RESY_API_URL}/3/details`;
169const response = await fetch(url.toString(), {
170method: "POST",
185seats: number;
186}) => {
187const url = `${RESY_API_URL}/4/find`;
188const searchParams = new URLSearchParams();
189searchParams.set("lat", "0");
208city: string;
209}) => {
210const url = `${RESY_API_URL}/3/venue`;
211const searchParams = new URLSearchParams();
212searchParams.set("url_slug", params.slug);
224authToken: string;
225}) => {
226const response = await fetch(`${RESY_API_URL}/3/book`, {
227method: "POST",
228headers: {
v2FanFicScrapermain.tsx30 matches
11e.preventDefault();
12setLoading(true);
13console.log(`Submitting URL for scraping: ${url}`);
1415const maxRetries = 3;
28if (!response.ok) {
29if (response.status === 400) {
30throw new APIError("Bad request. Check your parameters.", response.status);
31} else if (response.status === 401) {
32throw new APIError("No more credit available. Please upgrade your plan.", response.status);
33} else if (response.status === 404) {
34throw new APIError("Requested URL not found.", response.status);
35} else if (response.status === 429) {
36throw new APIError("Too many concurrent requests. Please upgrade your plan.", response.status);
37} else {
38throw new APIError(`HTTP error! status: ${response.status}`, response.status);
39}
40}
44break; // Exit the loop if successful
45} catch (error) {
46console.log(`Error occurred while scraping URL: ${url}. Error details: ${error.message}`);
4748if (error.name === "TypeError" && error.message === "Failed to fetch") {
76/>
77<button type="submit" disabled={loading}>
78{loading ? "Scraping..." : "Scrape"}
79</button>
80</form>
130async function scrapePage(url) {
131console.log(`Starting to scrape page: ${url}`);
132const apiKey = await getApiKey();
133134url = normalizeUrl(url);
135console.log(`Normalized URL for scraping: ${url}`);
136137const extractRules = {
161};
162163const result = await scrapePageWithRules(url, apiKey, extractRules);
164return processResults(result);
165}
186}
187188class APIError extends Error {
189constructor(message, status) {
190super(message);
191this.name = "APIError";
192this.status = status;
193}
201}
202203async function scrapePageWithRules(url, apiKey, extractRules) {
204console.log(`Sending request to ScrapingBee API for URL: ${url}`);
205try {
206const response = await fetch(
207`https://app.scrapingbee.com/api/v1/?api_key=${apiKey}&url=${
208encodeURIComponent(url)
209}&render_js=true&json_response=true&extract_rules=${encodeURIComponent(JSON.stringify(extractRules))}`,
211212if (!response.ok) {
213throw new APIError(`HTTP error! status: ${response.status}`, response.status);
214}
215216console.log("Response received from ScrapingBee API");
217console.log(`Cost: ${response.headers.get("Spb-cost")}`);
218console.log(`Initial status code: ${response.headers.get("Spb-initial-status-code")}`);
226}
227228console.log("ScrapingBee API response parsed successfully");
229return result;
230} catch (error) {
231if (error instanceof TypeError) {
232console.error("Network error:", error.message);
233throw new NetworkError("Failed to connect to the API");
234} else if (error instanceof APIError) {
235console.error("API error:", error.message, "Status:", error.status);
236throw error;
237} else if (error instanceof ParsingError) {
286}
287288async function getApiKey() {
289const apiKey = Deno.env.get("ScrapingBeeAPIkey");
290if (!apiKey) {
291console.log("ScrapingBee API key not found in environment variables");
292throw new Error("ScrapingBee API key not found in environment variables");
293}
294return apiKey;
295}
296302const result = await scrapePage(url);
303console.log(`Successfully scraped URL: ${url}`);
304console.log(`Scraping completed for URL: ${url}
305Result summary:
306Title: ${result.title}
312console.log(`Error occurred while processing request. Error details: ${error.message}`);
313console.log(`Error stack trace: ${error.stack}`);
314console.error(`Error occurred during scraping operation:
315Error message: ${error.message}
316Stack trace: