import thisHtml from './canvas.html'; import thisCss from './canvas.css'; import stylesCss from '../../styles.css'; import rootCss from '../../root.css'; import { clone, delay, extractErrorMsg, getUUID } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs"; import { IbGibAddr } from "@ibgib/ts-gib/dist/types.mjs"; import { ROOT } from "@ibgib/ts-gib/dist/V1/constants.mjs"; import { IbGib_V1 } from "@ibgib/ts-gib/dist/V1/types.mjs"; import { MetaspaceService } from "@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs"; import { tellUserFunctionInfo } from '@ibgib/web-gib/dist/api/commands/chat/tell-user.mjs'; import { getGlobalMetaspace_waitIfNeeded, } from "@ibgib/web-gib/dist/helpers.mjs"; import { IbGibDynamicComponentInstanceBase, IbGibDynamicComponentMetaBase } from "@ibgib/web-gib/dist/ui/component/ibgib-dynamic-component-bases.mjs"; import { IbGibDynamicComponentInstance, IbGibDynamicComponentInstanceInitOpts, } from "@ibgib/web-gib/dist/ui/component/component-types.mjs"; import { AgentWitnessAny, } from "@ibgib/web-gib/dist/witness/agent/agent-one-file.mjs"; import { getAgents } from "@ibgib/web-gib/dist/witness/agent/agent-helpers.mjs"; import { getAgentsSvc } from "@ibgib/web-gib/dist/witness/agent/agents-service-v1.mjs"; import { GEMINI_DEFAULT_MODEL_STR, } from "@ibgib/web-gib/dist/witness/agent/gemini/gemini-constants.mjs"; import { storageGet, } from "@ibgib/web-gib/dist/storage/storage-helpers.web.mjs"; import { GLOBAL_LOG_A_LOT, ARMY_STORE, BEE_KEY, BLANK_GIB_DB_NAME, } from "../../constants.mjs"; import { getRenderService, RenderService_V1 } from "../../render/render-service-v1.mjs"; import { getAppShellSvc } from "../../ui/shell/app-shell-service.mjs"; import { RenderAgentFunctionInfos } from "../../api/commands/renderable/renderable-index.mjs"; import { AGENT_INITIAL_SYSTEM_TEXT_CANVASAGENT } from "../../agent-texts/canvas-agent-texts.mjs"; import { getComponentCtorArg } from '../../helpers.web.mjs'; const logalot = GLOBAL_LOG_A_LOT; export const AGENT_SPECIAL_IBGIB_TYPE_CANVASAGENT = 'canvasagent'; export const CHAT_WITH_AGENT_PLACEHOLDER_CANVASAGENT = `Chat with the canvas agent. Ctrl+ENTER to send`; const AGENT_AVAILABLE_FUNCTIONS_CANVASAGENT = [ tellUserFunctionInfo, ...RenderAgentFunctionInfos, ]; export const CANVAS_COMPONENT_NAME: string = 'ibgib-canvas'; export class CanvasComponentMeta extends IbGibDynamicComponentMetaBase { protected override lc: string = `[${CanvasComponentMeta.name}]`; /** * temporary regexp path for our initial dev. this component will become * attached to actual ib^gib addrs */ routeRegExp?: RegExp = /apps\/projects\/gib\/canvas/; // routeRegExp?: RegExp = /apps\/web1\/gib\/contact.html/; componentName: string = CANVAS_COMPONENT_NAME; constructor() { super(getComponentCtorArg()); customElements.define(this.componentName, CanvasComponentInstance); } async createInstance({ // parentEl, path, ibGibAddr }: { // parentEl: HTMLElement; path: string; ibGibAddr: IbGibAddr; }): Promise { const lc = `${this.lc}[${this.createInstance.name}]`; try { if (logalot) { console.log(`${lc} starting... (I: baf75543b6da9f117ae76fc76703fd25)`); } const component = document.createElement(this.componentName) as CanvasComponentInstance; await component.initialize({ ibGibAddr, meta: this, html: thisHtml, css: [rootCss, stylesCss, thisCss], }); return component; } catch (error) { console.error(`${lc} ${extractErrorMsg(error)}`); throw error; } finally { if (logalot) { console.log(`${lc} complete.`); } } } } export interface CanvasComponentElements { canvasEl: HTMLCanvasElement; } export class CanvasComponentInstance extends IbGibDynamicComponentInstanceBase implements IbGibDynamicComponentInstance { protected override lc: string = `[${CanvasComponentInstance.name}]`; renderSvcId: string = ''; renderSvc: RenderService_V1 | undefined; metaspace: MetaspaceService | undefined; constructor() { super(); } override async initialize(opts: IbGibDynamicComponentInstanceInitOpts): Promise { const lc = `${this.lc}[${this.initialize.name}]`; try { if (logalot) { console.log(`${lc} starting... (I: b3964c3b9f3f5100870f1106226eb325)`); } // before any initialization, we want to ensure we are bootstrapped // await getIbGibGlobalThis_BlankGib().bootstrapPromise; // this is in the super call now await super.initialize(opts); } catch (error) { console.error(`${lc} ${extractErrorMsg(error)}`); throw error; } finally { if (logalot) { console.log(`${lc} complete.`); } } } override async created(): Promise { const lc = `${this.lc}[${this.created.name}]`; try { if (logalot) { console.log(`${lc} starting... (I: 3a2fe4eea594c46f8f84374461e12f25)`); } if (!this.shadowRoot) { throw new Error(`(UNEXPECTED) this.shadowRoot falsy? (E: 14bbf25a34e34cdc0c4f88fb423e2325)`); } await this.initElements(); this.agentsInitialized = this.initAgents(); // spins off if (!this.elements) { throw new Error(`(UNEXPECTED) this.elements falsy? (E: 52b66c20807577b74f2a87d93b719725)`); } const { canvasEl } = this.elements; this.renderSvcId ||= await getUUID(); this.renderSvc = getRenderService({ canvasEl, renderSvcId: this.renderSvcId, }); // const inputEl = this.shadowRoot.getElementById('canvas-agent-input') as HTMLTextAreaElement; // if (!inputEl) { throw new Error(`(UNEXPECTED) canvas-agent-input not found in this.shadowRoot? (E: 2cab312537c3b8c93e5aade8212ee825)`); } await this.agentsInitialized; await this.initInput(); await this.agent!.witness(ROOT); } catch (error) { console.error(`${lc} ${extractErrorMsg(error)}`); throw error; } finally { if (logalot) { console.log(`${lc} complete.`); } } } override async disconnected(): Promise { const lc = `${this.lc}[${this.disconnected.name}]`; try { if (logalot) { console.log(`${lc} starting... (I: 385596be521e5e859317324c9703e725)`); } // no action atow } catch (error) { console.error(`${lc} ${extractErrorMsg(error)}`); throw error; } finally { if (logalot) { console.log(`${lc} complete.`); } } } private async initElements(): Promise { const lc = `${this.lc}[${this.initElements.name}]`; try { if (logalot) { console.log(`${lc} starting... (I: f917e333013af9d7543e90dbbde18a25)`); } if (!this.shadowRoot) { throw new Error(`(UNEXPECTED) this.shadowRoot falsy? (E: 83348540068c2d607a77c631b1303825)`); } const canvasEl = this.shadowRoot.getElementById('ibgib-canvas') as HTMLCanvasElement; if (!canvasEl) { throw new Error(`(UNEXPECTED) canvasEl not found in this.shadowRoot? (E: 807ab134e7b602412a26abd35cd72b25)`); } this.elements = { canvasEl, } } catch (error) { console.error(`${lc} ${extractErrorMsg(error)}`); throw error; } finally { if (logalot) { console.log(`${lc} complete.`); } } } protected override async initAgents(): Promise { const lc = `${this.lc}[${this.initAgents.name}]`; try { if (logalot) { console.log(`${lc} starting... (I: 1963d663b5cfa8500df2799bbe71c125)`); } if (!this.elements) { throw new Error(`(UNEXPECTED) this.elements falsy? (E: 52b66c20807577b74f2a87d93b719725)`); } const { canvasEl } = this.elements; this.metaspace = await getGlobalMetaspace_waitIfNeeded(); console.warn(`${lc} always creating new canvas agent for now. todo: load previous canvas agent? (W: 549ebb2ff40ad408a410425151fd4925)`); let agent: AgentWitnessAny | undefined = undefined; let agents = await getAgents({ metaspace: this.metaspace, type: AGENT_SPECIAL_IBGIB_TYPE_CANVASAGENT, spaceId: undefined, // explicitly use default local space just to show this option bc it's early in life }); if (agents.length > 0) { agent = agents.at(0)!; } else { const agentsSvc = getAgentsSvc(); agent = await agentsSvc.createNewAgent({ metaspace: this.metaspace, superSpace: undefined, // uses default local user space as the super space name: `CanvasAgent-${this.instanceId}`, api: 'gemini', model: GEMINI_DEFAULT_MODEL_STR, availableFunctions: clone(AGENT_AVAILABLE_FUNCTIONS_CANVASAGENT), initialSystemText: [ AGENT_INITIAL_SYSTEM_TEXT_CANVASAGENT, // await getAgentSystemText({ agentType: 'canvas' }), `IMPORTANT: Your renderSvcId is ${this.renderSvcId}. Use this when you make render function calls!!`, `The size (width x height) of the canvas is ${canvasEl.width} x ${canvasEl.height}`, ].join('\n'), initialChatText: `Hi. Please introduce yourself as a canvas agent and give a very brief description of yourself. Choose a legit name, not some camelCase or other programming name, and not a name that sounds like a business name. Choose a real name, like a human, alien, and/or robbot name. And you can't use "Gemini"! ;-)`, // Initial chat message fnGetAPIKey: this.getFnGetAPIKey(), type: AGENT_SPECIAL_IBGIB_TYPE_CANVASAGENT, addToAgentsTag: true, }); } this.agents = [agent]; if (!this.agent) { throw new Error(`(UNEXPECTED) agent falsy after createNewAgent? (E: 6ea8e8b7aa551bcf467042dbabab9425)`); } } catch (error) { console.error(`${lc} ${extractErrorMsg(error)}`); throw error; } finally { if (logalot) { console.log(`${lc} complete.`); } } } private async initInput(): Promise { const lc = `${this.lc}[${this.initInput.name}]`; try { if (logalot) { console.log(`${lc} starting... (I: 4ffb333a2e89f51de4385b432ae69e25)`); } const appShellSvc = getAppShellSvc(); await appShellSvc.initialized; while (!appShellSvc.inputComponent) { console.log(`${lc} appShellSvc.inputComponent falsy. waiting until it's created. (I: b045c1f5ba4a94a66178ecbeec70c725)`); await delay(100); } await appShellSvc.inputComponent!.setContextInfo({ info: { agent: this.agent, placeholderText: CHAT_WITH_AGENT_PLACEHOLDER_CANVASAGENT, // default to default local user space for now spaceId: undefined, }, }); } catch (error) { console.error(`${lc} ${extractErrorMsg(error)}`); throw error; } finally { if (logalot) { console.log(`${lc} complete.`); } } } private getAPIKey(): Promise { const fn = this.getFnGetAPIKey(); return fn(); } private getFnGetAPIKey(): () => Promise { const lc = `${this.lc}[${this.getFnGetAPIKey.name}]`; try { if (logalot) { console.log(`${lc} starting... (I: 70797b0e43fe8be2ab9efc24b9abf725)`); } const fn = async () => { let apiKey = await storageGet({ dbName: BLANK_GIB_DB_NAME, storeName: ARMY_STORE, key: BEE_KEY, }); return apiKey ?? ''; }; return fn; } catch (error) { console.error(`${lc} ${extractErrorMsg(error)}`); throw error; } finally { if (logalot) { console.log(`${lc} complete.`); } } } }