diff --git a/src/grow.ts b/src/grow.ts index 5645cd7..94cf6d0 100644 --- a/src/grow.ts +++ b/src/grow.ts @@ -61,6 +61,7 @@ import { import { isLocalLocation, + locationDomain, makeAbsolute, packSeedReference, unpackSeedReference @@ -432,6 +433,12 @@ const growFetch = async (seed : Seed, env : Environment) : Promis let body = null; if (method != 'GET') body = extractString(await getProperty(seed, env, data.body, '')); + if (!isLocalLocation(seed.location)) { + const domain = locationDomain(resource); + const allowFetch = await seed.garden.profile.allowFetch(seed.location, domain); + if (!allowFetch) throw new Error(`User did not allow fetch from ${seed.location} to ${domain}`); + } + if (env.getKnownProtectedKey('mock')) { const data = { resource, diff --git a/src/profile.ts b/src/profile.ts index ede87c9..af8739f 100644 --- a/src/profile.ts +++ b/src/profile.ts @@ -10,9 +10,11 @@ import { EmbeddingModelID, LeafValue, MemoryID, + SeedPacketAbsoluteRemoteLocation, StoreID, StoreKey, - StoreValue + StoreValue, + URLDomain } from './types.js'; //When changing this also change environment.SAMPLE.json @@ -64,6 +66,12 @@ export class Profile{ _garden : Garden | undefined; + _allowedFetches : { + [packet : SeedPacketAbsoluteRemoteLocation]: { + [resourceDomain : string] : true + } + }; + _memories : { [id : MemoryID]: { embeddings: Embedding[] @@ -80,6 +88,7 @@ export class Profile{ constructor() { this._memories = {}; this._stores = {}; + this._allowedFetches = {}; } set garden(val : Garden) { @@ -99,6 +108,19 @@ export class Profile{ console.log(message, ...optionalParams); } + //Whether to allow fetch of a given location. + async allowFetch(remotePacketLocation : SeedPacketAbsoluteRemoteLocation, domain : URLDomain) : Promise { + if (this._allowedFetches[remotePacketLocation]) { + if (this._allowedFetches[remotePacketLocation][domain]) return true; + } + const question = `Do you want to allow a seed in ${remotePacketLocation} to fetch from domain ${domain}?`; + if (!confirm(question)) return false; + if (!confirm(`Do you want to save the choice to allow ${remotePacketLocation} to fetch from domain ${domain}?`)) return true; + if (!this._allowedFetches[remotePacketLocation]) this._allowedFetches[remotePacketLocation] = {}; + this._allowedFetches[remotePacketLocation][domain] = true; + return true; + } + async localFetch(_location : string) : Promise { throw new Error('localFetch is not supported on this profile type'); }