{
  "version": 3,
  "sources": ["../../../libs/helper-gib/src/rcli/rcli-helper.mts", "../../../libs/core-gib/src/witness/space/outer-space/outer-space-types.mts", "../../../libs/core-gib/src/common/encrypt/encrypt-types.mts", "../../../libs/helper-gib/src/helpers/ssml-helper.mts", "../../../libs/helper-gib/src/helpers/lex-helper.mts", "../../../libs/core-gib/src/witness/robbot/robbot-types.mts", "../../../libs/core-gib/src/witness/robbot/robbot-helper.mts", "../../../libs/core-gib/src/common/secret/secret-constants.mts", "../../../libs/core-gib/src/witness/space/outer-space/outer-space-helper.mts", "../../../libs/core-gib/src/witness/space/metaspace/metaspace-base.mts", "../../../libs/core-gib/src/witness/space/filesystem-space/filesystem-constants.mts", "../../../libs/web-gib/src/common/prompt-functions.web.mts", "../../../libs/core-gib/src/witness/space/space-base-v1.mts", "../../../libs/core-gib/src/witness/space/filesystem-space/filesystem-space-v1.mts", "../../../libs/web-gib/src/witness/space/web-filesystem-space/web-filesystem-space-types.mts", "../../../libs/web-gib/src/witness/space/web-filesystem-space/web-filesystem-space-helper.mts", "../../../libs/web-gib/src/witness/space/web-filesystem-space/web-filesystem-space-v1.mts", "../../../libs/web-gib/src/witness/space/metaspace/metaspace-webspace/metaspace-webspace-helper.mts", "../../../libs/web-gib/src/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mts", "../../../libs/web-gib/src/app-bootstrap/bootstrap.mts", "../../../libs/core-gib/src/witness/app/app-types.mts", "../../../libs/core-gib/src/common/pic/pic-helper.mts", "../../../libs/core-gib/src/witness/app/app-base-v1.mts", "../src/witness/app/blank-canvas/blank-canvas-types.mts", "../src/witness/app/blank-canvas/blank-canvas-helper.mts", "../src/witness/app/blank-canvas/blank-canvas-helper.web.mts", "../src/agent-texts/primary-agent-texts.mts", "../src/witness/app/blank-canvas/blank-canvas-app-v1.mts", "../src/api/commands/ui/ui-index.mts", "../src/api/commands/website/fetch-web1-page.mts", "../src/api/commands/minigame/minigame-index.mts", "../src/api/function-infos.web.mts", "../src/bootstrap.mts"],
  "sourcesContent": ["/**\n * @module rcli-helper functions\n *\n * utilities to help enable rcli functionality, yeah, that's the ticket...\n */\n\nimport { clone, extractErrorMsg, pretty } from '../helpers/utils-helper.mjs';\nimport { RCLIArgInfo, RCLIArgType, RCLIParamInfo, RawArgInfo, } from \"./rcli-types.mjs\";\nimport { HELPER_LOG_A_LOT } from '../constants.mjs';\nimport { PARAM_INFO_BARE } from \"./rcli-constants.mjs\";\n\n\n/**\n * used in verbose logging\n */\nconst logalot = HELPER_LOG_A_LOT || false;\n\n/**\n * All incoming arg values are strings. This will convert that depending on the\n * parameter definition.\n *\n * ...hmm, unsure how to handle undefined just yet, even though that is a return type here...\n *\n * @returns casted/parsed value as a string/number/boolean value.\n */\nexport function getValueFromRawString<T extends RCLIArgType = string>({\n    paramInfo,\n    valueString,\n}: {\n    paramInfo: RCLIParamInfo;\n    valueString: string | undefined;\n}): T | undefined {\n    const lc = `[${getValueFromRawString.name}]`;\n    try {\n        switch (paramInfo.argTypeName) {\n            case 'string':\n                // no conversion required, but we need to strip the double-quotes if exist.\n                let castedValue = valueString as string;\n                if (\n                    (castedValue.startsWith(`\"`) && castedValue.endsWith(`\"`)) ||\n                    (castedValue.startsWith(`'`) && castedValue.endsWith(`'`))\n                ) {\n                    castedValue = castedValue.slice(1);\n                    castedValue = castedValue.slice(0, castedValue.length - 1);\n                }\n                return castedValue as T;\n            case 'integer':\n                // convert to a number\n                if (valueString === undefined) { throw new Error(`integer arg value is undefined. integers must be a valid integer string (E: ce17acde3b863ec5e2fdcc594f0f1423)`); }\n                const argValueInt = Number.parseInt(valueString);\n                if (typeof argValueInt !== 'number') { throw new Error(`arg value string (${valueString})did not parse to an integer. parse result: ${argValueInt} (E: 43cde93160458610ffb49fd16a02d123)`); }\n                return argValueInt as T;\n            case 'boolean':\n                // convert to a boolean\n                if (valueString === undefined || valueString === '') {\n                    if (!paramInfo.isFlag) { throw new Error(`valueString is undefined or empty string but paramInfo.argTypeName === 'boolean' and paramInfo.isFlag is falsy. (E: 482e595c0ec7344b04def76c1441d623)`); }\n                    // value is not provided, so the arg string is empty. the param is\n                    // a flag, so just its presence means the value is \"true\".\n                    return true as T;\n                } else if (valueString === null) {\n                    // ? is this even possible to get here?\n                    throw new Error(`(UNEXPECTED) valueString === null? (E: 78f548b93026407968356d9c4f106223)`);\n                } else {\n                    // typos will evaluate\n                    if (!['true', 'false'].includes(valueString)) {\n                        throw new Error(`invalid boolean valueString (\"${valueString}\"). must be either \"true\" or \"false\" (E: ba7a0d0804131acc2bd9ab37c0382523)`);\n                    }\n                    return (valueString === 'true') as T;\n                }\n            default:\n                throw new Error(`(UNEXPECTED) invalid paramInfo.argTypeName (E: c8b03ccb71394d22a29858b98753a123)`);\n        }\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\n/**\n * extracts the arg value(s) from the corresponding `paramInfo` from the given\n * `argInfos`.\n *\n * @returns the arg.value corresponding to the given `paramInfo`\n */\nexport function extractArgValue<T extends RCLIArgType>({\n    paramInfo,\n    argInfos,\n    throwIfNotFound,\n}: {\n    /**\n     * Param you're pulling from the args.\n     */\n    paramInfo: RCLIParamInfo,\n    /**\n     * the given arg infos from the request line.\n     */\n    argInfos: RCLIArgInfo<RCLIArgType>[],\n    /**\n     * If true, will throw an exception if the param is not found in the args,\n     * else just returns undefined.\n     */\n    throwIfNotFound?: boolean,\n}): T | T[] | undefined {\n    const lc = `[${extractArgValue.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: d376123d1e383f6323ef1fc6bb68f123)`); }\n\n        const filteredArgInfos = argInfos.filter(x => x.name === paramInfo.name || (x.synonyms ?? []).some(syn => (paramInfo.synonyms ?? []).includes(syn)));\n\n        if (logalot) { console.log(`${lc} filteredArgInfos: ${pretty(filteredArgInfos)} (I: a15831a9bf2930435960263c79d34323)`); }\n        if (filteredArgInfos.length === 0) {\n            if (throwIfNotFound) {\n                throw new Error(`param (name: ${paramInfo.name}) not found among args. (E: a74e41ca7de883f26f216a8d15ab7a23)`);\n            } else {\n                return undefined;\n            }\n        }\n\n        if (paramInfo.allowMultiple) {\n            // allow multiple args, so return type is T[]\n            if (paramInfo.isFlag) { throw new Error(`(UNEXPECTED) param (name: ${paramInfo.name}) is defined as allowMultiple and isFlag, which doesn't make sense. (E: 2854512470b2dde4b9a82fe225d22623)`); }\n            if (paramInfo.argTypeName === 'boolean') { throw new Error(`(UNEXPECTED) param (name: ${paramInfo.name}) is defined as allowMultiple and its type name is boolean, which doesn't make sense. (E: 259d77da25374726af4895eb19bb3041)`); }\n\n            if (filteredArgInfos.some(arg => arg.value !== 0 && !arg.value)) {\n                throw new Error(`param (name: ${paramInfo.name}) value is not 0 but is falsy. (E: e5af23465f6920a2ff6be7b7d49ef123)`);\n            }\n            return filteredArgInfos.map(arg => arg.value as T);\n\n        } else {\n            // allow only single arg, so return type is T\n            if (filteredArgInfos.length > 1) { throw new Error(`param (name: ${paramInfo.name}) had multiple args but param.allowMultiple is falsy. (E: 0d01157e773bd34f962f8713e7719c23)`); }\n\n            const argInfo = filteredArgInfos[0] as RCLIArgInfo<T>;\n\n            // if the flag is set but no `=\"true\"` or `=\"false\"` provided, then\n            // we set the value to true\n            if (paramInfo.isFlag && argInfo.value === undefined) {\n                if (paramInfo.argTypeName !== 'boolean') {\n                    throw new Error(`(UNEXPECTED) paramInfo.isFlag is true but argTypeName !== 'boolean' (E: 79a86d0c6ef4c7740aa84211ebadbb23)`);\n                }\n                argInfo.value = true as T;\n            }\n\n            if (logalot) { console.log(`argInfo.value: ${argInfo.value}`) }\n\n            return argInfo.value;\n        }\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * gets the paramInfo corresponding to the given argIdentifier\n * @returns paramInfo from given `paramInfos` or undefined if not found\n */\nexport function getParamInfo({\n    argIdentifier,\n    paramInfos,\n    throwIfNotFound,\n}: {\n    /**\n     * arg identifier is either a name or a synonym. atow only a name.\n     */\n    argIdentifier: string;\n    /**\n     * All possible param infos that the given arg identifier could be.\n     */\n    paramInfos: RCLIParamInfo[];\n    throwIfNotFound?: boolean;\n}): RCLIParamInfo | undefined {\n    const lc = `[${getParamInfo.name}]`;\n    try {\n        const filteredParamInfos = paramInfos.filter(p => p.name === argIdentifier || (p.synonyms ?? []).includes(argIdentifier));\n\n        if (filteredParamInfos.length === 1) {\n            return clone(filteredParamInfos[0]);\n        } else if (filteredParamInfos.length > 1) {\n            throw new Error(`(UNEXPECTED) multiple param infos found with argIdentifier. do you have overlapping arg names/synonyms? (${argIdentifier} found in (${filteredParamInfos.length} param infos)) (E: d599a6647c5ead6d9fbac4e4c96e6d23)`);\n        } else {\n            if (throwIfNotFound) {\n                throw new Error(`(UNEXPECTED) param info not found for argIdentifier (${argIdentifier}) (E: 47e704068f2eb5a0551cf45d0e72c823)`);\n            } else {\n                return undefined;\n            }\n        }\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\n/**\n * helper that parses a raw arg e.g. 'bare-arg', '--double-dashed-arg',\n * '-single-dashed-arg', ':command-arg', etc.\n */\nexport function parseRawArg({\n    rawArg,\n}: {\n    rawArg: string,\n}): RawArgInfo {\n    const lc = `[${parseRawArg.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 5d51b75b7a025e2e3fa498da7c08ac24)`); }\n\n        const fnGetQuoteType: (s: string) => \"single\" | 'double' | undefined = (s) => {\n            if (s.startsWith('\"') && s.endsWith('\"')) {\n                return 'double';\n            } else if (s.startsWith(\"'\") && s.endsWith(\"'\")) {\n                return \"single\";\n            } else {\n                return undefined;\n            }\n        }\n\n        const fnStripQuotes: (s: string) => string = (s) => {\n            if (fnGetQuoteType(s)) {\n                return s.slice(0, s.length - 1).slice(1);\n            } else {\n                return s;\n            }\n        }\n\n        /**\n         * if falsy, a name=value form may still have value quoted\n         */\n        const rawArgQuoteMaybe = fnGetQuoteType(rawArg);\n\n        if (rawArgQuoteMaybe) {\n            // entire raw arg is bare and surrounded by quotes\n            return {\n                prefix: undefined,\n                identifier: undefined,\n                isNameValuePair: false,\n                valueInfo: {\n                    rawValueString: rawArg.concat(),\n                    resolvedValueString: fnStripQuotes(rawArg),\n                    singleQuoted: rawArgQuoteMaybe === 'single',\n                    doubleQuoted: rawArgQuoteMaybe === 'double',\n                },\n            }\n        } else if (rawArg.match(/^(--\\w|-\\w|:\\w)/)) {\n            // not quoted but starts with a prefix (non-word character), so not\n            // bare. if it has an equal sign, then is definitely name=value with\n            // possible quoted value.\n            if (rawArg.includes('=')) {\n                // raw arg is --name=value, name=value and value may be quoted\n                /**\n                 * starts with prefix, then identifier, then equals sign, then possibly quoted value\n                 */\n                const regexp = /^(--|-|:)([\\w\\-]+)=(['\"]?.+['\"]?)$/;\n                let regExpMatch = rawArg.match(regexp);\n                if (!regExpMatch) { throw new Error(`invalid rawArg (${rawArg}). expected an arg matching regexp ${regexp}. (E: 05ca56163e184faeb66456a0e9190b28)`); }\n\n                const [_entireArg, prefix, identifier, possiblyQuotedValue] = regExpMatch;\n                const valueQuoteMaybe = fnGetQuoteType(possiblyQuotedValue);\n                return {\n                    prefix,\n                    identifier,\n                    isNameValuePair: true,\n                    valueInfo: {\n                        rawValueString: possiblyQuotedValue,\n                        resolvedValueString: !!valueQuoteMaybe ? fnStripQuotes(possiblyQuotedValue) : possiblyQuotedValue,\n                        singleQuoted: valueQuoteMaybe === 'single',\n                        doubleQuoted: valueQuoteMaybe === 'double',\n                    },\n                };\n            } else {\n                // starts with prefix but no name=value - so is a boolean flag\n                const regexp = /^(--|-|:)([\\w\\-]+)$/;\n                let regExpMatch = rawArg.match(regexp);\n                if (!regExpMatch) { throw new Error(`invalid rawArg (${rawArg}). expected an arg matching regexp ${regexp}. at this point, it should have a prefix (e.g. \"--\"), and a single identifier (should be a flag since there is no equal sign). (E: 93305923465d9449bdce3f81373fae24)`); }\n                const [_entireArg, prefix, bareArg] = regExpMatch;\n                return {\n                    prefix,\n                    identifier: bareArg,\n                    isNameValuePair: false,\n                    valueInfo: {\n                        rawValueString: undefined,\n                        resolvedValueString: 'true',\n                        singleQuoted: false,\n                        doubleQuoted: false,\n                    }\n                }\n            }\n        } else if (rawArg.includes('=')) {\n            throw new Error(`invalid rawArg (${rawArg}). isn't quoted, doesn't start with prefix, but it does have an equal sign? that's bad. (E: e8ad15211ce6fd56a4a214c2778c4724)`);\n        } else {\n            // bare but not quoted. this could be either the identifier/name or\n            // the value. only the caller knows how to interpret this.\n            return {\n                prefix: undefined,\n                identifier: undefined,\n                isNameValuePair: false,\n                valueInfo: {\n                    rawValueString: rawArg,\n                    resolvedValueString: rawArg,\n                    doubleQuoted: false,\n                    singleQuoted: false,\n                },\n            }\n        }\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * helper that checks a raw arg (including any dashes) against a parameter\n * definition.\n *\n * @returns true if the arg is the given paramInfo, else false\n */\nexport function argIs({ arg, paramInfo, argInfoIndex, }: {\n    /**\n     * raw arg string, including dash(es)\n     */\n    arg: string,\n    /**\n     * param you're checking against the raw arg value.\n     */\n    paramInfo: RCLIParamInfo,\n    /**\n     * positional index in argInfos. used in interpreting bare args.\n     *\n     * if it's the first arg and bare, then it's a command identifier. If it's a\n     * different position and bare, then it's the bare arg value.\n     */\n    argInfoIndex: number,\n}): boolean {\n    const rawArgInfo = parseRawArg({ rawArg: arg });\n    let identifier: string;\n    if (rawArgInfo.prefix) {\n        if (!rawArgInfo.identifier) { throw new Error(`rawArgInfo.prefix truthy but rawArgInfo.identifier falsy? (E: b53cf8d2f26b84e3d7f6351d7b2ebc24)`); }\n        identifier = rawArgInfo.identifier.toLowerCase();\n    } else if (argInfoIndex === 0) {\n        // bare arg. if it's position index === 0, then it's a command identifier.\n        if (!rawArgInfo.valueInfo?.rawValueString) { throw new Error(`(unexpected) argInfoIndex === 0 and prefix falsy, but !rawArgInfo.valueInfo?.rawValueString? (E: 1c237f304dc54505e94846eeb16e0124)`); }\n        identifier = rawArgInfo.valueInfo.rawValueString;\n    } else {\n        // bare arg but not first position\n        identifier = PARAM_INFO_BARE.name;\n    }\n    const nameMatches = identifier === paramInfo.name.toLowerCase();\n    if (nameMatches) {\n        // no need to check synonyms\n        return true; /* <<<< returns early */\n    } else if ((paramInfo.synonyms ?? []).length > 0) {\n        // check synonyms\n        return paramInfo.synonyms!.some(x => x.toLowerCase() === identifier);\n    } else {\n        // no synonyms and name didn't match\n        return false;\n    }\n}\n\n/**\n * This takes incoming raw `args` and parameter definitions and\n * creates arginfos based on the given args.\n * @returns argInfos that include values based on given raw args\n */\nexport function buildArgInfos<T extends RCLIArgType = string>({\n    args,\n    paramInfos,\n    bareArgParamInfo = clone(PARAM_INFO_BARE),\n    logalot: localLogalot,\n}: {\n    /**\n     * array of raw args, including dashes\n     */\n    args: string[],\n    /**\n     * parameter set of all possible parameters\n     */\n    paramInfos: RCLIParamInfo[],\n    /**\n     * provides the param info to use when encountering a \"bare arg\".\n     *\n     * there can be one bare arg in the RCLI args list. This is an arg that does\n     * not start with the `--` prefix. When a bare arg is received, you must\n     * specify which param to map this to, because we don't have a param\n     * identifer (param name or synonym).\n     */\n    bareArgParamInfo?: RCLIParamInfo,\n    /**\n     * if you want to use verbose logging, set this to true\n     */\n    logalot?: boolean,\n}): RCLIArgInfo<T>[] {\n    const lc = `[${buildArgInfos.name}]`;\n    try {\n        if (logalot || localLogalot) { console.log(`${lc} starting... (I: f389aaa490796dfd823bc7b9d4e58b23)`); }\n\n        /**\n         * the first positional arg can be bare and one additional non-positional arg can be bare.\n         *\n         * if a non-positional bare arg is found and we then find another one, then we gotta throw\n         */\n        let nonPositionalBareArgFound = false;\n\n        const argInfos = args.map((arg: string, argIndex: number) => {\n            let argIdentifier: string;\n            let valueString: string;\n            let argInfo: RCLIArgInfo<T>;\n            const { prefix, identifier, isNameValuePair, valueInfo } = parseRawArg({ rawArg: arg });\n            if (prefix) {\n                // normal arg prefixed with --, -, :, etc.\n                if (logalot || localLogalot) { console.log(`identifier: ${identifier} (I: 519ce129a1e34753a9070d3a205c9a8b)`); }\n                if (!identifier) { throw new Error(`(UNEXPECTED) prefix truthy but identifier falsy? (E: f33ab3a2b623acc0d1bc36685edfaf24)`); }\n\n                argIdentifier = identifier;\n                if (!valueInfo) { throw new Error(`(UNEXPECTED) !valueInfo? (E: 05249a361a59008cd313d2dfa8f08b24)`); }\n\n                if (isNameValuePair) {\n                    if (logalot) { console.log(`${lc} identifier with equals: ${identifier}. (I: 5f8ae91d1ddd4a7f94c0f4fb7e688502)`) }\n                    // [argIdentifier, valueString] = identifier.split('=');\n\n                    const paramInfo = getParamInfo({ argIdentifier, paramInfos, throwIfNotFound: true })!;\n                    argInfo = {\n                        ...paramInfo,\n                        value: getValueFromRawString<T>({ paramInfo, valueString: valueInfo.rawValueString }),\n                        identifier: argIdentifier,\n                    }\n                } else {\n                    if (logalot) { console.log(`${lc} identifier without equals: ${identifier}`) }\n                    argIdentifier = identifier;\n                    const paramInfo = getParamInfo({ argIdentifier, paramInfos, throwIfNotFound: true })!;\n                    argInfo = {\n                        ...paramInfo,\n                        value: getValueFromRawString<T>({ paramInfo, valueString: undefined }),\n                        identifier: argIdentifier,\n                        isFlag: true, // should be the same in paramInfo, but being explicit here\n                    }\n                }\n            } else if (argIndex === 0) {\n                // bare arg, but it's in the first position.  the first arg must\n                // be a command/flag (or a scope-limiting flag that acts\n                // essentially the same as a command) so we interpret this as\n                // the identifier.\n                if (!valueInfo) { throw new Error(`(UNEXPECTED) argIndex === 0 but valueInfo falsy? (E: 4642b42c855593b7ffdacb85f27dab24)`); }\n                if (!valueInfo.rawValueString) { throw new Error(`(UNEXPECTED) !valueInfo.rawValueString? (E: 0b35f71eb8227cdd67ccfc32f2e45824)`); }\n                if (valueInfo.singleQuoted) { throw new Error(`first arg is quoted? (single). a bare arg in first position must be a command/flag. (E: 28cce820417fd3b4f95ba6c7e94b4624)`); }\n                if (valueInfo.doubleQuoted) { throw new Error(`first arg is quoted? (double). a bare arg in first position must be a command/flag. (E: 0b948c87081043fdb168f08ba05ebbce)`); }\n                argIdentifier = valueInfo.rawValueString;\n                const paramInfo = getParamInfo({ argIdentifier, paramInfos, throwIfNotFound: true })!;\n                argInfo = {\n                    ...paramInfo,\n                    value: true as any,\n                    identifier: argIdentifier,\n                    isFlag: true, // should be the same in paramInfo, but being explicit here\n                }\n            } else {\n                // bare arg found and it's not in the first position\n                if (logalot || localLogalot) { console.log(`bare arg found. (I: d6f67074c7e44a63864948d4bf04bee8)`); }\n                if (!bareArgParamInfo) { throw new Error(`bare arg found (one without prefix like \"--\" or \":\") but there is no param info expected for bare args. You must provide which param info a bare arg maps to in this ${buildArgInfos.name} call. (E: 650dd3695d62f0f87dd0cbafbf068c23)`); }\n                if (nonPositionalBareArgFound) { throw new Error(`You can have the first arg - a special arg like a command - be bare (without prefix like \"--\" or \":\") and one additional non-positional arg be bare. But more than one non-positional bare arg found. Also remember if the arg has spaces then you have to enclose it with single or double quotes.  (E: 74dea8f13f0c14e3b7a2f125c7faca23)`); }\n                nonPositionalBareArgFound = true;\n                const paramInfo = clone(bareArgParamInfo) as RCLIParamInfo;\n                argInfo = {\n                    ...paramInfo,\n                    isBare: true,\n                    identifier: paramInfo.name, // not strictly true but the isBare indicates this\n                    value: getValueFromRawString<T>({ paramInfo, valueString: arg }),\n                };\n            }\n            if (logalot) { console.log(`${lc} argInfo: ${pretty(argInfo)}`); }\n            return argInfo!;\n        });\n        return argInfos;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot || localLogalot) { console.log(`${lc} complete.`); }\n    }\n}\n", "/**\n * @module outer-space\n * Outer spaces are spaces connecting local inner spaces.\n * ATOW there is just sync spaces, but definitely just the beginning.\n *\n * ## on future implementations, CRDT-like behavior\n *\n * I just realized that when merging, I can actually create a meta transform\n * ibgib to maintain the order of transforms.\n */\n\nimport { IbGibRel8ns_V1, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/index.mjs';\nimport { IbGibAddr, IbGib, Gib, Ib, } from '@ibgib/ts-gib/dist/types.mjs';\n\nimport {\n    IbGibSpaceData, IbGibSpaceRel8ns,\n    IbGibSpaceOptionsData, IbGibSpaceOptionsRel8ns, IbGibSpaceOptionsIbGib,\n    IbGibSpaceOptionsCmdModifier,\n    IbGibSpaceResultData, IbGibSpaceResultRel8ns, IbGibSpaceResultIbGib, SyncSpaceSubtype, SpaceType, SpaceSubtype,\n} from '../space-types.mjs';\nimport { IbGibSpaceAny } from '../space-base-v1.mjs';\nimport { CIPHERTEXT_REL8N_NAME } from '../../../common/encrypt/encrypt-constants.mjs';\nimport { SubjectWitness } from '../../../common/pubsub/subject/subject-types.mjs';\nimport { SubscriptionWitness } from '../../../common/pubsub/subscription/subscription-types.mjs';\n\n/**\n * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n *\n * ## driving use case\n *\n * I'm adding this for tracking status for longer-running inter-spatial\n * communications. Specifically, I'm working on the first aws dynamo db\n * sync space.\n *\n * ## notes\n *\n * * I think http status codes do a pretty good job of protocol information\n *   exchange.\n * * The only non-standard status code I'm doing ATOW is 0 meaning \"undefined\".\n * * I'm adding (whitelisting) codes as I use them.\n *   * Note that sections of code check for validation of membership here and\n *     will error if not present.\n */\nexport type StatusCode =\n    'undefined' |\n    'preparing' |\n    'started' |\n    'inserted' | 'updated' |\n    'merged_dna' | 'merged_state' |\n    'already_synced' |\n    'completed';\nexport const StatusCode = {\n    /**\n     * Using this as the code for the parent primitive.\n     */\n    undefined: 'undefined' as StatusCode,\n    /**\n     * gt\n     */\n    preparing: 'preparing' as StatusCode,\n    /**\n     * Communication between spaces has just started, but no evaluation as to\n     * intrinsic ibgibs shared has been made.\n     *\n     * Using this for the start of the sync process, meaning the ball has begun\n     * rolling, a metadata ibgib to track the operation has been created (but\n     * not necessarily yet stored), but no intrinsic (non-meta) data has been\n     * exchanged.\n     */\n    started: 'started' as StatusCode,\n    /**\n     * New insertion of ibgib(s) into the outerspace.\n     *\n     * The outerspace did not have the timeline or ibgib(s) at all, so this is\n     * the first time.\n     */\n    inserted: 'inserted' as StatusCode,\n    /**\n     * Updated outerspace with local ibgib(s).\n     *\n     * The outerspace had the same timeline as the local space, just not as\n     * recent.\n     */\n    updated: 'updated' as StatusCode,\n    /**\n     * When syncing, this means that we've reconciled one or more timeline(s)\n     * between the local and sync spaces. The process of this was by\n     * automatically applying dna ibgibs that did not exist in one or the other\n     * timelines, so that the end result is that the dna at the end is\n     * \"effectively equal\". this does not guarantee order, it only guarantees\n     * application.  anything sensitive to order must be done with locality.\n     *\n     * Note that in this case, we've created new ibgib to fulfill the operation\n     * (besides the derivative metadata ibgibs created in the communication).\n     * These ibgibs should be found on the status ibgib.\n     *\n     * @see {@link merged_state}\n     */\n    merged_dna: 'merged_dna' as StatusCode,\n    /**\n     * Similar to {@link merged_dna}, but we didn't have dna to work with. So we\n     * fudged and did our best guess at merging the state using some opinionated\n     * algorithms.\n     *\n     * Note that in this case, we've created new ibgib to fulfill the operation\n     * (besides the derivative metadata ibgibs created in the communication).\n     * These ibgibs should be found on the status ibgib.\n     *\n     * @see {@link merged_dna}\n     */\n    merged_state: 'merged_state' as StatusCode,\n    /**\n     * The operation has completed, but there were no intrinsic changes.\n     *\n     * For example, if we were to sync an ibGib but it's already up-to-date in a\n     * space, then we have generated metadata ibgibs. But *intrinsically* we have\n     * not altered any timeline ibgibs or added any stone ibgibs.\n     */\n    already_synced: 'already_synced' as StatusCode,\n    /**\n     * Inter-spatial communication complete.\n     *\n     * * There should be no more status updates after this.\n     * * syncStatus$ observable should be completed just after this.\n     * * subscribers should unsubscribe if not already done.\n     *   * I think this happens at the publishing end also, but always good\n     *     to take care of your own cleanup if possible.\n     *\n     */\n    completed: 'completed' as StatusCode,\n}\n\nexport interface OuterSpaceData extends IbGibSpaceData {\n}\n\nexport interface OuterSpaceRel8ns extends IbGibSpaceRel8ns {\n    /**\n     * the ciphertext will contain private data that is typed per use case (per\n     * concrete implementation).\n     */\n    [CIPHERTEXT_REL8N_NAME]?: IbGibAddr[];\n}\n\n/**\n *\n */\nexport interface OuterSpaceIbGib\n    extends IbGib_V1<OuterSpaceData, OuterSpaceRel8ns> {\n}\n\nexport interface SyncSpaceData extends OuterSpaceData {\n    type: 'sync';\n    subtype: SyncSpaceSubtype;\n    /**\n     * if true, this sync space will NOT store status updates **IN THE SYNC\n     * SPACE** as the sync saga progresses.\n     *\n     * the **local space** will still store the status ibgib updates.\n     *\n     * ## notes\n     *\n     * ideally, it would be useful to always store status updates in order to\n     * see the history of the transaction. in the future we will have an expiry\n     * or ttl. another option is to have this setting configurable from the\n     * calling function, or more complex participant requirements. for now we\n     * have this stopgap boolean flag.\n     *\n     * ## intent\n     *\n     * i want to be able to run tests against aws that are less expensive, as\n     * long as we are ultimately testing both...\n     *\n     * 1. storing status updates\n     *   * preferable for auditing/debugging and long-term cost reduction\n     * 2. not storing status updates\n     *   * preferable for short-term performance and short-term cost reduction\n     *\n     * @default should be false\n     */\n    dontStoreStatusUpdatesInSyncSpace: boolean;\n}\nexport interface SyncSpaceRel8ns extends OuterSpaceRel8ns {\n}\nexport interface SyncSpaceIbGib\n    extends IbGib_V1<SyncSpaceData, SyncSpaceRel8ns> {\n}\n\n/**\n * this is the info about the **space**, as in the space participates in the\n * synchronization saga.\n */\nexport interface ParticipantInfo {\n    /**\n     * space.data.uuid\n     */\n    id: string;\n    /**\n     * space's gib\n     */\n    gib: Gib;\n    /**\n     * s = src, d = destination\n     *\n     * so this is discriminator of source or destination in terms of the\n     * participant's role.\n     */\n    s_d: 'src' | 'dest';\n}\n\n/**\n * Options shape specific to OuterSpaces.\n * Marker interface only atm.\n */\nexport interface OuterSpaceOptionsData extends IbGibSpaceOptionsData {\n    /**\n     * Operation id across multiple spaces.\n     *\n     * ## notes\n     *\n     * If src/local space is communicating with more than one\n     * other space, then this can be used to coordinate among\n     * all of them. If there are only two spaces, then the\n     * gib of the individual status ibgib is just as uniquely\n     * identifying.\n     */\n    multiSpaceOpId?: string;\n    /**\n     * Modifying flags for cmd routing for the associated cmd ibGib.\n     */\n    cmdModifiers?: (OuterSpaceOptionsCmdModifier | string)[];\n    /**\n     * This id is used when communicating between two spaces.  During that\n     * communication, multiple ibgibs will be passed back and forth, and this\n     * `sagaId` will be common among those messages.\n     *\n     * There is also an id that is common to operations that\n     * refer to multiple spaces. {@see multiSpaceOpId}\n     */\n    sagaId?: string;\n    /**\n     * Info of the participating spaces (as endpoints) in the communication.\n     */\n    participants?: ParticipantInfo[];\n}\n\nexport interface OuterSpaceOptionsRel8ns extends IbGibSpaceOptionsRel8ns {\n}\nexport interface OuterSpaceOptionsIbGib<\n    TIbGib extends IbGib = IbGib_V1,\n    TOptsData extends OuterSpaceOptionsData = OuterSpaceOptionsData,\n    // TOptsRel8ns extends IbGibSpaceOptionsRel8ns = IbGibSpaceOptionsRel8ns\n    TOptsRel8ns extends OuterSpaceOptionsRel8ns = OuterSpaceOptionsRel8ns,\n> extends IbGibSpaceOptionsIbGib<TIbGib, TOptsData, TOptsRel8ns> {\n}\n\nexport interface OuterSpaceResultData extends IbGibSpaceResultData {\n    /**\n     * If the space operation involves a saga, this is the id.\n     */\n    sagaId?: string;\n}\nexport interface OuterSpaceResultRel8ns extends IbGibSpaceResultRel8ns {\n}\nexport interface OuterSpaceResultIbGib<\n    TIbGib extends IbGib,\n    TResultData extends OuterSpaceResultData,\n    TResultRel8ns extends OuterSpaceResultRel8ns\n> extends IbGibSpaceResultIbGib<TIbGib, TResultData, TResultRel8ns> {\n}\n\n/**\n * Marker atm.\n *\n * {@see IbGibSpaceOptionsCmdModifier}\n */\nexport type OuterSpaceOptionsCmdModifier = IbGibSpaceOptionsCmdModifier;\n/**\n * Marker atm.\n *\n * {@see IbGibSpaceOptionsCmdModifier}\n */\nexport const OuterSpaceOptionsCmdModifier = {\n    ...IbGibSpaceOptionsCmdModifier,\n}\n\n/**\n * Extends basic ibgib space options cmd modifiers to include sync specific ones.\n *\n * {@see IbGibSpaceOptionsCmdModifier}\n * {@see OuterSpaceOptionsCmdModifier}\n */\nexport type SyncSpaceOptionsCmdModifier = OuterSpaceOptionsCmdModifier | 'sync';\n/**\n * Flags to affect the command's interpretation.\n *\n * {@see IbGibSpaceOptionsCmdModifier}\n * {@see OuterSpaceOptionsCmdModifier}\n */\nexport const SyncSpaceOptionsCmdModifier = {\n    ...OuterSpaceOptionsCmdModifier, // \"inherited\"\n    /**\n     * special type of 'put' operation that will start a sync process.\n     */\n    sync: 'sync' as SyncSpaceOptionsCmdModifier,\n}\n\nexport interface SyncSpaceOptionsData extends OuterSpaceOptionsData {\n    /**\n     * Extends inherited\n     */\n    cmdModifiers?: (SyncSpaceOptionsCmdModifier | string)[];\n    /**\n     * Each Sync has a status ibGib that tracks the progress of the\n     * overall sync operation (saga).\n     *\n     *\n     * If this is specified, then it means the sync cmd is associated with\n     * an existing/ongoing operation.\n     */\n    tjpGib?: Gib;\n    // txId?: string;\n    /**\n     * tjp addrs of all timelines that are to be synced in the sync transaction.\n     */\n    ibGibAddrs_All_Tjps?: IbGibAddr[];\n    /**\n     * all addrs of non-tjp (stones) that are to be synced.\n     *\n     * this is essentially a replication process, i.e., either it has it or it\n     * doesn't.\n     */\n    ibGibAddrs_All_NonTjps?: IbGibAddr[];\n}\nexport interface SyncSpaceOptionsRel8ns extends OuterSpaceOptionsRel8ns {\n}\n/**\n * options ibgib (argument ibgib) sent to a sync space.\n */\nexport interface SyncSpaceOptionsIbGib<\n    TIbGib extends IbGib = IbGib_V1,\n    TOptsData extends SyncSpaceOptionsData = SyncSpaceOptionsData,\n    TOptsRel8ns extends SyncSpaceOptionsRel8ns = SyncSpaceOptionsRel8ns,\n> extends OuterSpaceOptionsIbGib<TIbGib, TOptsData, TOptsRel8ns> {\n    /**\n     * Produces status ibgibs or error strings.\n     */\n    syncSagaInfo: SyncSagaInfo;\n}\n\nexport interface SyncSpaceResultData extends OuterSpaceResultData {\n    statusTjpAddr?: IbGibAddr;\n}\nexport interface SyncSpaceResultRel8ns extends OuterSpaceResultRel8ns {\n}\n/**\n * result ibgib (return) from a syncspace.witness(syncOptionsIbGib) call.\n */\nexport interface SyncSpaceResultIbGib<\n    TIbGib extends IbGib = IbGib_V1,\n    TResultData extends SyncSpaceResultData = SyncSpaceResultData,\n    TResultRel8ns extends SyncSpaceResultRel8ns = SyncSpaceResultRel8ns\n> extends OuterSpaceResultIbGib<TIbGib, TResultData, TResultRel8ns> {\n    /**\n     * Produces status ibgibs or error strings.\n     */\n    syncSagaInfo: SyncSagaInfo;\n}\n\n/**\n * status info on the sync process.\n */\nexport interface SyncStatusData {\n    /**\n     * Status code for this status update.\n     *\n     * Note that this is also in the ib, which will be in each of the\n     * statuses' `past` rel8n. This way, callers can easily tell which\n     * kinds of actions were required.\n     */\n    statusCode: StatusCode;\n\n    // /**\n    //  * unused?\n    //  */\n    // syncGib: string;\n\n    // srcSpaceId: string;\n    // srcSpaceGib: string;\n    participants: ParticipantInfo[];\n\n    /**\n     * Explicit re-declaration from base data, just to remind us...I guess...\n     *\n     * This indicates if this status ibgib is the tjp for the status line.\n     */\n    isTjp?: boolean;\n\n    /**\n     * When putting, this is the list of ibGibs to send.\n     *\n     * ## notes\n     *\n     * Maybe the receiver needs all of these, maybe it doesn't.\n     */\n    toTx?: IbGibAddr[];\n    /**\n     * When putting, this is the list of ibGibs we don't need/want (or refuse)\n     * to send.\n     *\n     * IGNORED ATOW\n     *\n     * ## notes\n     *\n     * Not really sure about this atow, since the aws-dynamo space is not a true\n     * communication between two separate nodes. Just figure someone will have a\n     * reason for it in the future.\n     */\n    notToTx?: IbGibAddr[];\n    /**\n     * When communicating, the receiver is asking the sender for\n     * these ibGibs.\n     *\n     * ## notes\n     *\n     * ATOW this indicates only that the receiver does not have\n     * these addresses.\n     */\n    toRx?: IbGibAddr[];\n    /**\n     * A receiving space can set this to indicate to the transmitter that it\n     * does not need/want these, possibly because they already have them or just\n     * are not interested in them.\n     *\n     * ## notes\n     *\n     * ATOW this will only be because the receiver already has these addresses.\n     */\n    notToRx?: IbGibAddr[];\n\n    /**\n     * Flag to indicate that THIS STEP in communication (part of a saga) had no\n     * errors.\n     */\n    success?: boolean;\n\n    /**\n     * If this is true, then the tx/rx inter-space saga is marked\n     * as complete and this status ibgib should be the last one.\n     */\n    complete?: boolean;\n    /**\n     * List of warnings for THIS STEP in the inter-spatial communication.\n     *\n     * Should NOT be an accumulating list of warnings, i.e., if a warning\n     * happens early on in a tx/rx, then it stays on that ibGib.\n     */\n    warnings?: string[];\n    /**\n     * List of errors for THIS STEP in the inter-spatial communication.\n     *\n     * Should NOT be an accumulating list of errors, i.e., if an error happens\n     * early on in a tx/rx, then it stays on that ibGib.\n     *\n     * ## notes\n     *\n     * atow my error workflow is pretty minimal. So I think if any error happens\n     * the entire saga gets nixed...\n     *\n     * But it should be that this type of behavior should be determined by\n     * on-chain ibgibs that correspond to consensus behavior contracts (with a\n     * default behavior ultimately existing hard-coded in source).\n     */\n    errors?: string[];\n\n    /**\n     * List of ibgib addrs that were newly created specifically for this\n     * space operation.\n     *\n     * ATOW, this means that there was a merged timeline event and\n     * the receiving space dynamically applied dna to its existing\n     * timeline.\n     *\n     * ## notes\n     *\n     * * This should not include status metadata ibgibs, as this is\n     *   already captured in the `past` rel8n.\n     */\n    didCreate?: IbGibAddr[];\n    /**\n     * List of ibgib addrs that were merged in the rx space instead of stored\n     * directly.\n     *\n     * Tx space may choose to somehow mark these as orphaned or whatever seems\n     * best per use case. (i.e. I haven't coded that yet even in this naive\n     * first implementation)\n     */\n    didMergeMap?: { [oldAddr: string]: IbGibAddr };\n    /**\n     * List of ibgibs that were actively transmitted to the receiving\n     * space.\n     *\n     * ## notes\n     *\n     * * It could be that the receiving space received the ibgib,\n     *   but that it already had it. It may have been unsure if it\n     *   had it based on the algorithms in play.\n     * * An empty array upon completion of a communication saga\n     *   indicates that the receiving space already had all of the\n     *   ibgibs attempted to be sent, i.e., it was already up-to-date.\n     *\n     */\n    didRx?: IbGibAddr[];\n    /**\n     * List of ibgibs that were actively transmitted from the receiving\n     * space to the sending space.\n     *\n     * ## notes\n     *\n     * * During a sync operation, any ibgibs that start in the sync space\n     *   and are \"sent\" to the local space during the sync operation that\n     *   did not originate from the local space will be here.\n     */\n    didTx?: IbGibAddr[];\n}\n\nexport interface SyncStatusRel8ns extends IbGibRel8ns_V1 {\n    created?: IbGibAddr[];\n    final?: IbGibAddr[];\n}\n\n/**\n * IbGib that tracks/logs the entire syncing process.\n *\n * Since this is created with a tjp, it includes the tjp.gib in\n * each status frame ibgib.gib. This tjp.gib acts as the \"saga id\"\n * or \"status stream id\".\n *\n * ## stages\n *\n * ### starting - (code 102)\n *\n * Gets the ball rolling with creating the first status ibgib.\n *\n * ###\n *\n */\nexport interface SyncStatusIbGib extends IbGib_V1<SyncStatusData, SyncStatusRel8ns> {\n    statusIbGibGraph: IbGib_V1[],\n    /**\n     * Ibgibs that were created as side effects from a merge.\n     *\n     * ## notes\n     *\n     * This happens when you apply one or more local transforms to\n     * a timeline in the store that has already been changed by some\n     * other space (other than local that is).\n     */\n    createdIbGibs?: IbGib_V1[];\n    /**\n     * Ibgibs that are only found in the store and not locally.\n     *\n     * ## notes\n     *\n     * This happens when ibgibs were created in some other space.\n     */\n    storeOnlyIbGibs?: IbGib_V1[];\n    /**\n     * This is a map of the local space \"oldAddr\" to the ultimately\n     * most recent ibgib address in the outer/sync space.\n     *\n     * ## notes\n     *\n     * You will need to also download the createdIbGibs and/or storeOnlyIbGibs\n     * which will contain the dependency graph between these two endpoints in\n     * each map entry here from old addr -> new addr.\n     *\n     * It is assumed that the local address already has all of the rest of the\n     * dependencies for `oldAddr`.\n     */\n    ibGibsMergeMap?: { [oldAddr: string]: IbGib_V1 };\n}\n\n/**\n * A saga atow refers only to the saga across a single space.\n */\nexport interface SagaInfo<\n    TIbGib extends IbGib_V1,\n    TSpaceOptionsData extends OuterSpaceOptionsData,\n    TSpaceOptionsRel8ns extends OuterSpaceOptionsRel8ns,\n    TSpaceOptionsIbGib extends OuterSpaceOptionsIbGib<TIbGib, TSpaceOptionsData, TSpaceOptionsRel8ns>,\n    TSpaceResultData extends OuterSpaceResultData,\n    TSpaceResultRel8ns extends OuterSpaceResultRel8ns,\n    TSpaceResultIbGib extends OuterSpaceResultIbGib<TIbGib, TSpaceResultData, TSpaceResultRel8ns>,\n    TStatusIbGib extends TIbGib,\n> {\n    /**\n     * UUID generated at the beginning of a multi-space operation that is common\n     * across all spaces.\n     *\n     * This is in contrast with a `sagaId`, which only pertains to a saga within\n     * a single space.\n     */\n    multiSpaceOpId: string;\n    /**\n     * UUID generated at the beginning of a sync saga for a single space.\n     *\n     * This is in contrast with the `syncId`, which pertains to a sync operation\n     * across all spaces.\n     */\n    sagaId: string;\n    /**\n     * Reference to the space with which we're communicating.\n     *\n     * Note that this is a witness not just an ibgib data shape. so you will be\n     * able to pass in args to witness to this space.\n     */\n    outerSpace: IbGibSpaceAny;\n    spaceId: string;\n    participants: ParticipantInfo[];\n\n    complete?: boolean;\n\n    /**\n     * Only publishes values after subscribed.\n     */\n    syncStatus$: SubjectWitness<TStatusIbGib>;\n    syncStatusSubscriptions: SubscriptionWitness[];\n\n    /**\n     * For each communication saga, there will be one or more calls to each\n     * space's `witness` function. This will produce arg & result ibgibs. This\n     * is the observable stream/subject of those witness calls.\n     */\n    witnessFnArgsAndResults$: SubjectWitness<TSpaceOptionsIbGib | TSpaceResultIbGib>;\n\n    syncIbGibs_All: IbGib_V1[];\n    syncAddrs_All: IbGibAddr[];\n    syncAddrs_All_AreTjps: IbGibAddr[];\n    syncAddrs_All_WithTjps: IbGibAddr[];\n    syncAddrs_All_WithoutTjps: IbGibAddr[];\n    syncAddrs_Skipped: IbGibAddr[];\n    syncAddrs_ToDo: IbGibAddr[];\n    syncAddrs_InProgress: IbGibAddr[];\n    syncAddrs_Failed: IbGibAddr[];\n}\n\n/**\n * Information about a sync operation over its entirety.\n *\n * ## notes\n *\n * This will be attached to each space arg/result ibgib, but this info object\n * WILL NOT be part of the internal `data` of either arg or result ibGib.\n */\nexport interface SyncSagaInfo\n    extends SagaInfo<\n        IbGib_V1,\n        SyncSpaceOptionsData,\n        SyncSpaceOptionsRel8ns,\n        SyncSpaceOptionsIbGib,\n        SyncSpaceResultData,\n        SyncSpaceResultRel8ns,\n        SyncSpaceResultIbGib,\n        SyncStatusIbGib> {\n}\n\n// export interface SyncCycleInfo {\n//     arg: SyncSpaceOptionsIbGib;\n//     result?: SyncSpaceResultIbGib;\n// }\n\n/**\n * AWS-specific outerspace type\n */\nexport type AWSRegion = 'us-east-1' | string;\n\nexport interface StatusIbInfo {\n    /**\n     * Code for the given status.\n     *\n     */\n    statusCode: StatusCode,\n    spaceType: SpaceType,\n    spaceSubtype: SpaceSubtype,\n    sagaId: string,\n    delimiter?: string,\n}\n", "import { HashAlgorithm } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { AlphabetIndexingMode, BlockModeOptions, SaltStrategy } from '@ibgib/encrypt-gib/dist/types.mjs';\nimport { IbGibData_V1, IbGibRel8ns_V1, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';\nimport { IbGibAddr, } from '@ibgib/ts-gib/dist/types.mjs';\n\nimport { ENCRYPTION_REL8N_NAME } from './encrypt-constants.mjs';\n\n\n\nexport type EncryptionMethod = 'encrypt-gib';\n/**\n * Discriminator for the algorithm used in encryption that specifies the\n * algorithm used in encryption.\n *\n * The value of this will decide which descending encryption interface is used\n * that specifies parameters specific to this method.\n */\nexport const EncryptionMethod = {\n    /**\n     * custom probably very weak algorithm that uses indexing into a recursive\n     * hash-based rounding function instead of keystream generation.\n     */\n    encrypt_gib: 'encrypt-gib' as EncryptionMethod,\n}\nexport const VALID_ENCRYPTION_METHODS = Object.values(EncryptionMethod);\n\n/**\n * Encryption-specific information that will form the {@link EncryptionData_V1}\n * shape. If you examine that interface, you'll see that it is this type\n */\nexport interface EncryptionInfo {\n    name: string;\n    description?: string;\n    /**\n     * @see {@link EncryptionMethod}\n     */\n    method: EncryptionMethod;\n}\n\n/**\n * Parameter information that is specific to the encrypt-gib algorithm.\n */\nexport interface EncryptionInfo_EncryptGib extends EncryptionInfo {\n    method: 'encrypt-gib'\n    /**\n     * This is the algorithm that encrypt-gib will use in its\n     * internal hashing round function to encrypt the data.\n     */\n    hashAlgorithm: HashAlgorithm;\n    /**\n     * This is an initial number of recursions to perform to \"get farther away\"\n     * from the password. It is a one-time cost at the beginning of the\n     * entire encryption process, so it does not cost more with more data.\n     */\n    initialRecursions: number;\n    /**\n     * This is the number of internal hashes per round function, which is per\n     * hex character of data. So the more recursions here, the longer it is\n     * going to take to encrypt/decrypt.\n     */\n    recursionsPerHash?: number;\n    /**\n     * Salt used throughout hashing in encryption/decryption. The longer and\n     * more random, the better for security. But there is also a resource cost.\n     */\n    salt: string;\n    /**\n     * Stronger are the perHash options.\n     *\n     *    'prependPerHash' | 'appendPerHash' | 'initialPrepend' | 'initialAppend';\n     */\n    saltStrategy?: SaltStrategy;\n    /**\n     * The encrypted data is a delimited list of indices.\n     *\n     * @default \",\" (comma-delimited)\n     */\n    encryptedDataDelimiter?: string;\n    /**\n     * indexOf vs. lastIndexOf when recording the plaintext char's index into the jit alphabet.\n     *\n     * @see {@link AlphabetIndexingMode}\n     */\n    indexingMode?: AlphabetIndexingMode;\n    /**\n     * boolean determines if the algorithm is run in block mode (relatively\n     * stronger but slower) or in stream mode (faster but weaker).\n     * @see {@link BlockModeOptions}\n     */\n    blockMode: boolean;\n    /**\n     * @see {@link BlockModeOptions}\n     */\n    blockModeOptions?: BlockModeOptions;\n}\n\n/**\n * @see {@link EncryptionIbGib_V1}\n */\nexport type EncryptionData_V1 = IbGibData_V1 & EncryptionInfo & (\n    EncryptionInfo_EncryptGib // extends this with logical OR of subtypes\n);\n\n/**\n * @see {@link EncryptionIbGib_V1}\n */\nexport interface EncryptionRel8ns_V1 extends IbGibRel8ns_V1 { }\n\n/**\n * IbGib that represents encryption settings.\n *\n * This determines the {@link EncryptionMethod}\n */\nexport interface EncryptionIbGib_V1 extends IbGib_V1<EncryptionData_V1, EncryptionRel8ns_V1> { }\n\n/**\n * Data for the actual encrypted ciphertext.\n */\nexport interface CiphertextData<TMetadata = any> extends IbGibData_V1 {\n    ciphertext?: string;\n    metadata?: TMetadata;\n}\n\n/**\n * Rel8ns for the actual encrypted ciphertext\n */\nexport interface CiphertextRel8ns extends IbGibRel8ns_V1 {\n    // [ENCRYPTION_REL8N_NAME]?: IbGibAddr[];\n}\n\n/**\n * Ibgib for the actual encrypted content, as opposed to the\n * encryption secret (password) or encryption method/algorithm.\n */\nexport interface CiphertextIbGib_V1<TMetadata = any>\n    extends IbGib_V1<CiphertextData<TMetadata>, CiphertextRel8ns> {\n}\n", "import { HELPER_LOG_A_LOT } from \"../constants.mjs\";\n\nconst logalot = HELPER_LOG_A_LOT || true;\n\nexport declare class SsmlTypes {\n    /**\n     * Describes how the text should be interpreted. This lets you\n     * provide additional context to the text and eliminate any\n     * ambiguity on how Alexa should render the text. Indicate how\n     * Alexa should interpret the text with the interpret-as attribute.\n     *\n     * Note that the Alexa service attempts to interpret the provided\n     * text correctly based on the text\u2019s formatting even without this\n     * tag. For example, if your output speech includes \u201C202-555-1212\u201D,\n     * Alexa speaks each individual digit, with a brief pause for each\n     * dash. You don\u2019t need to use <say-as interpret-as=\"telephone\"> in\n     * this case. However, if you provided the text \u201C2025551212\u201D, but\n     * you wanted Alexa to speak it as a phone number, you would need\n     * to use <say-as interpret-as=\"telephone\">.\n     *\n     * @example\n     * <speak>\n     *     Here is a number spoken as a cardinal number:\n     *     <say-as interpret-as=\"cardinal\">12345</say-as>.\n     *     Here is the same number with each digit spoken separately:\n     *     <say-as interpret-as=\"digits\">12345</say-as>.\n     *     Here is a word spelled out: <say-as interpret-as=\"spell-out\">hello</say-as>\n     * </speak>\n     *\n     * @see\n     * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#say-as\n     */\n    static sayAs({ text, interpret, format }: {\n        /**\n         * Text to specify interpretation.\n         */\n        text: string;\n        /**\n         * Value that indicates how text should be interpreted.\n         *\n         * @see {InterpretAs}\n         */\n        interpret: InterpretAs;\n        /**\n         * Only used when interpret-as is set to date. Set to one of\n         * the following to indicate format of the date:\n         *\n         *     mdy\n         *     dmy\n         *     ymd\n         *     md\n         *     dm\n         *     ym\n         *     my\n         *     d\n         *     m\n         *     y\n         *\n         * Alternatively, if you provide the date in YYYYMMDD format,\n         * the format attribute is ignored. You can include question\n         * marks (?) for portions of the date to leave out. For\n         * instance, Alexa would speak <say-as interpret-as=\"date\">????\n         * 0922</say-as> as \u201CSeptember 22nd\u201D.\n         */\n        format?: SayAsDate;\n    }): string;\n}\n\nexport type InterpretAs = \"characters\" | \"spell-out\" | \"cardinal\" | \"number\" | \"ordinal\" | \"digits\" | \"fraction\" | \"unit\" | \"date\" | \"time\" | \"telephone\" | \"address\" | \"interjection\" | \"expletive\";\n/**\n * Values that indicate how Alexa should speak text.\n * To be used with Ssml.sayAs({text, interpret: As.characters})\n */\nexport const As = {\n    /**\n     * Spell out each letter.\n     */\n    characters: \"characters\",\n    /**\n     * Spell out each letter.\n     */\n    spell_out: \"spell-out\" as InterpretAs,\n    /**\n     * Interpret the value as a cardinal number.\n     *\n     * @example \"12\" is pronounced as \"twelve\" and not \"1-2\".\n     */\n    cardinal: \"cardinal\" as InterpretAs,\n    /**\n     * Interpret the value as a cardinal number.\n     *\n     * @example \"12\" is pronounced as \"twelve\" and not \"1-2\".\n     */\n    number: \"number\" as InterpretAs,\n    /**\n     * Interpret the value as an ordinal number.\n     *\n     * @example \"12\" is pronounced as \"twelfth\"\n     */\n    ordinal: \"ordinal\" as InterpretAs,\n    /**\n     * Spell each digit separately.\n     */\n    digits: \"digits\" as InterpretAs,\n    /**\n     * Interpret the value as a fraction. This works for both common\n     * fractions (such as 3/20) and mixed fractions (such as 1+1/2).\n     */\n    fraction: \"fraction\" as InterpretAs,\n    /**\n     * Interpret a value as a measurement. The value should be either a\n     * number or fraction followed by a unit (with no space in between)\n     * or just a unit.\n     */\n    unit: \"unit\" as InterpretAs,\n    /**\n     * Interpret the value as a date. Specify the format with the\n     * format attribute.\n     */\n    date: \"date\" as InterpretAs,\n    /**\n     * Interpret a value such as 1'21\" as duration in minutes and\n     * seconds.\n     */\n    time: \"time\" as InterpretAs,\n    /**\n     * Interpret a value as a 7-digit or 10-digit telephone number.\n     * This can also handle extensions (for example, 2025551212x345).\n     */\n    telephone: \"telephone\" as InterpretAs,\n    /**\n     * Interpret a value as part of street address.\n     */\n    address: \"address\" as InterpretAs,\n    /**\n     * askGib NOTE: SpeechCons are already implemented directly: e.g. `Ssml.speech(Con.abracadabra)`\n     *\n     * Interpret the value as an interjection. Alexa speaks the text in\n     * a more expressive voice. For optimal results, only use the\n     * supported interjections and surround each one with a pause. For\n     *\n     * @example\n     * <say-as interpret-as=\"interjection\">Wow.</say-as>.\n     *\n     * Speechcons are supported for English (US), English (UK), and\n     * German.\n     */\n    interjection: \"interjection\" as InterpretAs,\n    /**\n     * \u201CBleep\u201D out the content inside the tag.\n     */\n    expletive: \"expletive\" as InterpretAs,\n};\nexport type SayAsDate = \"mdy\" | \"dmy\" | \"ymd\" | \"md\" | \"dm\" | \"ym\" | \"my\" | \"d\" | \"m\" | \"y\";\n/**\n * Date formats, used with @see {sayAs} function when\n * @see {InterpretAs} is \"date\".\n *\n * Alternatively, if you provide the date in YYYYMMDD format, the\n * format attribute is ignored. You can include question marks (?) for\n * portions of the date to leave out. For instance, Alexa would speak\n * <say-as interpret-as=\"date\">????0922</say-as> as \u201CSeptember 22nd\u201D.\n */\nexport const SayAsDate = {\n    mdy: \"mdy\" as SayAsDate,\n    dmy: \"dmy\" as SayAsDate,\n    ymd: \"ymd\" as SayAsDate,\n    md: \"md\" as SayAsDate,\n    dm: \"dm\" as SayAsDate,\n    ym: \"ym\" as SayAsDate,\n    my: \"my\" as SayAsDate,\n    d: \"d\" as SayAsDate,\n    m: \"m\" as SayAsDate,\n    y: \"y\" as SayAsDate,\n};\nexport type ProsodyRateType = \"x-slow\" | \"slow\" | \"medium\" | \"fast\" | \"x-fast\" | number;\nexport type ProsodyPitchType = \"x-low\" | \"low\" | \"medium\" | \"high\" | \"x-high\" | number;\nexport type ProsodyVolumeType = \"silent\" | \"x-soft\" | \"soft\" | \"medium\" | \"loud\" | \"x-loud\" | number;\nexport type SpeechCon =\n    \"abracadabra\" | \"achoo\" | \"aha\" | \"ahem\" | \"ahoy\" | \"all righty\" | \"aloha\" | \"aooga\" | \"argh\" | \"arrivederci\" | \"as you wish\" | \"attagirl\" | \"au revoir\" | \"avast ye\" | \"aw man\" | \"baa\" | \"bada bing bada boom\" | \"bah humbug\" | \"bam\" | \"bang\" | \"batter up\" | \"bazinga\" | \"beep beep\" | \"bingo\" | \"blah\" | \"blarg\" | \"blast\" | \"boing\" | \"bon appetit\" | \"bonjour\" | \"bon voyage\" | \"boo\" | \"boo hoo\" | \"boom\" | \"booya\" | \"bravo\" | \"bummer\" | \"caw\" | \"cha ching\" | \"checkmate\" | \"cheerio\" | \"cheers\" | \"cheer up\" | \"chirp\" | \"choo choo\" | \"clank\" | \"click clack\" | \"cock a doodle doo\" | \"coo\" | \"cowabunga\" | \"darn\" | \"ding dong\" | \"ditto\" | \"d\u2019oh\" | \"dot dot dot\" | \"duh\" | \"dum\" | \"dun dun dun\" | \"dynomite\" | \"eek\" | \"eep\" | \"encore\" | \"en gard\" | \"eureka\" | \"fancy that\" | \"geronimo\" | \"giddy up\" | \"good grief\" | \"good luck\" | \"good riddance\" | \"gotcha\" | \"great scott\" | \"heads up\" | \"hear hear\" | \"hip hip hooray\" | \"hiss\" | \"honk\" | \"howdy\" | \"hurrah\" | \"hurray\" | \"huzzah\" | \"jeepers creepers\" | \"jiminy cricket\" | \"jinx\" | \"just kidding\" | \"kaboom\" | \"kablam\" | \"kaching\" | \"kapow\" | \"katchow\" | \"kazaam\" | \"kerbam\" | \"kerboom\" | \"kerching\" | \"kerchoo\" | \"kerflop\" | \"kerplop\" | \"kerplunk\" | \"kerpow\" | \"kersplat\" | \"kerthump\" | \"knock knock\" | \"le sigh\" | \"look out\" | \"mamma mia\" | \"man overboard\" | \"mazel tov\" | \"meow\" | \"merci\" | \"moo\" | \"nanu nanu\" | \"neener neener\" | \"no way\" | \"now now\" | \"oh boy\" | \"oh brother\" | \"oh dear\" | \"oh my\" | \"oh snap\" | \"oink\" | \"okey dokey\" | \"oof\" | \"ooh la la\" | \"open sesame\" | \"ouch\" | \"oy\" | \"phew\" | \"phooey\" | \"ping\" | \"plop\" | \"poof\" | \"pop\" | \"pow\" | \"quack\" | \"read \u2018em and weep\" | \"ribbit\" | \"righto\" | \"roger\" | \"ruh roh\" | \"shucks\" | \"splash\" | \"spoiler alert\" | \"squee\" | \"swish\" | \"swoosh\" | \"ta da\" | \"ta ta\" | \"tee hee\" | \"there there\" | \"thump\" | \"tick tick tick\" | \"tick-tock\" | \"touche\" | \"tsk tsk\" | \"tweet\" | \"uh huh\" | \"uh oh\" | \"um\" | \"voila\" | \"vroom\" | \"wahoo\" | \"wah wah\" | \"watch out\" | \"way to go\" | \"well done\" | \"well well\" | \"wham\" | \"whammo\" | \"whee\" | \"whew\" | \"woof\" | \"whoops a daisy\" | \"whoosh\" | \"woo hoo\" | \"wow\" | \"wowza\" | \"wowzer\" | \"yadda yadda yadda\" | \"yay\" | \"yikes\" | \"yippee\" | \"yoink\" | \"yoo hoo\" | \"you bet\" | \"yowza\" | \"yowzer\" | \"yuck\" | \"yum\" | \"zap\" | \"zing\" | \"zoinks\";\n/**\n * Special interjections that Alexa can say.\n * I have this called only \"Con\" for readability of calling code.\n *\n * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speechcon-reference\n *\n * All spaces in keys are replaced with underscores.\n */\nexport const Con = {\n    abracadabra: \"abracadabra\" as SpeechCon,\n    achoo: \"achoo\" as SpeechCon,\n    aha: \"aha\" as SpeechCon,\n    ahem: \"ahem\" as SpeechCon,\n    ahoy: \"ahoy\" as SpeechCon,\n    all_righty: \"all righty\" as SpeechCon,\n    aloha: \"aloha\" as SpeechCon,\n    aooga: \"aooga\" as SpeechCon,\n    argh: \"argh\" as SpeechCon,\n    arrivederci: \"arrivederci\" as SpeechCon,\n    as_you_wish: \"as you wish\" as SpeechCon,\n    attagirl: \"attagirl\" as SpeechCon,\n    au_revoir: \"au revoir\" as SpeechCon,\n    avast_ye: \"avast ye\" as SpeechCon,\n    aw_man: \"aw man\" as SpeechCon,\n    baa: \"baa\" as SpeechCon,\n    bada_bing_bada_boom: \"bada bing bada boom\" as SpeechCon,\n    bah_humbug: \"bah humbug\" as SpeechCon,\n    bam: \"bam\" as SpeechCon,\n    bang: \"bang\" as SpeechCon,\n    batter_up: \"batter up\" as SpeechCon,\n    bazinga: \"bazinga\" as SpeechCon,\n    beep_beep: \"beep beep\" as SpeechCon,\n    bingo: \"bingo\" as SpeechCon,\n    blah: \"blah\" as SpeechCon,\n    blarg: \"blarg\" as SpeechCon,\n    blast: \"blast\" as SpeechCon,\n    boing: \"boing\" as SpeechCon,\n    bon_appetit: \"bon appetit\" as SpeechCon,\n    bonjour: \"bonjour\" as SpeechCon,\n    bon_voyage: \"bon voyage\" as SpeechCon,\n    boo: \"boo\" as SpeechCon,\n    boo_hoo: \"boo hoo\" as SpeechCon,\n    boom: \"boom\" as SpeechCon,\n    booya: \"booya\" as SpeechCon,\n    bravo: \"bravo\" as SpeechCon,\n    bummer: \"bummer\" as SpeechCon,\n    caw: \"caw\" as SpeechCon,\n    cha_ching: \"cha ching\" as SpeechCon,\n    checkmate: \"checkmate\" as SpeechCon,\n    cheerio: \"cheerio\" as SpeechCon,\n    cheers: \"cheers\" as SpeechCon,\n    cheer_up: \"cheer up\" as SpeechCon,\n    chirp: \"chirp\" as SpeechCon,\n    choo_choo: \"choo choo\" as SpeechCon,\n    clank: \"clank\" as SpeechCon,\n    click_clack: \"click clack\" as SpeechCon,\n    cock_a_doodle_doo: \"cock a doodle doo\" as SpeechCon,\n    coo: \"coo\" as SpeechCon,\n    cowabunga: \"cowabunga\" as SpeechCon,\n    darn: \"darn\" as SpeechCon,\n    ding_dong: \"ding dong\" as SpeechCon,\n    ditto: \"ditto\" as SpeechCon,\n    doh: \"doh\" as SpeechCon,\n    dot_dot_dot: \"dot dot dot\" as SpeechCon,\n    duh: \"duh\" as SpeechCon,\n    dum: \"dum\" as SpeechCon,\n    dun_dun_dun: \"dun dun dun\" as SpeechCon,\n    dynomite: \"dynomite\" as SpeechCon,\n    eek: \"eek\" as SpeechCon,\n    eep: \"eep\" as SpeechCon,\n    encore: \"encore\" as SpeechCon,\n    en_gard: \"en gard\" as SpeechCon,\n    eureka: \"eureka\" as SpeechCon,\n    fancy_that: \"fancy that\" as SpeechCon,\n    geronimo: \"geronimo\" as SpeechCon,\n    giddy_up: \"giddy up\" as SpeechCon,\n    good_grief: \"good grief\" as SpeechCon,\n    good_luck: \"good luck\" as SpeechCon,\n    good_riddance: \"good riddance\" as SpeechCon,\n    gotcha: \"gotcha\" as SpeechCon,\n    great_scott: \"great scott\" as SpeechCon,\n    heads_up: \"heads up\" as SpeechCon,\n    hear_hear: \"hear hear\" as SpeechCon,\n    hip_hip_hooray: \"hip hip hooray\" as SpeechCon,\n    hiss: \"hiss\" as SpeechCon,\n    honk: \"honk\" as SpeechCon,\n    howdy: \"howdy\" as SpeechCon,\n    hurrah: \"hurrah\" as SpeechCon,\n    hurray: \"hurray\" as SpeechCon,\n    huzzah: \"huzzah\" as SpeechCon,\n    jeepers_creepers: \"jeepers creepers\" as SpeechCon,\n    jiminy_cricket: \"jiminy cricket\" as SpeechCon,\n    jinx: \"jinx\" as SpeechCon,\n    just_kidding: \"just kidding\" as SpeechCon,\n    kaboom: \"kaboom\" as SpeechCon,\n    kablam: \"kablam\" as SpeechCon,\n    kaching: \"kaching\" as SpeechCon,\n    kapow: \"kapow\" as SpeechCon,\n    katchow: \"katchow\" as SpeechCon,\n    kazaam: \"kazaam\" as SpeechCon,\n    kerbam: \"kerbam\" as SpeechCon,\n    kerboom: \"kerboom\" as SpeechCon,\n    kerching: \"kerching\" as SpeechCon,\n    kerchoo: \"kerchoo\" as SpeechCon,\n    kerflop: \"kerflop\" as SpeechCon,\n    kerplop: \"kerplop\" as SpeechCon,\n    kerplunk: \"kerplunk\" as SpeechCon,\n    kerpow: \"kerpow\" as SpeechCon,\n    kersplat: \"kersplat\" as SpeechCon,\n    kerthump: \"kerthump\" as SpeechCon,\n    knock_knock: \"knock knock\" as SpeechCon,\n    le_sigh: \"le sigh\" as SpeechCon,\n    look_out: \"look out\" as SpeechCon,\n    mamma_mia: \"mamma mia\" as SpeechCon,\n    man_overboard: \"man overboard\" as SpeechCon,\n    mazel_tov: \"mazel tov\" as SpeechCon,\n    meow: \"meow\" as SpeechCon,\n    merci: \"merci\" as SpeechCon,\n    moo: \"moo\" as SpeechCon,\n    nanu_nanu: \"nanu nanu\" as SpeechCon,\n    neener_neener: \"neener neener\" as SpeechCon,\n    no_way: \"no way\" as SpeechCon,\n    now_now: \"now now\" as SpeechCon,\n    oh_boy: \"oh boy\" as SpeechCon,\n    oh_brother: \"oh brother\" as SpeechCon,\n    oh_dear: \"oh dear\" as SpeechCon,\n    oh_my: \"oh my\" as SpeechCon,\n    oh_snap: \"oh snap\" as SpeechCon,\n    oink: \"oink\" as SpeechCon,\n    okey_dokey: \"okey dokey\" as SpeechCon,\n    oof: \"oof\" as SpeechCon,\n    ooh_la_la: \"ooh la la\" as SpeechCon,\n    open_sesame: \"open sesame\" as SpeechCon,\n    ouch: \"ouch\" as SpeechCon,\n    oy: \"oy\" as SpeechCon,\n    phew: \"phew\" as SpeechCon,\n    phooey: \"phooey\" as SpeechCon,\n    ping: \"ping\" as SpeechCon,\n    plop: \"plop\" as SpeechCon,\n    poof: \"poof\" as SpeechCon,\n    pop: \"pop\" as SpeechCon,\n    pow: \"pow\" as SpeechCon,\n    quack: \"quack\" as SpeechCon,\n    read_em_and_weep: \"read em and weep\" as SpeechCon,\n    ribbit: \"ribbit\" as SpeechCon,\n    righto: \"righto\" as SpeechCon,\n    roger: \"roger\" as SpeechCon,\n    ruh_roh: \"ruh roh\" as SpeechCon,\n    shucks: \"shucks\" as SpeechCon,\n    splash: \"splash\" as SpeechCon,\n    spoiler_alert: \"spoiler alert\" as SpeechCon,\n    squee: \"squee\" as SpeechCon,\n    swish: \"swish\" as SpeechCon,\n    swoosh: \"swoosh\" as SpeechCon,\n    ta_da: \"ta da\" as SpeechCon,\n    ta_ta: \"ta ta\" as SpeechCon,\n    tee_hee: \"tee hee\" as SpeechCon,\n    there_there: \"there there\" as SpeechCon,\n    thump: \"thump\" as SpeechCon,\n    tick_tick_tick: \"tick tick tick\" as SpeechCon,\n    tick_tock: \"tick tock\" as SpeechCon,\n    touche: \"touche\" as SpeechCon,\n    tsk_tsk: \"tsk tsk\" as SpeechCon,\n    tweet: \"tweet\" as SpeechCon,\n    uh_huh: \"uh huh\" as SpeechCon,\n    uh_oh: \"uh oh\" as SpeechCon,\n    um: \"um\" as SpeechCon,\n    voila: \"voila\" as SpeechCon,\n    vroom: \"vroom\" as SpeechCon,\n    wahoo: \"wahoo\" as SpeechCon,\n    wah_wah: \"wah wah\" as SpeechCon,\n    watch_out: \"watch out\" as SpeechCon,\n    way_to_go: \"way to go\" as SpeechCon,\n    well_done: \"well done\" as SpeechCon,\n    well_well: \"well well\" as SpeechCon,\n    wham: \"wham\" as SpeechCon,\n    whammo: \"whammo\" as SpeechCon,\n    whee: \"whee\" as SpeechCon,\n    whew: \"whew\" as SpeechCon,\n    woof: \"woof\" as SpeechCon,\n    whoops_a_daisy: \"whoops a daisy\" as SpeechCon,\n    whoosh: \"whoosh\" as SpeechCon,\n    woo_hoo: \"woo hoo\" as SpeechCon,\n    wow: \"wow\" as SpeechCon,\n    wowza: \"wowza\" as SpeechCon,\n    wowzer: \"wowzer\" as SpeechCon,\n    yadda_yadda_yadda: \"yadda yadda yadda\" as SpeechCon,\n    yay: \"yay\" as SpeechCon,\n    yikes: \"yikes\" as SpeechCon,\n    yippee: \"yippee\" as SpeechCon,\n    yoink: \"yoink\" as SpeechCon,\n    yoo_hoo: \"yoo hoo\" as SpeechCon,\n    you_bet: \"you bet\" as SpeechCon,\n    yowza: \"yowza\" as SpeechCon,\n    yowzer: \"yowzer\" as SpeechCon,\n    yuck: \"yuck\" as SpeechCon,\n    yum: \"yum\" as SpeechCon,\n    zap: \"zap\" as SpeechCon,\n    zing: \"zing\" as SpeechCon,\n    zoinks: \"zoinks\" as SpeechCon,\n};\nexport type SpeechConUK = \"abracadabra\" | \"ace\" | \"achoo\" | \"ahoy\" | \"all\" | \"aloha\" | \"aooga\" | \"arrivederci\" | \"as if\" | \"as you wish\" | \"au revoir\" | \"aw\" | \"aw man\" | \"awesome\" | \"baa\" | \"bah humbug\" | \"bam\" | \"bang\" | \"bazinga\" | \"beep beep\" | \"bingo\" | \"blah\" | \"blarg\" | \"blast\" | \"blimey\" | \"bob's your uncle\" | \"boing\" | \"bon appetit\" | \"bon voyage\" | \"bonjour\" | \"boo\" | \"boo hoo\" | \"booya\" | \"bother\" | \"bravo\" | \"caw\" | \"cha ching\" | \"checkmate\" | \"cheer up\" | \"cheerio\" | \"cheers\" | \"chirp\" | \"choo choo\" | \"clank\" | \"clickety clack\" | \"cock a doodle doo\" | \"codswallop\" | \"coo\" | \"cowabunga\" | \"crikey\" | \"d'oh\" | \"darn\" | \"ditto\" | \"dot dot dot\" | \"duh\" | \"dun dun dun\" | \"eek\" | \"eep\" | \"en garde\" | \"encore\" | \"eureka\" | \"ew\" | \"fancy that\" | \"geronimo\" | \"giddy up\" | \"good golly\" | \"good grief\" | \"good luck\" | \"good riddance\" | \"gosh\" | \"gotcha\" | \"great scott\" | \"ha\" | \"ha ha\" | \"heads up\" | \"hear hear\" | \"hip hip hooray\" | \"hiss\" | \"honk\" | \"howdy\" | \"howzat\" | \"hurrah\" | \"hurray\" | \"huzzah\" | \"jeepers creepers\" | \"jiminy cricket\" | \"jinx\" | \"just kidding\" | \"kablam\" | \"kaboom\" | \"kaching\" | \"kapow\" | \"knock knock\" | \"le sigh\" | \"look out\" | \"mamma mia\" | \"man overboard\" | \"mazel tov\" | \"meow\" | \"merci\" | \"moo\" | \"no way\" | \"nom nom\" | \"now now\" | \"oh boy\" | \"oh dear\" | \"oh my\" | \"oh my giddy aunt\" | \"oh snap\" | \"okey dokey\" | \"oof\" | \"ooh la la\" | \"open sesame\" | \"ouch\" | \"ow\" | \"oy\" | \"pardon\" | \"phew\" | \"phooey\" | \"ping\" | \"plop\" | \"pop\" | \"pow\" | \"quack\" | \"read 'em and weep\" | \"ribbit\" | \"righto\" | \"roger\" | \"sigh\" | \"simples\" | \"splash\" | \"spoiler alert\" | \"squee\" | \"swish\" | \"swoosh\" | \"ta da\" | \"tallyho\" | \"tee hee\" | \"there there\" | \"thump\" | \"tick tick tick\" | \"tick tock\" | \"tosh\" | \"touche\" | \"tsk tsk\" | \"tut tut\" | \"tweet\" | \"uh huh\" | \"uh oh\" | \"voila\" | \"vroom\" | \"wahoo\" | \"watch out\" | \"way to go\" | \"well done\" | \"well well\" | \"wham\" | \"whammo\" | \"whee\" | \"whoop\" | \"whoops\" | \"whoops a daisy\" | \"whoosh\" | \"woo hoo\" | \"wow\" | \"wowza\" | \"yadda yadda yadda\" | \"yippee\" | \"yoink\" | \"you bet\" | \"yowza\" | \"yum\" | \"zap\" | \"zing\" | \"zoinks\";\nexport const ConUK = {\n    abracadabra: \"abracadabra\" as SpeechConUK,\n    ace: \"ace\" as SpeechConUK,\n    achoo: \"achoo\" as SpeechConUK,\n    ahoy: \"ahoy\" as SpeechConUK,\n    all: \"all\" as SpeechConUK,\n    aloha: \"aloha\" as SpeechConUK,\n    aooga: \"aooga\" as SpeechConUK,\n    arrivederci: \"arrivederci\" as SpeechConUK,\n    as_if: \"as if\" as SpeechConUK,\n    as_you_wish: \"as you wish\" as SpeechConUK,\n    au_revoir: \"au revoir\" as SpeechConUK,\n    aw: \"aw\" as SpeechConUK,\n    aw_man: \"aw man\" as SpeechConUK,\n    awesome: \"awesome\" as SpeechConUK,\n    baa: \"baa\" as SpeechConUK,\n    bah_humbug: \"bah humbug\" as SpeechConUK,\n    bam: \"bam\" as SpeechConUK,\n    bang: \"bang\" as SpeechConUK,\n    bazinga: \"bazinga\" as SpeechConUK,\n    beep_beep: \"beep beep\" as SpeechConUK,\n    bingo: \"bingo\" as SpeechConUK,\n    blah: \"blah\" as SpeechConUK,\n    blarg: \"blarg\" as SpeechConUK,\n    blast: \"blast\" as SpeechConUK,\n    blimey: \"blimey\" as SpeechConUK,\n    bobs_your_uncle: \"bobs your uncle\" as SpeechConUK,\n    boing: \"boing\" as SpeechConUK,\n    bon_appetit: \"bon appetit\" as SpeechConUK,\n    bon_voyage: \"bon voyage\" as SpeechConUK,\n    bonjour: \"bonjour\" as SpeechConUK,\n    boo: \"boo\" as SpeechConUK,\n    boo_hoo: \"boo hoo\" as SpeechConUK,\n    booya: \"booya\" as SpeechConUK,\n    bother: \"bother\" as SpeechConUK,\n    bravo: \"bravo\" as SpeechConUK,\n    caw: \"caw\" as SpeechConUK,\n    cha_ching: \"cha ching\" as SpeechConUK,\n    checkmate: \"checkmate\" as SpeechConUK,\n    cheer_up: \"cheer up\" as SpeechConUK,\n    cheerio: \"cheerio\" as SpeechConUK,\n    cheers: \"cheers\" as SpeechConUK,\n    chirp: \"chirp\" as SpeechConUK,\n    choo_choo: \"choo choo\" as SpeechConUK,\n    clank: \"clank\" as SpeechConUK,\n    clickety_clack: \"clickety clack\" as SpeechConUK,\n    cock_a_doodle_doo: \"cock a doodle doo\" as SpeechConUK,\n    codswallop: \"codswallop\" as SpeechConUK,\n    coo: \"coo\" as SpeechConUK,\n    cowabunga: \"cowabunga\" as SpeechConUK,\n    crikey: \"crikey\" as SpeechConUK,\n    doh: \"doh\" as SpeechConUK,\n    darn: \"darn\" as SpeechConUK,\n    ditto: \"ditto\" as SpeechConUK,\n    dot_dot_dot: \"dot dot dot\" as SpeechConUK,\n    duh: \"duh\" as SpeechConUK,\n    dun_dun_dun: \"dun dun dun\" as SpeechConUK,\n    eek: \"eek\" as SpeechConUK,\n    eep: \"eep\" as SpeechConUK,\n    en_garde: \"en garde\" as SpeechConUK,\n    encore: \"encore\" as SpeechConUK,\n    eureka: \"eureka\" as SpeechConUK,\n    ew: \"ew\" as SpeechConUK,\n    fancy_that: \"fancy that\" as SpeechConUK,\n    geronimo: \"geronimo\" as SpeechConUK,\n    giddy_up: \"giddy up\" as SpeechConUK,\n    good_golly: \"good golly\" as SpeechConUK,\n    good_grief: \"good grief\" as SpeechConUK,\n    good_luck: \"good luck\" as SpeechConUK,\n    good_riddance: \"good riddance\" as SpeechConUK,\n    gosh: \"gosh\" as SpeechConUK,\n    gotcha: \"gotcha\" as SpeechConUK,\n    great_scott: \"great scott\" as SpeechConUK,\n    ha: \"ha\" as SpeechConUK,\n    ha_ha: \"ha ha\" as SpeechConUK,\n    heads_up: \"heads up\" as SpeechConUK,\n    hear_hear: \"hear hear\" as SpeechConUK,\n    hip_hip_hooray: \"hip hip hooray\" as SpeechConUK,\n    hiss: \"hiss\" as SpeechConUK,\n    honk: \"honk\" as SpeechConUK,\n    howdy: \"howdy\" as SpeechConUK,\n    howzat: \"howzat\" as SpeechConUK,\n    hurrah: \"hurrah\" as SpeechConUK,\n    hurray: \"hurray\" as SpeechConUK,\n    huzzah: \"huzzah\" as SpeechConUK,\n    jeepers_creepers: \"jeepers creepers\" as SpeechConUK,\n    jiminy_cricket: \"jiminy cricket\" as SpeechConUK,\n    jinx: \"jinx\" as SpeechConUK,\n    just_kidding: \"just kidding\" as SpeechConUK,\n    kablam: \"kablam\" as SpeechConUK,\n    kaboom: \"kaboom\" as SpeechConUK,\n    kaching: \"kaching\" as SpeechConUK,\n    kapow: \"kapow\" as SpeechConUK,\n    knock_knock: \"knock knock\" as SpeechConUK,\n    le_sigh: \"le sigh\" as SpeechConUK,\n    look_out: \"look out\" as SpeechConUK,\n    mamma_mia: \"mamma mia\" as SpeechConUK,\n    man_overboard: \"man overboard\" as SpeechConUK,\n    mazel_tov: \"mazel tov\" as SpeechConUK,\n    meow: \"meow\" as SpeechConUK,\n    merci: \"merci\" as SpeechConUK,\n    moo: \"moo\" as SpeechConUK,\n    no_way: \"no way\" as SpeechConUK,\n    nom_nom: \"nom nom\" as SpeechConUK,\n    now_now: \"now now\" as SpeechConUK,\n    oh_boy: \"oh boy\" as SpeechConUK,\n    oh_dear: \"oh dear\" as SpeechConUK,\n    oh_my: \"oh my\" as SpeechConUK,\n    oh_my_giddy_aunt: \"oh my giddy aunt\" as SpeechConUK,\n    oh_snap: \"oh snap\" as SpeechConUK,\n    okey_dokey: \"okey dokey\" as SpeechConUK,\n    oof: \"oof\" as SpeechConUK,\n    ooh_la_la: \"ooh la la\" as SpeechConUK,\n    open_sesame: \"open sesame\" as SpeechConUK,\n    ouch: \"ouch\" as SpeechConUK,\n    ow: \"ow\" as SpeechConUK,\n    oy: \"oy\" as SpeechConUK,\n    pardon: \"pardon\" as SpeechConUK,\n    phew: \"phew\" as SpeechConUK,\n    phooey: \"phooey\" as SpeechConUK,\n    ping: \"ping\" as SpeechConUK,\n    plop: \"plop\" as SpeechConUK,\n    pop: \"pop\" as SpeechConUK,\n    pow: \"pow\" as SpeechConUK,\n    quack: \"quack\" as SpeechConUK,\n    read_em_and_weep: \"read em and weep\" as SpeechConUK,\n    ribbit: \"ribbit\" as SpeechConUK,\n    righto: \"righto\" as SpeechConUK,\n    roger: \"roger\" as SpeechConUK,\n    sigh: \"sigh\" as SpeechConUK,\n    simples: \"simples\" as SpeechConUK,\n    splash: \"splash\" as SpeechConUK,\n    spoiler_alert: \"spoiler alert\" as SpeechConUK,\n    squee: \"squee\" as SpeechConUK,\n    swish: \"swish\" as SpeechConUK,\n    swoosh: \"swoosh\" as SpeechConUK,\n    ta_da: \"ta da\" as SpeechConUK,\n    tallyho: \"tallyho\" as SpeechConUK,\n    tee_hee: \"tee hee\" as SpeechConUK,\n    there_there: \"there there\" as SpeechConUK,\n    thump: \"thump\" as SpeechConUK,\n    tick_tick_tick: \"tick tick tick\" as SpeechConUK,\n    tick_tock: \"tick tock\" as SpeechConUK,\n    tosh: \"tosh\" as SpeechConUK,\n    touche: \"touche\" as SpeechConUK,\n    tsk_tsk: \"tsk tsk\" as SpeechConUK,\n    tut_tut: \"tut tut\" as SpeechConUK,\n    tweet: \"tweet\" as SpeechConUK,\n    uh_huh: \"uh huh\" as SpeechConUK,\n    uh_oh: \"uh oh\" as SpeechConUK,\n    voila: \"voila\" as SpeechConUK,\n    vroom: \"vroom\" as SpeechConUK,\n    wahoo: \"wahoo\" as SpeechConUK,\n    watch_out: \"watch out\" as SpeechConUK,\n    way_to_go: \"way to go\" as SpeechConUK,\n    well_done: \"well done\" as SpeechConUK,\n    well_well: \"well well\" as SpeechConUK,\n    wham: \"wham\" as SpeechConUK,\n    whammo: \"whammo\" as SpeechConUK,\n    whee: \"whee\" as SpeechConUK,\n    whoop: \"whoop\" as SpeechConUK,\n    whoops: \"whoops\" as SpeechConUK,\n    whoops_a_daisy: \"whoops a daisy\" as SpeechConUK,\n    whoosh: \"whoosh\" as SpeechConUK,\n    woo_hoo: \"woo hoo\" as SpeechConUK,\n    wow: \"wow\" as SpeechConUK,\n    wowza: \"wowza\" as SpeechConUK,\n    yadda_yadda_yadda: \"yadda yadda yadda\" as SpeechConUK,\n    yippee: \"yippee\" as SpeechConUK,\n    yoink: \"yoink\" as SpeechConUK,\n    you_bet: \"you bet\" as SpeechConUK,\n    yowza: \"yowza\" as SpeechConUK,\n    yum: \"yum\" as SpeechConUK,\n    zap: \"zap\" as SpeechConUK,\n    zing: \"zing\" as SpeechConUK,\n    zoinks: \"zoinks\" as SpeechConUK,\n};\nexport type SpeechConDE = \"aber hallo\" | \"aber sicher\" | \"abrakadabra\" | \"ach\" | \"ach du gr\u00FCne neune\" | \"ach du liebe zeit\" | \"ach du meine g\u00FCte\" | \"ach ja\" | \"ach so\" | \"achje\" | \"achtung\" | \"ade\" | \"ah\" | \"aha\" | \"\u00E4hm\" | \"ahoi\" | \"alles klar\" | \"aloha\" | \"als ob\" | \"argh\" | \"arrivederci\" | \"aso\" | \"au\" | \"au weia\" | \"aua\" | \"autsch\" | \"bazinga\" | \"bingo\" | \"bis bald\" | \"bis dann\" | \"bla\" | \"boing\" | \"bon appetit\" | \"bon voyage\" | \"bonjour\" | \"bravo\" | \"brumm\" | \"buh\" | \"buhu\" | \"bumm\" | \"bzz\" | \"da lachen ja die h\u00FChner\" | \"ding dong\" | \"dito\" | \"donner und doria\" | \"donnerwetter\" | \"ebenso\" | \"en garde\" | \"ey\" | \"geh nur\" | \"gemach\" | \"genug\" | \"gesundheit\" | \"gott im himmel\" | \"gr\u00FC\u00DF gott\" | \"gute reise\" | \"guten appetit\" | \"hach ja\" | \"halleluja\" | \"hals und beinbruch\" | \"halt\" | \"h\u00E4nde hoch\" | \"heiliger strohsack\" | \"heisa\" | \"hey\" | \"hihi\" | \"hipp hipp hurra\" | \"h\u00F6rt h\u00F6rt\" | \"h\u00FC\" | \"h\u00FCa\" | \"huch\" | \"huhu\" | \"hui\" | \"hurra\" | \"ich glaub ich bin im kino\" | \"ich glaub mein schwein pfeift\" | \"ich glaub mich knutscht ein elch\" | \"ich glaub mich laust der affe\" | \"ich glaub mich tritt ein pferd\" | \"igitt\" | \"iiieh\" | \"ist nicht dein ernst\" | \"japp\" | \"jawohl\" | \"jo\" | \"juhu\" | \"kein kommentar\" | \"keine ursache\" | \"kikeriki\" | \"klar\" | \"klick klack\" | \"kopf hoch\" | \"kuckuck\" | \"lass es dir schmecken\" | \"lecker\" | \"los\" | \"mach's gut\" | \"mahlzeit\" | \"mamma mia\" | \"mann \u00FCber bord\" | \"manometer\" | \"mazel tov\" | \"mein gott\" | \"merci\" | \"miau\" | \"mist\" | \"moin\" | \"muh\" | \"na klar\" | \"na sieh mal einer an\" | \"na und?\" | \"na?\" | \"naja\" | \"nanu?\" | \"ne\" | \"nee\" | \"nichts da\" | \"nix da\" | \"n\u00F6\" | \"null problemo\" | \"obacht\" | \"och\" | \"oh mann\" | \"oh mein gott\" | \"oh my god\" | \"oh nein\" | \"oh oh\" | \"ohne schei\u00DF\" | \"oink\" | \"oje\" | \"okey dokey\" | \"ooh la la\" | \"pfui\" | \"piep\" | \"plop\" | \"plumps\" | \"prima\" | \"prosit\" | \"prost\" | \"puff\" | \"puh\" | \"pustekuchen\" | \"schachmatt\" | \"schade\" | \"schau an\" | \"sesam \u00F6ffne dich\" | \"seufz\" | \"sieh an\" | \"siehe da\" | \"siehste?\" | \"spoileralarm\" | \"stimmt\" | \"super\" | \"supi\" | \"s\u00FC\u00DFes oder saures\" | \"tada\" | \"tats\u00E4chlich\" | \"tick tack\" | \"tja\" | \"touche\" | \"tsch\u00F6\" | \"t\u00FCrlich\" | \"tut\" | \"uff\" | \"verdammt\" | \"verflixt\" | \"viel gl\u00FCck\" | \"voila\" | \"von wegen\" | \"vorsicht\" | \"war nur ein scherz\" | \"was zur h\u00F6lle\" | \"weh mir\" | \"wehe\" | \"wie du meinst\" | \"willkommen\" | \"wow\" | \"wuff\" | \"yay\" | \"zugabe\" | \"zum wohl\";\nexport const ConDE = {\n    aber_hallo: \"aber hallo\" as SpeechConDE,\n    aber_sicher: \"aber sicher\" as SpeechConDE,\n    abrakadabra: \"abrakadabra\" as SpeechConDE,\n    ach: \"ach\" as SpeechConDE,\n    ach_du_gr\u00FCne_neune: \"ach du gr\u00FCne neune\" as SpeechConDE,\n    ach_du_liebe_zeit: \"ach du liebe zeit\" as SpeechConDE,\n    ach_du_meine_g\u00FCte: \"ach du meine g\u00FCte\" as SpeechConDE,\n    ach_ja: \"ach ja\" as SpeechConDE,\n    ach_so: \"ach so\" as SpeechConDE,\n    achje: \"achje\" as SpeechConDE,\n    achtung: \"achtung\" as SpeechConDE,\n    ade: \"ade\" as SpeechConDE,\n    ah: \"ah\" as SpeechConDE,\n    aha: \"aha\" as SpeechConDE,\n    \u00E4hm: \"\u00E4hm\" as SpeechConDE,\n    ahoi: \"ahoi\" as SpeechConDE,\n    alles_klar: \"alles klar\" as SpeechConDE,\n    aloha: \"aloha\" as SpeechConDE,\n    als_ob: \"als ob\" as SpeechConDE,\n    argh: \"argh\" as SpeechConDE,\n    arrivederci: \"arrivederci\" as SpeechConDE,\n    aso: \"aso\" as SpeechConDE,\n    au: \"au\" as SpeechConDE,\n    au_weia: \"au weia\" as SpeechConDE,\n    aua: \"aua\" as SpeechConDE,\n    autsch: \"autsch\" as SpeechConDE,\n    bazinga: \"bazinga\" as SpeechConDE,\n    bingo: \"bingo\" as SpeechConDE,\n    bis_bald: \"bis bald\" as SpeechConDE,\n    bis_dann: \"bis dann\" as SpeechConDE,\n    bla: \"bla\" as SpeechConDE,\n    boing: \"boing\" as SpeechConDE,\n    bon_appetit: \"bon appetit\" as SpeechConDE,\n    bon_voyage: \"bon voyage\" as SpeechConDE,\n    bonjour: \"bonjour\" as SpeechConDE,\n    bravo: \"bravo\" as SpeechConDE,\n    brumm: \"brumm\" as SpeechConDE,\n    buh: \"buh\" as SpeechConDE,\n    buhu: \"buhu\" as SpeechConDE,\n    bumm: \"bumm\" as SpeechConDE,\n    bzz: \"bzz\" as SpeechConDE,\n    da_lachen_ja_die_h\u00FChner: \"da lachen ja die h\u00FChner\" as SpeechConDE,\n    ding_dong: \"ding dong\" as SpeechConDE,\n    dito: \"dito\" as SpeechConDE,\n    donner_und_doria: \"donner und doria\" as SpeechConDE,\n    donnerwetter: \"donnerwetter\" as SpeechConDE,\n    ebenso: \"ebenso\" as SpeechConDE,\n    en_garde: \"en garde\" as SpeechConDE,\n    ey: \"ey\" as SpeechConDE,\n    geh_nur: \"geh nur\" as SpeechConDE,\n    gemach: \"gemach\" as SpeechConDE,\n    genug: \"genug\" as SpeechConDE,\n    gesundheit: \"gesundheit\" as SpeechConDE,\n    gott_im_himmel: \"gott im himmel\" as SpeechConDE,\n    gr\u00FC\u00DF_gott: \"gr\u00FC\u00DF gott\" as SpeechConDE,\n    gute_reise: \"gute reise\" as SpeechConDE,\n    guten_appetit: \"guten appetit\" as SpeechConDE,\n    hach_ja: \"hach ja\" as SpeechConDE,\n    halleluja: \"halleluja\" as SpeechConDE,\n    hals_und_beinbruch: \"hals und beinbruch\" as SpeechConDE,\n    halt: \"halt\" as SpeechConDE,\n    h\u00E4nde_hoch: \"h\u00E4nde hoch\" as SpeechConDE,\n    heiliger_strohsack: \"heiliger strohsack\" as SpeechConDE,\n    heisa: \"heisa\" as SpeechConDE,\n    hey: \"hey\" as SpeechConDE,\n    hihi: \"hihi\" as SpeechConDE,\n    hipp_hipp_hurra: \"hipp hipp hurra\" as SpeechConDE,\n    h\u00F6rt_h\u00F6rt: \"h\u00F6rt h\u00F6rt\" as SpeechConDE,\n    h\u00FC: \"h\u00FC\" as SpeechConDE,\n    h\u00FCa: \"h\u00FCa\" as SpeechConDE,\n    huch: \"huch\" as SpeechConDE,\n    huhu: \"huhu\" as SpeechConDE,\n    hui: \"hui\" as SpeechConDE,\n    hurra: \"hurra\" as SpeechConDE,\n    ich_glaub_ich_bin_im_kino: \"ich glaub ich bin im kino\" as SpeechConDE,\n    ich_glaub_mein_schwein_pfeift: \"ich glaub mein schwein pfeift\" as SpeechConDE,\n    ich_glaub_mich_knutscht_ein_elch: \"ich glaub mich knutscht ein elch\" as SpeechConDE,\n    ich_glaub_mich_laust_der_affe: \"ich glaub mich laust der affe\" as SpeechConDE,\n    ich_glaub_mich_tritt_ein_pferd: \"ich glaub mich tritt ein pferd\" as SpeechConDE,\n    igitt: \"igitt\" as SpeechConDE,\n    iiieh: \"iiieh\" as SpeechConDE,\n    ist_nicht_dein_ernst: \"ist nicht dein ernst\" as SpeechConDE,\n    japp: \"japp\" as SpeechConDE,\n    jawohl: \"jawohl\" as SpeechConDE,\n    jo: \"jo\" as SpeechConDE,\n    juhu: \"juhu\" as SpeechConDE,\n    kein_kommentar: \"kein kommentar\" as SpeechConDE,\n    keine_ursache: \"keine ursache\" as SpeechConDE,\n    kikeriki: \"kikeriki\" as SpeechConDE,\n    klar: \"klar\" as SpeechConDE,\n    klick_klack: \"klick klack\" as SpeechConDE,\n    kopf_hoch: \"kopf hoch\" as SpeechConDE,\n    kuckuck: \"kuckuck\" as SpeechConDE,\n    lass_es_dir_schmecken: \"lass es dir schmecken\" as SpeechConDE,\n    lecker: \"lecker\" as SpeechConDE,\n    los: \"los\" as SpeechConDE,\n    mach: \"mach's gut\" as SpeechConDE,\n    mahlzeit: \"mahlzeit\" as SpeechConDE,\n    mamma_mia: \"mamma mia\" as SpeechConDE,\n    mann_\u00FCber_bord: \"mann \u00FCber bord\" as SpeechConDE,\n    manometer: \"manometer\" as SpeechConDE,\n    mazel_tov: \"mazel tov\" as SpeechConDE,\n    mein_gott: \"mein gott\" as SpeechConDE,\n    merci: \"merci\" as SpeechConDE,\n    miau: \"miau\" as SpeechConDE,\n    mist: \"mist\" as SpeechConDE,\n    moin: \"moin\" as SpeechConDE,\n    muh: \"muh\" as SpeechConDE,\n    na_klar: \"na klar\" as SpeechConDE,\n    na_sieh_mal_einer_an: \"na sieh mal einer an\" as SpeechConDE,\n    na_und_: \"na und?\" as SpeechConDE,\n    na_: \"na?\" as SpeechConDE,\n    naja: \"naja\" as SpeechConDE,\n    nanu: \"nanu\" as SpeechConDE,\n    ne: \"ne\" as SpeechConDE,\n    nee: \"nee\" as SpeechConDE,\n    nichts_da: \"nichts da\" as SpeechConDE,\n    nix_da: \"nix da\" as SpeechConDE,\n    n\u00F6: \"n\u00F6\" as SpeechConDE,\n    null_problemo: \"null problemo\" as SpeechConDE,\n    obacht: \"obacht\" as SpeechConDE,\n    och: \"och\" as SpeechConDE,\n    oh_mann: \"oh mann\" as SpeechConDE,\n    oh_mein_gott: \"oh mein gott\" as SpeechConDE,\n    oh_my_god: \"oh my god\" as SpeechConDE,\n    oh_nein: \"oh nein\" as SpeechConDE,\n    oh_oh: \"oh oh\" as SpeechConDE,\n    ohne_schei\u00DF: \"ohne schei\u00DF\" as SpeechConDE,\n    oink: \"oink\" as SpeechConDE,\n    oje: \"oje\" as SpeechConDE,\n    okey_dokey: \"okey dokey\" as SpeechConDE,\n    ooh_la_la: \"ooh la la\" as SpeechConDE,\n    pfui: \"pfui\" as SpeechConDE,\n    piep: \"piep\" as SpeechConDE,\n    plop: \"plop\" as SpeechConDE,\n    plumps: \"plumps\" as SpeechConDE,\n    prima: \"prima\" as SpeechConDE,\n    prosit: \"prosit\" as SpeechConDE,\n    prost: \"prost\" as SpeechConDE,\n    puff: \"puff\" as SpeechConDE,\n    puh: \"puh\" as SpeechConDE,\n    pustekuchen: \"pustekuchen\" as SpeechConDE,\n    schachmatt: \"schachmatt\" as SpeechConDE,\n    schade: \"schade\" as SpeechConDE,\n    schau_an: \"schau an\" as SpeechConDE,\n    sesam_\u00F6ffne_dich: \"sesam \u00F6ffne dich\" as SpeechConDE,\n    seufz: \"seufz\" as SpeechConDE,\n    sieh_an: \"sieh an\" as SpeechConDE,\n    siehe_da: \"siehe da\" as SpeechConDE,\n    siehste: \"siehste\" as SpeechConDE,\n    spoileralarm: \"spoileralarm\" as SpeechConDE,\n    stimmt: \"stimmt\" as SpeechConDE,\n    super: \"super\" as SpeechConDE,\n    supi: \"supi\" as SpeechConDE,\n    s\u00FC\u00DFes_oder_saures: \"s\u00FC\u00DFes oder saures\" as SpeechConDE,\n    tada: \"tada\" as SpeechConDE,\n    tats\u00E4chlich: \"tats\u00E4chlich\" as SpeechConDE,\n    tick_tack: \"tick tack\" as SpeechConDE,\n    tja: \"tja\" as SpeechConDE,\n    touche: \"touche\" as SpeechConDE,\n    tsch\u00F6: \"tsch\u00F6\" as SpeechConDE,\n    t\u00FCrlich: \"t\u00FCrlich\" as SpeechConDE,\n    tut: \"tut\" as SpeechConDE,\n    uff: \"uff\" as SpeechConDE,\n    verdammt: \"verdammt\" as SpeechConDE,\n    verflixt: \"verflixt\" as SpeechConDE,\n    viel_gl\u00FCck: \"viel gl\u00FCck\" as SpeechConDE,\n    voila: \"voila\" as SpeechConDE,\n    von_wegen: \"von wegen\" as SpeechConDE,\n    vorsicht: \"vorsicht\" as SpeechConDE,\n    war_nur_ein_scherz: \"war nur ein scherz\" as SpeechConDE,\n    was_zur_h\u00F6lle: \"was zur h\u00F6lle\" as SpeechConDE,\n    weh_mir: \"weh mir\" as SpeechConDE,\n    wehe: \"wehe\" as SpeechConDE,\n    wie_du_meinst: \"wie du meinst\" as SpeechConDE,\n    willkommen: \"willkommen\" as SpeechConDE,\n    wow: \"wow\" as SpeechConDE,\n    wuff: \"wuff\" as SpeechConDE,\n    yay: \"yay\" as SpeechConDE,\n    zugabe: \"zugabe\" as SpeechConDE,\n    zum_wohl: \"zum wohl\" as SpeechConDE,\n};\nexport type Effect = \"whispered\";\nexport const Effect = {\n    whispered: \"whispered\" as Effect,\n};\nexport type BreakStrengthType = \"none\" | \"x-weak\" | \"weak\" | \"medium\" | \"strong\" | \"x-strong\";\n/**\n * amazon:VB: Interpret the word as a verb (present simple).\n *\n * amazon:VBD: Interpret the word as a past participle.\n *\n * amazon:NN: Interpret the word as a noun.\n *\n * amazon:SENSE_1:\u2009 Use the non-default sense of the word. For example,\n *   the noun \u201Cbass\u201D is pronounced differently depending on meaning.\n *   The \u201Cdefault\u201D meaning is the lowest part of the musical range. The\n *   alternate sense (which is still a noun) is a freshwater fish.\n *   Specifying <speak><w role=\"amazon:SENSE_1\">bass</w>\"</speak>\n *   renders the non-default pronunciation (freshwater fish).\n */\nexport type PartOfSpeech = \"amazon:VB\" | \"amazon:VBD\" | \"amazon:NN\" | \"amazon:SENSE_1\";\nexport const PartOfSpeech = {\n    /**\n     * Interpret the word as a verb (present simple).\n     */\n    verb: \"amazon:VB\" as PartOfSpeech,\n    /**\n     * Interpret the word as a past participle.\n     */\n    past_participle: \"amazon:VBD\" as PartOfSpeech,\n    /**\n     * Interpret the word as a noun.\n     */\n    noun: \"amazon:NN\" as PartOfSpeech,\n    /**\n     * Use the non-default sense of the word. For example,\n     * the noun \u201Cbass\u201D is pronounced differently depending on meaning.\n     * The \u201Cdefault\u201D meaning is the lowest part of the musical range.\n     * The alternate sense (which is still a noun) is a freshwater\n     * fish. Specifying\n     * <speak><w role=\"amazon:SENSE_1\">bass</w>\"</speak>\n     * renders the non-default pronunciation (freshwater fish).\n     */\n    sense1: \"amazon:SENSE_1\" as PartOfSpeech,\n};\n\nexport class Ssml {\n    private static lc: string = `[${Ssml.name}]`;\n    /**\n     * Wraps a given list of paragraph strings in `<speak>` tags, with\n     * optional paragraph `<p>` tags.\n     *\n     * @param paras individual paragraphs to be wrapped in <p></p> tags.\n     * @param addParaTags If true, wraps individual strings in paras with `<p>` tags. Otherwise just concats.\n     */\n    static wrapSsmlSpeak(paras: string[], addParaTags: boolean = true): string {\n        let result: string = \"<speak>\" +\n            paras.reduce((agg, p) => {\n                return addParaTags ? agg + \"<p>\" + p + \"</p>\" : agg + p;\n            }, \"\") +\n            \"</speak>\";\n        return result;\n    }\n    /**\n     * This simply replaces <speak> and </speak> tags with an empty\n     * string.\n     *\n     * Use this when you want to add some text to existing ssml and\n     * then re-wrap the ssml.\n     *\n     * @see {Helper.stripSsml} function.\n     *\n     * @param ssml with <speak> tag around the whole thing.\n     */\n    static unwrapSsmlSpeak(ssml: string): string {\n        return ssml.replace(/\\<speak\\>/g, \"\").replace(/\\<\\/speak\\>/g, \"\");\n    }\n    /**\n     * Simply wraps with <p> tag.\n     *\n     * Represents a paragraph. This tag provides extra-strong breaks\n     * before and after the tag. This is equivalent to specifying a\n     * pause with <break strength=\"x-strong\"/>.\n     *\n     * @param text to wrap\n     */\n    static p(text: string): string {\n        return '<p>' + text + '</p>';\n    }\n    /**\n     * Simply wraps with <s> tag.\n     *\n     * Represents a sentence. This tag provides strong breaks before\n     * and after the tag.\n     *\n     * This is equivalent to:\n     *     Ending a sentence with a period (.).\n     *     Specifying a pause with <break strength=\"strong\"/>.\n\n     * @param text to wrap\n     */\n    static s(text: string): string {\n        return '<s>' + text + '</s>';\n    }\n    /**\n     * Strips all tags within ssml to produce plain text.\n     *\n     * @see {Helper.unwrapSsmlSpeak} function.\n     *\n     * @param ssml to strip\n     */\n    static stripSsml(ssml: string): string {\n        const stripped = ssml\n            // Combines </p> <p> to not double para breaks\n            .replace(/\\<\\/p\\>[ ]*\\<p\\>/g, \"<p>\")\n            // remove spaces after <p>,</p> tags\n            .replace(/\\<p\\>(?=[ ])/g, \"<p>\")\n            .replace(/\\<\\/p\\>(?=[ ])/g, \"</p>\")\n            // convert <p> and </p> to two new lines\n            .replace(/\\<[\\/]*p\\>/g, \"\\n\\n\")\n            // Strip all remaining tags\n            .replace(/(<([^>]*)>)/ig, \"\")\n            // Replace multiple spaces with a single space\n            .replace(/  +/g, ' ')\n            .replace(/\\\\n\\\\n\\\\n/g, \"\\n\\n\")\n            // .replace(/^\\\\n+/, \"\")\n            .replace(/^\\n+/, \"\")\n            .replace(/\\n+$/, \"\");\n        return stripped;\n    }\n    /**\n     * Wraps a given text in an ssml phoneme tag with the given\n     * pronunciation and alphabet.\n     *\n     * @param text Literal text that we're wrapping the phoneme tag around, e.g. \"sewing\".\n     * @param pronunciation the phoneme itself, e.g. \"so\u028A\u026A\u014B\"\n     * @param alphabet phoneme alphabet, either \"ipa\" or \"x-sampe\" (ATOW)\n     *\n     * @see {@link https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#prosody|SsmlReference}\n     */\n    static phoneme(text: string, pronunciation: string, alphabet: \"ipa\" | \"x-sampa\" = \"ipa\"): string {\n        return `<phoneme alphabet=\"${alphabet}\" ph=\"${pronunciation}\">${text}</phoneme>`;\n    }\n    /**\n     * Wraps a given text in an ssml emphasis tag.\n     *\n     * e.g. <emphasis level=\"${level}\">${text}</emphasis>`\n     *\n     * @param text to wrap with the emphasis tag\n     * @param level attribute in emphasis tag. Valid values \"strong\" | \"moderate\" | \"reduced\" = \"moderate\"\n     *\n     * @see {@link https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#prosody|SsmlReference}\n     */\n    static emphasis(text: string, level: \"strong\" | \"moderate\" | \"reduced\" = \"moderate\"): string {\n        return `<emphasis level=\"${level}\">${text}</emphasis>`;\n    }\n    /**\n     * Wraps a given text in an ssml prosody tag with the given\n     * options of rate, pitch, and/or volume.\n     *\n     * @param rate valid values ATOW \"x-slow\" | \"slow\" | \"medium\" | \"fast\" | \"x-fast\" | number,\n     * @param pitch valid values ATOW \"x-low\" | \"low\" | \"medium\" | \"high\" | \"x-high\" | number,\n     * @param volume valid values ATOW \"silent\" | \"x-soft\" | \"soft\" | \"medium\" | \"loud\" | \"x-loud\" | number\n     *\n     * @see {@link https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#prosody|SsmlReference}\n     */\n    // static prosody(text, { rate, pitch, volume }) {\n    static prosody(text: string, { rate, pitch, volume }: {\n        rate?: ProsodyRateType;\n        pitch?: ProsodyPitchType;\n        volume?: ProsodyVolumeType;\n    }): string {\n        const lc = `${Ssml.lc}${Ssml.prosody.name}`;\n        let attrs = \"\";\n        // adds the + to positive numbers\n        if (rate || rate === 0) {\n            const rateText = typeof rate === 'number' ?\n                rate + \"%\" :\n                rate;\n            attrs += `rate=\"${rateText}\"`;\n        }\n        if (pitch || pitch === 0) {\n            let pitchText: string;\n            if (typeof pitch === 'number') {\n                const pitchNum = pitch;\n                if (pitch >= 0) {\n                    const max = 50;\n                    if (pitchNum > max) { console.warn(`${lc} max: ${max}, actual: ${pitchNum} (W: 7fd9706e59f24dba896e2de149904677)`); }\n                    pitchText = \"+\" + pitchNum + \"%\";\n                } else {\n                    const min = -33.3;\n                    if (pitchNum < min) { console.warn(`${lc} min: ${min}, actual: ${pitchNum} (W: 90f4c21672034c51a8a95dcfcd281f98)`); }\n                    pitchText = \"-\" + pitchNum + \"%\";\n                }\n            } else {\n                pitchText = pitch;\n            }\n            attrs = attrs ? attrs + \" \" : attrs;\n            attrs += `pitch=\"${pitchText}\"`;\n        }\n        if (volume || volume === 0) {\n            let volumeText: string;\n            if (typeof volume === 'number') {\n                let volumeNum = volume;\n                if (volumeNum >= 0) {\n                    const max = 4.08;\n                    if (volumeNum > max) { console.warn(`${lc} max: ${max}, actual: ${volumeNum} (W: 7db9521e6b3e418faca89d2f5cfa4f2c)`); }\n                    volumeText = \"+\" + volumeNum + \"%\";\n                } else {\n                    const min = -12;\n                    if (volumeNum < min) { console.warn(`${lc} min: ${min}, actual: ${volumeNum} (W: 49210d930272498e828d2c9a815ceea0)`); }\n                }\n\n                volumeText = volumeNum + \"%\";\n            } else {\n                volumeText = volume;\n\n            }\n            attrs = attrs ? attrs + \" \" : attrs;\n            attrs += (volume ? `volume=\"${volumeText}\"` : \"\");\n        }\n        return \"<prosody \" + attrs + \">\" + text + \"</prosody>\";\n    }\n    /**\n     * Generates SpeechCon SSML.\n     * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speechcon-reference\n     */\n    static speech(speechCon: SpeechCon): string {\n        return `<say-as interpret-as=\"interjection\">${speechCon}</say-as>`;\n    }\n    /**\n     * Applies Amazon-specific effects to the speech.\n     *\n     * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#amazon-effect\n     *\n     * The name of the effect to apply to the speech. Available effects:\n     *   whispered: Applies a whispering effect to the speech.\n     * @param effect Which amazon:effect. ATOW only whispered implemented.\n     * @param s text to wrap in the effect.\n     */\n    static amazon(effect: Effect, s: string): string {\n        return `<amazon:effect name=\"${effect}\">${s}</amazon:effect>`;\n    }\n    /**\n     * The audio tag lets you provide the URL for an MP3 file that the\n     * Alexa service can play while rendering a response. You can use\n     * this to embed short, pre-recorded audio within your service\u2019s\n     * response. For example, you could include sound effects alongside\n     * your text-to-speech responses, or provide responses using a\n     * voice associated with your brand. For more information, see\n     * Including Short Pre-Recorded Audio in your Response at\n     * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/handling-requests-sent-by-alexa#audio.\n     *\n     * Note the following requirements and limitations:\n     *\n     * * The MP3 must be hosted at an Internet-accessible HTTPS\n     *   endpoint. HTTPS is required, and the domain hosting the MP3\n     *   file must present a valid, trusted SSL certificate.\n     *   Self-signed certificates cannot be used.\n     * * The MP3 must not contain any customer-specific or other\n     *   sensitive information.\n     * * The MP3 must be a valid MP3 file (MPEG version 2).\n     * * The audio file cannot be longer than ninety (90) seconds.\n     * * The bit rate must be 48 kbps. Note that this bit rate gives a\n     *   good result when used with spoken content, but is generally\n     *   not a high enough quality for music.\n     * * The sample rate must be 16000 Hz.\n     *\n     * You may need to use converter software to convert your MP3 files\n     * to the required codec version (MPEG version 2) and bit rate (48\n     * kbps).\n     *\n     * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#audio\n     *\n     * @param srcUrl Specifies the URL for the MP3 file.\n     */\n    static audio(srcUrl: string): string {\n        return `<audio src=\"${srcUrl}\" />`;\n    }\n    /**\n     * Represents a pause in the speech. Set the length of the pause\n     * with the strength or time attributes.\n     *\n     * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#break\n     *\n     * @param param0\n     */\n    static break({ strength, s, ms }: {\n        /**\n         * none:     No pause should be outputted. This can be used to remove a pause that would normally occur (such as after a period).\n         *\n         * x-weak:   No pause should be outputted (same as none).\n         *\n         * weak:     \u2009Treat adjacent words as if separated by a single comma (equivalent to medium).\n         *\n         * medium:   Treat adjacent words as if separated by a single comma.\n         *\n         * strong:   Make a sentence break (equivalent to using the <s> tag).\n         *\n         * x-strong: Make a paragraph break (equivalent to using the <p> tag).\n         */\n        strength?: BreakStrengthType;\n        /**\n         * Duration of the pause in seconds; up to 10 seconds.\n         */\n        s?: number;\n        /**\n         * Duration of the pause in milliseconds; up to 10000 milliseconds.\n         */\n        ms?: number;\n    }): string {\n        const lc = `${Ssml.lc}${Ssml.break.name}`;\n        if (strength) {\n            return `<break strength=\"${strength}\"/>`;\n        } else if (s || s === 0) {\n            const min = 0;\n            const max = 10;\n            if (s < min) {\n                console.warn(`${lc} min: ${min}, actual: ${s} (W: 6ff97060a6734f20b16a81a20d06630e)`);\n                s = min;\n            } else if (s > max) {\n                console.warn(`${lc} max: ${max}, actual: ${s} (W: d57ed120e09c4fcaa19b864bdf9f1fc7)`);\n                s = max;\n            }\n            return `<break time=\"${s}s\"/>`;\n        } else if (ms || ms === 0) {\n            const min = 0;\n            const max = 10000;\n            if (ms < min) {\n                console.warn(`min: ${min}, actual: ${ms} (W: 0addf6dbab1844a9906bd18a859be3d7)`);\n                ms = 0;\n            } else if (ms > max) {\n                console.warn(`max: ${max}, actual: ${ms} (W: f46b9868ec6d4ef2abd4f2aefe879427)`);\n                ms = max;\n            }\n            return `<break time=\"${ms}ms\"/>`;\n        } else {\n            throw new Error('Unknown break parameters (E: 1ae569301a354c28a54cc06b58c93b87)');\n        }\n    }\n\n    /**\n     * Takes a given text that will be written and provides an alias\n     * for it when it's actually spoken.\n     *\n     * For example, if the written text is the element symbol \"Mg\", then\n     * you probably want to verbally say the entire word: \"Magnesium\".\n     * In this case, the \"text\" is \"Mg\" and the \"alias\" is \"Magnesium\".\n     *\n     * @see (@link https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#sub)\n     *\n     * @param text Written text that will be substituted when spoken, e.g. \"Mg\"\n     * @param alias Spoken alias that will be spoken, e.g. \"Magnesium\"\n     */\n    static sub(text: string, alias: string): string {\n        return `<sub alias=\"${alias}\">${text}</sub>`;\n    }\n\n    /**\n     * Similar to <say-as>, this tag customizes the pronunciation of\n     * words by specifying the word\u2019s part of speech.\n     *\n     * @param text Text that requires clarity.\n     * @param partOfSpeech Context provided for the given text.\n     */\n    static w(text: string, partOfSpeech: PartOfSpeech): string {\n        return `<w role=\"${partOfSpeech}\">${text}</w>`;\n    }\n\n    /**\n     * Describes how the text should be interpreted. This lets you\n     * provide additional context to the text and eliminate any\n     * ambiguity on how Alexa should render the text. Indicate how\n     * Alexa should interpret the text with the interpret-as attribute.\n     *\n     * Note that the Alexa service attempts to interpret the provided\n     * text correctly based on the text\u2019s formatting even without this\n     * tag. For example, if your output speech includes \u201C202-555-1212\u201D,\n     * Alexa speaks each individual digit, with a brief pause for each\n     * dash. You don\u2019t need to use <say-as interpret-as=\"telephone\"> in\n     * this case. However, if you provided the text \u201C2025551212\u201D, but\n     * you wanted Alexa to speak it as a phone number, you would need\n     * to use <say-as interpret-as=\"telephone\">.\n     *\n     * @example\n     * <speak>\n     *     Here is a number spoken as a cardinal number:\n     *     <say-as interpret-as=\"cardinal\">12345</say-as>.\n     *     Here is the same number with each digit spoken separately:\n     *     <say-as interpret-as=\"digits\">12345</say-as>.\n     *     Here is a word spelled out: <say-as interpret-as=\"spell-out\">hello</say-as>\n     * </speak>\n     *\n     * @see\n     * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#say-as\n     */\n    static sayAs({ text, interpret, format }: {\n        /**\n         * Text to specify interpretation.\n         */\n        text: string;\n        /**\n         * Value that indicates how text should be interpreted.\n         *\n         * @see {InterpretAs}\n         */\n        interpret: InterpretAs;\n        /**\n         * Only used when interpret-as is set to date. Set to one of\n         * the following to indicate format of the date:\n         *\n         *     mdy\n         *     dmy\n         *     ymd\n         *     md\n         *     dm\n         *     ym\n         *     my\n         *     d\n         *     m\n         *     y\n         *\n         * Alternatively, if you provide the date in YYYYMMDD format,\n         * the format attribute is ignored. You can include question\n         * marks (?) for portions of the date to leave out. For\n         * instance, Alexa would speak <say-as interpret-as=\"date\">????\n         * 0922</say-as> as \u201CSeptember 22nd\u201D.\n         */\n        format?: SayAsDate;\n    }): string {\n        const lc = `${Ssml.lc}[${Ssml.sayAs.name}]`;\n        try {\n            if (format) {\n                if (interpret !== As.date) {\n                    throw new Error(`\\`format\\` arg requires (implies) \\`interpret\\` === \"date\" (E: 2a470b25ac284ec4bec9eb3e6a704b6b)`);\n                }\n                return `<say-as interpret-as=\"${interpret}\" format=\"${format}\">${text}</say-as>`;\n            } else {\n                return `<say-as interpret-as=\"${interpret}\">${text}</say-as>`;\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n}\n", "import { HELPER_LOG_A_LOT } from '../constants.mjs';\nimport { Ssml } from './ssml-helper.mjs';\n\nconst logalot = HELPER_LOG_A_LOT;\n\nexport type LanguageCode = \"en\" | \"de\" | \"en-US\" | \"en-GB\" | \"en-CA\" | \"en-IN\" | \"de-DE\";\nexport const LanguageCode = {\n    en: \"en\" as LanguageCode,\n    de: \"de\" as LanguageCode,\n    enUS: \"en-US\" as LanguageCode,\n    enGB: \"en-GB\" as LanguageCode,\n    enCA: \"en-CA\" as LanguageCode,\n    enIN: \"en-IN\" as LanguageCode,\n    deDE: \"de-DE\" as LanguageCode,\n};\n\n/**\n * Interface for each record in the lex data.\n *\n * When specifying `TProps`, be sure it is a flat key: value object. (I think...) Definitely not a circular reference complex object, so maybe any non-circular POCO will work.\n */\nexport interface LexDatum<TProps extends PropsData = PropsData> {\n    /**\n     * Language of the lexical datum.\n     */\n    language?: LanguageCode;\n    /**\n     * Lexical items with the same id are considered alternatives for\n     * the equivalent message, e.g. \"Hello\" and \"Howdy\".\n     *\n     * If you have multiple LexDatums with the same id, then this\n     * can differentiate among them to get the _exact_ record.\n     *\n     * Basically this is an optional unique id, but the data overall\n     * is indexed by a non-unique \"id\" string. :nose:? maybe...\n     */\n    specifier?: string;\n    /**\n     * Lexical items with the same id are considered alternatives for\n     * the equivalent message, e.g. \"Hello\" and \"Howdy\".\n     *\n     * If you have multiple LexDatums with the same id, then this\n     * can define the weighting of chance when selecting one of those\n     * alternatives.\n     *\n     * Must be non-zero. Default weighting is 1.\n     *\n     * @see Lex.pickDatum\n     */\n    weighting?: number;\n    /**\n     * Keywords relating to the datum. You can specify keywords.\n     */\n    keywords?: string[];\n    /**\n     * This is the lines of plain text.\n     *\n     * There should be no ssml tags in here.\n     */\n    texts?: string[];\n    /**\n     * This is the ssml equivalent to `text`.\n     *\n     * Do NOT include any <speak> tags in here.\n     */\n    ssmls?: string[];\n    /**\n     * Additional dynamic properties to filter/match against.\n     *\n     * Use Case:\n     *\n     * Currently, I'm doing x=123 in keywords, and this is meant to\n     * improve upon that.\n     */\n    props?: TProps;\n}\nexport interface LexGetOptions<TProps extends PropsData = PropsData> {\n    /**\n     * Language of datum to get.\n     */\n    language?: LanguageCode;\n    /**\n     * Specifier of datum to get.\n     */\n    specifier?: string;\n    /**\n     * Keywords of datum to get.\n     */\n    keywords?: string[];\n    /**\n     * Determines how the `LexGetOptions.keywords` match with filtering\n     * data.\n     * @see {KeywordMode}\n     */\n    keywordMode?: KeywordMode;\n    /**\n     * Index (0-based) into text/ssml of LexDatum to get.\n     * If not provided, will return all lines.\n     * Basically, use this if you just want a single string from the\n     * texts/ssmls array but don't want to duplicate that in a separate\n     * data entry.\n     *\n     * @example If you have texts of [ \"a\", \"b\", \"c\" ], but you just\n     * want the \"b\" line, you would pass in a lineIndex of 1.\n     */\n    lineIndex?: number;\n    /**\n     * If provided, and if there are multiple lines in datum's\n     * text/ssml, then this determines how they are concatenated.\n     *\n     * @see LexLineConcat\n     */\n    lineConcat?: LexLineConcat;\n    /**\n     * If lineConcat is \"delim\", then it will concat using this\n     * string as a delimiter. I'll have a default in the `get`\n     * function.\n     *\n     * @see Lex.get\n     */\n    lineConcatDelim?: string;\n    /**\n     * How to capitalize the lex item text output when concatenating\n     * multiple lines in texts/ssmls.\n     *\n     * NOTE:\n     * I'm not sure if I should make it capitalize the ssml, but\n     * my hunch is to NOT do this, since that is supposed to be spoken\n     * text.\n     *\n     * @see LexCapitalize for individual options.\n     */\n    capitalize?: LexCapitalize;\n    /**\n     * Template placeholder arguments. Each template in Lex can either\n     * be a reference to another Lex datum, e.g. $(hi), or it can be\n     * a template placeholder, e.g. $name, $age, $0, $1, etc. It simply\n     * has to start with a $ and be followed by one or more word\n     * characters ([a-zA-Z_0-9]+, i.e. \\w+).\n     *\n     * So this javascript object is in the format of\n     *   `\"placeholder\": \"replacement\"`, e.g.\n     *\n     * NOTE: If you want different variable replacements for texts and\n     * ssmls, then use this config option for the texts and use\n     * ssmlVars for the ssmls.\n     *\n     * @example\n     * In Lex data:\n     *   \"Welcome back, $username!\"\n     * Calling code:\n     *   `lex._('greeting', { vars: { username } })`\n     * If the text is  and this is called\n     * with , then the output\n     * would be e.g. \"Welcome back, Cotter!\"\n     * (equivalent to `Welcome back, ${username}!`)\n     */\n    vars?: { [key: string]: string; };\n    /**\n     * Same as vars option, but will only replace template variables\n     * in the `ssmls`.\n     */\n    ssmlVars?: {\n        [key: string]: string;\n    };\n    /**\n     * Additional dynamic properties to filter/match against.\n     *\n     * Use Case:\n     *\n     * Currently, I'm doing x=123 in keywords, and this is meant to\n     * improve upon that.\n     *\n     * ## notes\n     *\n     * These property filters require lambda functions, and as such,\n     * these cannot be used from within template references in\n     * lex data. see {@link Lex.replaceTemplateRefs}\n     */\n    props?: PropsFilter<TProps>;\n    /**\n     * Determines how the props predicate functions.\n     * @see PropertyPredicateLevel\n     */\n    propsMode?: PropsFilterMode;\n    /**\n     * \"Catchall\" predicate filter that acts on the entire lex datum.\n     *\n     * So if you don't have a specific filter option in the params list, use this as\n     * a backup to just filter against the entire datum in a custom way.\n     *\n     * ## driving use case\n     *\n     * I want to reverse get where the `LexDatum.texts` property is exactly a\n     * certain value and get the reverse mapping to the \"semantic id\".  So a user\n     * says some natural language, and I map that back to the possibility(s) for the\n     * semantic id of that user word/phrase.\n     */\n    fnDatumPredicate?: LexDatumPredicate<TProps>,\n}\n/**\n * Contains properties per datum that allow for more complex filtering with\n * two strategies:\n * 1. per property name via a lambda\n * 2. per entire props object via a lambda\n *\n * This is the type in the LexDatum.props property.\n *\n * NOTE: atow this must be just a flat dictionary, i.e. cannot contain nested\n * objects. However, if you want to use FilterPerProps filtering, I believe you\n * can just `any` cast this and do your filtering predicate against the entire\n * props object as you like.\n * */\nexport type PropsData = { [propName: string]: any; };\n/** This is the type used in LexGetOptions.prFilter either per property or per the entire prop data object. */\nexport type PropsFilter<TProps> = FilterPerProp | FilterPerProps<TProps>;\n/** Individual property predicate */\nexport type PropertyPredicate = (propName: string) => boolean;\n/** Filter on individual property level. */\nexport type FilterPerProp = { [propName: string]: PropertyPredicate; };\n/** Filter at the entire props object level (`LexDatum.props`). */\nexport type FilterPerProps<TProps> = (props: TProps) => boolean;\n\nexport interface LexFindOptions<TProps extends PropsData = PropsData> {\n    fnDatumPredicate?: LexDatumPredicate<TProps>,\n}\nexport type LexFindResults<TProps extends PropsData = PropsData> = { [id: string]: LexDatum<TProps>[] }\n\n/**\n * filter against the entier lex datum entry. see the LexGet options.\n */\nexport type LexDatumPredicate<TProps extends PropsData> = (value: LexDatum<TProps>) => boolean;\n\n/**\n * keywords are used to filter lex items. this sets how those keywords are\n * interpreted.\n */\nexport type KeywordMode = \"any\" | \"all\" | \"none\";\n/**\n * keywords are used to filter lex items. this sets how those keywords are\n * interpreted.\n */\nexport const KeywordMode = {\n    /** Any of the keywords must match to return a lex result. */\n    any: \"any\" as KeywordMode,\n    /** All of the keywords must match to return a lex result. */\n    all: \"all\" as KeywordMode,\n    /** Only return results that do NOT include any of the keywords. */\n    none: \"none\" as KeywordMode,\n};\n\nexport type PropsFilterMode = \"prop\" | \"props\";\nexport const PropertyPredicateLevel = {\n    /**\n     * Predicate acts upon individual properties.\n     * So you'll pass an object in with prop key and a predicate(s).\n     *\n     * Check out advanced unit tests for more concrete examples.\n     *\n     * @example props: { id: x => x === \"id2\", color: x => x === \"orange\" }\n     */\n    prop: \"prop\" as PropsFilterMode,\n    /**\n     * Predicate acts upon the datum's entire props object.\n     * So you'll pass a single predicate that is the entire props\n     * object, i.e. datum[props].\n     *\n     * Check out advanced unit tests for more concrete examples.\n     *\n     * @example { props: (p: PropsData) => { return p && p.id && p.id === \"id1\"; }, propsMode: \"props\"\n     */\n    props: \"props\" as PropsFilterMode,\n};\n\n// export type LexResultType = \"text\" | \"ssml\" | \"obj\";\n\n/**\n * Result object when using `Lex._`\n *\n * @see Lex\n * @see Lex.get\n */\nexport interface LexResultObj<TProps extends PropsData = PropsData> {\n    /**\n     * The text output of the single datum that was picked.\n     */\n    text: string;\n    /**\n     * The ssml output of the single datum that was picked.\n     */\n    ssml: string;\n    /**\n     * The single raw datum that was picked.\n     */\n    datum: LexDatum<TProps>;\n    /**\n     * All of the data that matched the given params (specifier,\n     * keywords, language, etc.)\n     */\n    rawData: LexDatum<TProps>[];\n}\n\nexport type LexCapitalize = \"upperfirst\" | \"uppereach\" | \"lowerfirst\" | \"lowereach\" | \"none\";\nexport const LexCapitalize = {\n    /**\n     * Uppercase the first letter of only the first line in texts/ssmls.\n     */\n    upperfirst: \"upperfirst\" as LexCapitalize,\n    /**\n     * Uppercase the first letter of each line in texts/ssmls.\n     */\n    uppereach: \"uppereach\" as LexCapitalize,\n    /**\n     * Lowercase the first letter of only the first line in texts/ssmls.\n     */\n    lowerfirst: \"lowerfirst\" as LexCapitalize,\n    /**\n     * Lowercase the first letter of each line in texts/ssmls.\n     */\n    lowereach: \"lowereach\" as LexCapitalize,\n    /**\n     * Leave the casing as-is for texts/ssmls.\n     */\n    none: \"none\" as LexCapitalize,\n};\n\nexport type LexLineConcat = \"paragraph\" | \"sentence\" | \"newline\" | \"delim\";\nexport const LexLineConcat = {\n    /**\n     * Each line will be combined into a single string of paragraphs.\n     * @example\n     * [\"Line 1.\", \"Line 2.\"] will become\n     *   if text: \"Line 1.\\n\\nLine 2.\"\n     *   if ssml: \"<p>Line 1.</p><p>Line 2.</p>\"\n     */\n    p: \"paragraph\" as LexLineConcat,\n    paragraph: \"paragraph\" as LexLineConcat,\n    /**\n     * Each line will be combined into a single string of sentences.\n     * @example\n     * [\"Line 1.\", \"Line 2.\"] will become\n     *   if text: \"Line 1. Line 2.\"\n     *   if ssml: \"<s>Line 1</s><s>Line 2</s>\"\n     */\n    s: \"sentence\" as LexLineConcat,\n    sentence: \"sentence\" as LexLineConcat,\n    /**\n     * Each line will be combined into a single string with new\n     * line feeds between each line.\n     *\n     * Note: For Ssml, this is the same as \"paragraph\".\n     *\n     * @example\n     * [\"Line 1.\", \"Line 2.\"] will become\n     *   if text: \"Line 1.\\nLine 2.\"\n     *   if ssml: \"<p>Line 1.</p><p>Line 2.</p>\"\n     */\n    n: \"newline\" as LexLineConcat,\n    newline: \"newline\" as LexLineConcat,\n    /**\n     * Each line will be combined into a single string with each\n     * line delimited by the delimiter specified in the function.\n     *\n     * @example\n     * [\"Line 1.\", \"Line 2.\"] with delim | will become\n     *   if text: \"Line 1.|Line 2.\"\n     *   if ssml: \"Line 1.|Line 2.\"\n     */\n    delim: \"delim\" as LexLineConcat,\n};\nexport type LexData<TProps extends PropsData = PropsData> = {\n    [key: string]: LexDatum<TProps>[];\n};\n\n/**\n * These options control mostly the default behavior for filtering lex results\n * when consuming via the `Lex._(someIdentifier, opts)` call.  When you don't\n * specify in the `opts` how to filter, these values will be used.\n *\n * These options are in the constructor of the {@link Lex} class.\n */\nexport interface LexCtorOpts {\n    /**\n     * This is the language that your data will default to.\n     *\n     * This means that entries defined in the Lex data that do not\n     * have an explicit 'language' set will be interpreted as this\n     * language.\n     *\n     * So basically, if you're an American with American data, leave\n     * this as en-US. If you're a German speaker writing a skill\n     * that is primarily targeted at a German-speaking audience,\n     * then set this to de-DE and you don't need to explicitly\n     * set each entry to this.\n     *\n     * Then, when you go to translate into other languages, you can\n     * add on the explicit language markers in data. The overall\n     * mechanism allows you to skip this for the first language\n     * you write the skill in.\n     *\n     * @see requestLanguage\n     */\n    defaultLanguage?: LanguageCode;\n    /**\n     * This is the language that is coming in from the request.\n     *\n     * @see defaultLanguage\n     */\n    requestLanguage?: LanguageCode;\n    /**\n     * Default setting when concatenating lines. This will depend on how most of\n     * your data is structured. For example, it's designed so that you input\n     * your data separated by paragraphs, so the concat would be \"paragraph\".\n     * But if you already have data with <p> tags in your ssml, then you may\n     * want to set this to \"delim\" and do your own interpretation of using the\n     * multiple strings for the data.\n     *\n     * Defaults to delim & \"\" because most of the time, I find I\n     * just have a single line and want the single thing returned.\n     * This helps with templating, chunking, etc.\n     */\n    defaultLineConcat?: LexLineConcat;\n    /**\n     * Default delimiter used when using `lineConcatDelim`.\n     *\n     * Defaults to delim & \"\" because most of the time, I find I just have a\n     * single line and want the single thing returned.  This helps with\n     * templating, chunking, etc.\n     */\n    defaultDelim?: string;\n    /**\n     * Default capitalization action when getting texts/ssmls.\n     */\n    defaultCapitalize?: LexCapitalize;\n    /**\n     * When using keyword filtering, this is the default mode to be used\n     * when not explicitly set in the lex consumer.\n     */\n    defaultKeywordMode?: KeywordMode;\n    /**\n     * When using props filtering, this is the default mode to be used\n     * when not explicitly set in the lex consumer.\n     */\n    defaultPropsMode?: PropsFilterMode;\n}\n\n\n\n/**\n * Lex is a helper for your lexical data, i.e. the things that you get\n * Alexa to say. This can be used for i18n, but really it's a broader\n * helper to create more dynamic speech/text for Alexa to say and\n * present via cards.\n *\n * I am making this after learning my lessons with creating dynamic,\n * alternative-laden text and/or ssml generation for use with both\n * Alexa's speech, as well as outputting plain text to\n * cards. I'm designing it to be (actually) simple to use, but with\n * robustness allowed the more you become comfortable with it.\n *\n * Simple Usage\n *\n * To use it, you simply init what you want her to be able to say.\n * Then, when you want to create her speech, you call `text` or `ssml`\n * and pass in your options, the primary one being the `id`.\n *\n * For example, you could define the following data:\n    ```\n    const data: LexData = {\n        'hi': [\n            { texts: [ \"Hi\" ]}\n        ]\n    }\n    ```\n * To access this, you would call `Lex._('hi').text` to simply get the\n * plain text entry for \"hi\".\n *\n * Alternatives\n *\n * But there are a LOT of ways to say \"hi\", and this is the primary\n * reason for using Lex: Alternatives. With Lex, multiple items with\n * the same id are considered alternatives.\n *\n    ```\n    const data: LexData = {\n        'hi': [\n            { texts: [ \"Hi\" ] },\n            { texts: [ \"Hello\" ] },\n            { texts: [ \"Howdy\" ] }\n        ]\n    }\n    ```\n * Again, to access this, you would call the same line:\n *   `Lex._('hi').text\n *\n * So by using the _same_ calling code, you could get any one of these\n * texts as _alternatives_ for the \"hi\" lex datum. This is a huge\n * difference between natural voice interaction and computer UI as we\n * have known it up to now.\n *\n * If you want to get really fancy (looking forward to AI/ML), you can\n * weight the various alternatives, for example if you want to only\n * say \"Howdy\" a small percentage of the time. You could define this as follows:\n *\n    ```\n    const data: LexData = {\n        'hi': [\n            { texts: [ \"Hi\" ] },\n            { texts: [ \"Hello\" ] },\n            { texts: [ \"Howdy\" ], weighting: 0.2 }\n        ]\n    }\n    ```\n * Again, there is _no_ change to the calling code. This really allows\n * for a wonderful layer of dynamicism, and is easy to do.\n *\n * Internationalization (i18n)\n *\n * You can have your text be localized, but not worry about it to start\n * off with. It's _implicit_ i18n. So the above examples are actually\n * not really attached to any language, even though I'm writing in\n * English (en-US). This is because the i18n aspect relies on both the\n * data and the retrieval of the data via the `language` param option.\n *\n    ```\n    const data: LexData = {\n        'hi': [\n            { texts: [ \"Hi\" ] },\n            { texts: [ \"Hello\" ] },\n            { texts: [ \"Howdy\" ], weighting: 0.2 },\n            { texts: [ \"Cheers\" ], language: \"en-GB\" },\n            { texts: [ \"Guten Tag\" ], language: \"de-DE\" }\n        ]\n    }\n    ```\n/**\n * Lex is a helper for your lexical data, i.e. the things that you get\n * Alexa to say. This can be used for i18n, but really it's a broader\n * helper to create more dynamic speech/text for Alexa to say and\n * present via cards.\n *\n * I am making this after learning my lessons with creating dynamic,\n * alternative-laden text and/or ssml generation for use with both\n * Alexa's speech, as well as outputting plain text to\n * cards. I'm designing it to be (actually) simple to use, but with\n * robustness allowed the more you become comfortable with it.\n *\n * Simple Usage\n *\n * To use it, you simply init what you want her to be able to say.\n * Then, when you want to create her speech, you call `text` or `ssml`\n * and pass in your options, the primary one being the `id`.\n *\n * For example, you could define the following data:\n    ```\n    const data: LexData = {\n        'hi': [\n            { texts: [ \"Hi\" ]}\n        ]\n    }\n    ```\n * To access this, you would call `Lex._('hi').text` to simply get the\n * plain text entry for \"hi\".\n *\n * Alternatives\n *\n * But there are a LOT of ways to say \"hi\", and this is the primary\n * reason for using Lex: Alternatives. With Lex, multiple items with\n * the same id are considered alternatives.\n *\n    ```\n    const data: LexData = {\n        'hi': [\n            { texts: [ \"Hi\" ] },\n            { texts: [ \"Hello\" ] },\n            { texts: [ \"Howdy\" ] }\n        ]\n    }\n    ```\n * Again, to access this, you would call the same line:\n *   `Lex._('hi').text\n *\n * So by using the _same_ calling code, you could get any one of these\n * texts as _alternatives_ for the \"hi\" lex datum. This is a huge\n * difference between natural voice interaction and computer UI as we\n * have known it up to now.\n *\n * If you want to get really fancy (looking forward to AI/ML), you can\n * weight the various alternatives, for example if you want to only\n * say \"Howdy\" a small percentage of the time. You could define this as follows:\n *\n    ```\n    const data: LexData = {\n        'hi': [\n            { texts: [ \"Hi\" ] },\n            { texts: [ \"Hello\" ] },\n            { texts: [ \"Howdy\" ], weighting: 0.2 }\n        ]\n    }\n    ```\n * Again, there is _no_ change to the calling code. This really allows\n * for a wonderful layer of dynamicism, and is easy to do.\n *\n * Internationalization (i18n)\n *\n * You can have your text be localized, but not worry about it to start\n * off with. It's _implicit_ i18n. So the above examples are actually\n * not really attached to any language, even though I'm writing in\n * English (en-US). This is because the i18n aspect relies on both the\n * data and the retrieval of the data via the `language` param option.\n *\n    ```\n    const data: LexData = {\n        'hi': [\n            { texts: [ \"Hi\" ] },\n            { texts: [ \"Hello\" ] },\n            { texts: [ \"Howdy\" ], weighting: 0.2 },\n            { texts: [ \"Cheers\" ], language: \"en-GB\" },\n            { texts: [ \"Guten Tag\" ], language: \"de-DE\" }\n        ]\n    }\n    ```\n *\n * You can get at these languages multiple ways:\n *\n *   1) Choose the language when instantiating Lex.\n *      `let lex = new Lex(data, \"de-DE\");`\n *      Now, when you call `lex._(...)`, you will only return German\n *      data.\n *   2) Override the default language upon calling for data:\n *      `lex._('hi', { language: \"en-US\" }).text;`\n */\nexport class Lex<TProps extends PropsData = PropsData> {\n    protected lc: string = `[${Lex.name}]`;\n\n    data: LexData<TProps>;\n    defaultLanguage: LanguageCode;\n    defaultLineConcat: LexLineConcat;\n    /**\n     * Defaults to delim & \"\" because most of the time, I find I\n     * just have a single line and want the single thing returned.\n     * This helps with templating, chunking, etc.\n     *\n     * BREAKING CHANGE: This formerly defaulted to paragraphs, as\n     * I thought lines would mean paragraphs. No longer the case.\n     */\n    defaultDelim: string;\n    defaultCapitalize: LexCapitalize;\n    /**\n     * This is the language that is coming in from the request.\n     *\n     * @see defaultLanguage\n     */\n    requestLanguage: LanguageCode;\n    defaultKeywordMode: KeywordMode;\n    defaultPropsMode: PropsFilterMode;\n\n    constructor(\n        /**\n         * This is the initial lexical data that you want Alexa to be able to\n         * say. You can always change this dynamically at runtime as well.\n         */\n        data: LexData<TProps>,\n        /** optional opts */\n        {\n            /**\n             * This is the language that your data will default to.\n             * If a language isn't specified in `get`, `text`, or `ssml`, then this is used.\n             *\n             * This means that entries defined in the Lex data that do not\n             * have an explicit 'language' set will be interpreted as this\n             * language.\n             *\n             * So basically, if you're an American with American data, leave\n             * this as en-US. If you're a German speaker writing a skill\n             * that is primarily targeted at a German-speaking audience,\n             * then set this to de-DE and you don't need to explicitly\n             * set each entry to this.\n             *\n             * Then, when you go to translate into other languages, you can\n             * add on the explicit language markers in data. The overall\n             * mechanism allows you to skip this for the first language\n             * you write the skill in.\n             *\n             * @see requestLanguage\n             */\n            defaultLanguage = \"en-US\",\n            requestLanguage = \"en-US\",\n            /**\n             * Defaults to delim & \"\" because most of the time, I find I\n             * just have a single line and want the single thing returned.\n             * This helps with templating, chunking, etc.\n             *\n             * BREAKING CHANGE: This formerly defaulted to paragraphs, as\n             * I thought lines would mean paragraphs. No longer the case.\n             */\n            defaultLineConcat = LexLineConcat.delim,\n            /**\n             * Defaults to delim & \"\" because most of the time, I find I\n             * just have a single line and want the single thing returned.\n             * This helps with templating, chunking, etc.\n             *\n             * BREAKING CHANGE: This formerly defaulted to paragraphs, as\n             * I thought lines would mean paragraphs. No longer the case.\n             */\n            defaultDelim = \"\",\n            defaultCapitalize = \"none\",\n            defaultKeywordMode = \"any\",\n            defaultPropsMode = \"prop\",\n        }: LexCtorOpts\n    ) {\n        if (!data) { throw new Error(`data required (E: 2f8db30fa9d71d76db616ab110392c22)`); }\n        this.data = data;\n        this.defaultLanguage = defaultLanguage ?? \"en-US\";\n        this.defaultLineConcat = defaultLineConcat ?? LexLineConcat.delim;\n        this.defaultDelim = defaultDelim ?? \"\";\n        this.defaultCapitalize = defaultCapitalize ?? \"none\";\n        this.requestLanguage = requestLanguage ?? \"en-US\";\n        this.defaultKeywordMode = defaultKeywordMode ?? \"any\";\n        this.defaultPropsMode = defaultPropsMode ?? \"prop\";\n    }\n\n    /**\n     * Gets a string or array of strings of text or ssml.\n     * Builds the string or obj depending on the passed in options.\n     *\n     * NOTE: You'll probably want to actually use the `text` or `ssml`\n     * functions instead of this one.\n     *\n     * @param id Lexical items with the same id are considered alternatives for the equivalent message, e.g. \"Hello\" and \"Howdy\".\n     * @see LexGetOptions\n     */\n    get(\n        id: string,\n        {\n            language = this.requestLanguage,\n            specifier,\n            keywords, keywordMode = this.defaultKeywordMode,\n            lineIndex,\n            lineConcat = this.defaultLineConcat, lineConcatDelim = this.defaultDelim,\n            capitalize = this.defaultCapitalize,\n            vars, ssmlVars,\n            props, propsMode = this.defaultPropsMode,\n            fnDatumPredicate,\n        }: LexGetOptions<TProps> = {\n                // simplest case default options\n                language: this.requestLanguage,\n                keywordMode: this.defaultKeywordMode,\n                lineConcat: this.defaultLineConcat,\n                lineConcatDelim: this.defaultDelim,\n                capitalize: this.defaultCapitalize,\n                propsMode: this.defaultPropsMode,\n            }): LexResultObj<TProps> | null {\n        const lc = `${this.lc}[${this.get.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: e4e76a6bb301010fc13cf4456efcdc22)`); }\n\n            let lexData = this.data[id];\n\n            if (!lexData) { throw new Error(`Data id not found: ${id} (E: 4a79897167714dd5a34df77953072aaf)`); }\n\n            lexData = this.filterLexData({\n                lexData,\n                language, specifier,\n                keywords, keywordMode,\n                props: props as PropsFilter<TProps>, propsMode,\n                fnDatumPredicate,\n            });\n            if (lexData.length === 0) {\n                // no data found matching filtering.\n                // just return null and do not error.\n                return null;\n            }\n            const lexDatum = this.pickDatum(lexData)!;\n            let textLines = this.extractLines({ lexDatum, resultAs: \"text\", lineIndex });\n            textLines = this.replaceTemplateRefs({ lines: textLines, resultAs: \"text\" });\n            // Replace vars after references, so all text is fully\n            // expanded first.\n            textLines = this.replaceTemplateVars({ lines: textLines, vars: vars });\n            textLines = this.capitalizeLines({ lines: textLines, resultAs: \"text\", capitalize });\n            const text = this.concatLines({\n                lines: textLines,\n                lineType: \"text\",\n                lineConcat,\n                lineConcatDelim\n            });\n            let ssmlLines = this.extractLines({ lexDatum, resultAs: \"ssml\", lineIndex });\n            ssmlLines = this.replaceTemplateRefs({ lines: ssmlLines, resultAs: \"ssml\" });\n            // Replace vars after references, so all text is fully\n            // expanded first.\n            ssmlLines = this.replaceTemplateVars({ lines: ssmlLines, vars: ssmlVars || vars });\n            ssmlLines = this.capitalizeLines({ lines: ssmlLines, resultAs: \"ssml\", capitalize });\n            const ssml = this.concatLines({ lines: ssmlLines, lineType: \"ssml\", lineConcat, lineConcatDelim });\n\n            return { text, ssml, datum: lexDatum, rawData: lexData };\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Does a reverse lookup for lex data ids that correspond to the find\n     * criteria.\n     *\n     * @returns array of data ids that have at least one LexDatum entry that matches criteria.\n     */\n    find({ fnDatumPredicate }: LexFindOptions<TProps>): LexFindResults<TProps> | null {\n        const lc = `${this.lc}[${this.find.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 35e26d234ca2d0e987b39ee939f29c22)`); }\n            if (!fnDatumPredicate) { throw new Error(`only fnDatumPredicate implemented atow (E: 8c8babd2fa6fc4cb223b7b8c10ad5c22)`); }\n\n            const results: LexFindResults<TProps> = {};\n\n            const ids = Object.keys(this.data);\n            for (let i = 0; i < ids.length; i++) {\n                const id = ids[i];\n                const matchingDatums = this.data[id].filter(d => fnDatumPredicate(d));\n                if (matchingDatums.length > 0) { results[id] = matchingDatums; }\n            }\n\n            return Object.keys(results).length > 0 ? results : null;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * This is the original single function. it is just for backwards compatibility at this point.\n     * Probably not needed...\n     *\n     * @deprecated\n     */\n    _(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n\n    // #region syntactic sugar calls for `get`\n\n    /**\n     * just syntactic sugar for {@link Lex.get} .\n     */\n    getVariant(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n    /**\n     * just syntactic sugar for {@link Lex.get} .\n     */\n    variant(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n    /**\n     * just syntactic sugar for {@link Lex.get} .\n     */\n    getTranslation(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n    /**\n     * just syntactic sugar for {@link Lex.get} .\n     */\n    translate(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n    /**\n     * just syntactic sugar for {@link Lex.get} .\n     */\n    getSynonym(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n    /**\n     * just syntactic sugar for {@link Lex.get} .\n     */\n    synonym(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n    /**\n     * just syntactic sugar for {@link Lex.get} .\n     */\n    getI18n(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n    /**\n     * just syntactic sugar for {@link Lex.get} .\n     */\n    i18n(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null {\n        return this.get(id, opts);\n    }\n\n    // #endregion syntactic sugar calls for `get`\n\n    /**\n     * Pulls out lines from the datum, based on the what is wanted\n     * and what exists in the data.\n     *\n     * For example, you may be trying to extract text but only ssml\n     * is defined in the data. So you'll have to strip the ssml and\n     * return that. Or if you want ssml and only text exists in the\n     * data, then you'll simply return the texts.\n     *\n     * If you only want a single line out of multiple strings in the\n     * texts/ssmls array, then use lineIndex.\n     *\n     * @param param0 info\n     */\n    private extractLines({\n        lexDatum,\n        resultAs,\n        lineIndex\n    }: {\n        lexDatum: LexDatum<TProps>,\n        resultAs: \"text\" | \"ssml\",\n        lineIndex: number | undefined,\n    }): string[] {\n        const lc = `${this.lc}[${this.extractLines.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 0c21a7ed7c1b56251f39342380c47922)`); }\n\n            // ensure that either texts or ssmls is defined in data\n            if ((!lexDatum.texts || lexDatum.texts.length === 0) &&\n                (!lexDatum.ssmls || lexDatum.ssmls.length === 0)) {\n                throw new Error(`Invalid lexDatum. Datum texts and ssmls are both undefined. lexDatum: ${JSON.stringify(lexDatum)}.`);\n            }\n            // let lines;\n            let useLineIndex = lineIndex || lineIndex === 0;\n            if (resultAs === \"text\" &&\n                lexDatum.texts && lexDatum.texts.length > 0) {\n                // text wanted, text defined in data\n                return useLineIndex ?\n                    [lexDatum.texts[lineIndex!]] :\n                    lexDatum.texts;\n            } else if (resultAs === \"text\") {\n                // text wanted, but no text defined in data\n                console.warn(`building text lines from ssml (W: cfb59a05efda475ab7511acc659a5ee3)`);\n                return useLineIndex ?\n                    [Ssml.stripSsml(lexDatum.ssmls![lineIndex!])] :\n                    lexDatum.ssmls!.map(ssml => Ssml.stripSsml(ssml));\n            } else if (lexDatum.ssmls && lexDatum.ssmls.length > 0) {\n                // ssml wanted, ssml defined in data\n                return useLineIndex ?\n                    [lexDatum.ssmls[lineIndex!]] :\n                    lexDatum.ssmls;\n            } else {\n                // ssml wanted, but no ssml defined in data\n                return useLineIndex ?\n                    [lexDatum.texts![lineIndex!]] :\n                    lexDatum.texts!;\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Replaces any embedded template variables, e.g. $name, $0, etc.\n     * Note the format is \"$\" proceeded by any word characters\n     * ([a-zA-Z0-9_]).\n     *\n     * This is different than template references.\n     *\n     * @see {replaceTemplateRefs}\n     */\n    private replaceTemplateVars({\n        lines,\n        vars,\n    }: {\n        lines: string[],\n        vars?: { [key: string]: string; },\n    }): string[] {\n        const lc = `${this.lc}[${this.replaceTemplateVars.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: a756e7603d03d427c60c202cb4f6dd22)`); }\n\n            let replaceVarsSingleLine = (line: string) => {\n                let varNames = Object.keys(vars || {});\n                if (logalot) { console.log(`${lc} varNames: ${JSON.stringify(varNames)} (I: d9351cf582420b35eb3eceb923e64f22)`); }\n                return varNames.reduce((l, varName) => {\n                    if (logalot) { console.log(`${lc} varName: ${varName} (I: 8c0e4261972945d2bb4624efad14870b)`); }\n                    return l.replace(new RegExp('\\\\$' + varName, \"g\"), vars![varName]);\n                }, line);\n            };\n            if (vars) {\n                return lines.map(line => replaceVarsSingleLine(line));\n            } else {\n                return lines;\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n    /**\n     * Replaces any embedded template references, e.g. $(hi).  Note the\n     * parenthesis around \"hi\". This means it is a reference to another lex\n     * datum.\n     *\n     * This is different than template variables, e.g. $name, $0, etc.\n     *\n     * The template refs can be recursive, i.e. datum A can include a ref to\n     * datum B which includes a template to datum C.  But these cannot be\n     * self-referencing, i.e. C cannot then include a reference back to A.\n     *\n     * Template refs CANNOT work with props for filtering, as these require\n     * lambda functions.\n     *\n     * @see {replaceTemplateVars}\n     */\n    private replaceTemplateRefs({\n        lines,\n        resultAs,\n    }: {\n        /**\n         * source lines from data\n         */\n        lines: string[],\n        /**\n         * how do you want the lines back?\n         */\n        resultAs: \"ssml\" | \"text\",\n    }): string[] {\n        const lc = `${this.lc}[${this.replaceTemplateRefs.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 548949b651bbec84de5b25f3c01cf422)`); }\n            const regex = /\\$\\([\\w-]+\\|?[\\w-|\\{\\}:'\"\\s,\\[\\].,<>]+\\)/;\n\n            let replaceRefsSingleLine: (l: string) => any = (line: string) => {\n                let match = regex.exec(line);\n                if (match) {\n                    let template = match[0];\n                    // strip the $()\n                    template = template.substring(2, template.length - 1);\n                    // id|options\n                    const idAndOptions = template.split('|');\n                    const id = idAndOptions[0];\n                    const options: LexGetOptions<TProps> = idAndOptions.length === 2 ?\n                        JSON.parse(idAndOptions[1]) as LexGetOptions<TProps> :\n                        {};\n                    if (!options.lineConcat) {\n                        options.lineConcat = LexLineConcat.delim;\n                        options.lineConcatDelim = \"\";\n                    }\n                    const replacementResult = this.get(id, options);\n                    const replacement = resultAs === \"text\" ?\n                        replacementResult!.text :\n                        replacementResult!.ssml;\n                    line = line.replace(regex, replacement);\n                    // recursively call if more templates in line\n                    return regex.test(line) ?\n                        replaceRefsSingleLine(line) :\n                        line;\n                } else {\n                    return line;\n                }\n            };\n\n            return lines.map(line => replaceRefsSingleLine(line));\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Capitalizes the given lines depending on the given\n     * capitalize options.\n     *\n     * @param param0\n     */\n    private capitalizeLines({\n        lines,\n        resultAs,\n        capitalize,\n    }: {\n        lines: string[],\n        resultAs: \"ssml\" | \"text\",\n        capitalize: LexCapitalize,\n    }) {\n        const lc = `${this.lc}[${this.capitalizeLines.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: b0ec8263fd94c68ee53fdf61534c8322)`); }\n\n            const replaceAt = (s: string, i: number, replacement: string) => {\n                // todo: change substr to use substring\n                return s.substr(0, i) +\n                    replacement +\n                    s.substr(i + replacement.length);\n            };\n            const upperText = (line: string) => {\n                if (line === \"\") {\n                    return \"\";\n                }\n                // Thanks https://paulund.co.uk/capitalize-first-letter-string-javascript\n                return line.charAt(0).toUpperCase() + line.slice(1);\n            };\n            const upperSsml = (line: string) => {\n                if (line === \"\") {\n                    return \"\";\n                }\n                if (line.charAt(0) === \"<\") {\n                    let iFirstLetter = line.indexOf(\">\") + 1;\n                    return replaceAt(line, iFirstLetter, line[iFirstLetter].toUpperCase());\n                } else {\n                    return upperText(line);\n                }\n            };\n            const lowerText = (line: string) => {\n                if (line === \"\") {\n                    return \"\";\n                }\n                // Thanks https://paulund.co.uk/capitalize-first-letter-string-javascript\n                return line.charAt(0).toLowerCase() + line.slice(1);\n            };\n            const lowerSsml = (line: string) => {\n                if (line === \"\") {\n                    return \"\";\n                }\n                if (line.charAt(0) === \"<\") {\n                    let iFirstLetter = line.indexOf(\">\") + 1;\n                    return replaceAt(line, iFirstLetter, line[iFirstLetter].toLowerCase());\n                } else {\n                    return lowerText(line);\n                }\n            };\n            const firstLine = lines[0];\n            switch (capitalize) {\n                case LexCapitalize.upperfirst:\n                    lines[0] =\n                        resultAs === \"text\" ?\n                            upperText(firstLine) :\n                            upperSsml(firstLine);\n                    return lines;\n                case LexCapitalize.uppereach:\n                    return lines.map(l => {\n                        return resultAs === \"text\" ?\n                            upperText(l) :\n                            upperSsml(l);\n                    });\n                case LexCapitalize.lowerfirst:\n                    lines[0] =\n                        resultAs === \"text\" ?\n                            lowerText(firstLine) :\n                            lowerSsml(firstLine);\n                    return lines;\n                case LexCapitalize.lowereach:\n                    return lines.map(l => {\n                        return resultAs === \"text\" ?\n                            lowerText(l) :\n                            lowerSsml(l);\n                    });\n                case LexCapitalize.none:\n                    return lines;\n                default:\n                    throw new Error(`Unknown LexCapitalize: ${capitalize}`);\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Concatenates lines depending on given params.\n     *\n     * @param param0\n     */\n    private concatLines({\n        lines,\n        lineType,\n        lineConcat,\n        lineConcatDelim\n    }: {\n        lines: string[],\n        lineType: \"ssml\" | \"text\",\n        lineConcat: LexLineConcat,\n        lineConcatDelim: string,\n    }): string {\n        const lc = `${this.lc}[${this.concatLines.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 59e0a7b89457283751b376295b61bb22)`); }\n\n            const firstLine = lines[0];\n            // This used in both LexLineConcat.p and .n\n            const concatSsmlP = () => {\n                const pTag = \"<p>\";\n                if (firstLine.length < pTag.length ||\n                    firstLine.substring(0, pTag.length).toLowerCase() !== pTag) {\n                    return lines.map(l => `<p>${l}</p>`).join('');\n                } else {\n                    // First line starts with <p> so\n                    // we will simply concat all lines,\n                    // assuming the user has wrapped all lines.\n                    return lines.join('');\n                }\n            };\n            switch (lineConcat) {\n                case LexLineConcat.p:\n                    if (lineType === \"text\") {\n                        return lines.join(\"\\n\\n\");\n                    } else {\n                        return concatSsmlP();\n                    }\n                case LexLineConcat.s:\n                    if (lineType === \"text\") {\n                        // Append period if not in data.\n                        // e.g. Data may just be \"hello\" and we want to\n                        // make it a sentence by appending \".\"\n                        return lines.map(l => {\n                            let lastChar = l.substring(l.length - 1);\n                            return [\".\", \"!\", \"?\"].includes(lastChar) ?\n                                l :\n                                l + \".\";\n                        }).join(' ');\n                    } else {\n                        const sTag = \"<s>\";\n                        if (firstLine.length < sTag.length ||\n                            firstLine.substring(0, sTag.length).toLowerCase() !== sTag) {\n                            return lines.map(l => `<s>${l}</s>`).join('');\n                        } else {\n                            // First line starts with <s> so\n                            // we will simply concat all lines,\n                            // assuming the user has wrapped all lines.\n                            return lines.join('');\n                        }\n                    }\n                case LexLineConcat.n:\n                    if (lineType === \"text\") {\n                        return lines.join('\\n');\n                    } else {\n                        return concatSsmlP();\n                    }\n                case LexLineConcat.delim:\n                    return lines.join(lineConcatDelim);\n                default:\n                    throw new Error(`Unknown LexLineConcat: ${lineConcat} (E: e19f9c44217f4eb5999e2085d3f77b5c)`);\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Filters the given lexData per the language, specifier,\n     * and keywords.\n     *\n     * @param param0 Filter params\n     * @returns filtered datum array\n     */\n    private filterLexData({\n        lexData,\n        language,\n        specifier,\n        keywords, keywordMode,\n        props, propsMode,\n        fnDatumPredicate,\n    }: {\n        lexData: LexDatum<TProps>[],\n        language: LanguageCode,\n        specifier: string | undefined,\n        keywords: string[] | undefined,\n        keywordMode: KeywordMode,\n        props: PropsFilter<TProps> | undefined,\n        propsMode: PropsFilterMode,\n        fnDatumPredicate: LexDatumPredicate<TProps> | undefined,\n    }): LexDatum<TProps>[] {\n        const lc = `${this.lc}[${this.filterLexData.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 1091755e98f390954d296575d1096722)`); }\n            let result = lexData.concat(); // makes a copy\n            if (language) {\n                result = this.filterLanguage(result, language);\n            }\n            if (specifier) {\n                result = result.filter(d => d.specifier && d.specifier === specifier);\n            }\n            if (keywords && keywords.length > 0) {\n                // Datum must contain keywords that overlap with given\n                // keywords args.\n                keywords = keywords.map(kw => kw.toLocaleLowerCase())!;\n                switch (keywordMode) {\n                    case \"any\":\n                        result =\n                            result.filter(d => d.keywords &&\n                                d.keywords.some(kwDatum => keywords!\n                                    .map(kwArg => kwArg.toLocaleLowerCase())\n                                    .some(kwArg => kwDatum === kwArg)));\n                        break;\n                    case \"all\":\n                        result = result.filter(d => {\n                            let dKeywords = (d.keywords || [])\n                                .map(x => x.toLocaleLowerCase());\n                            return keywords!.every(kwArg => dKeywords.includes(kwArg));\n                        });\n                        break;\n                    case \"none\":\n                        result = result.filter(d => {\n                            let dKeywords = (d.keywords || [])\n                                .map(x => x.toLocaleLowerCase());\n                            return keywords!.every(kwArg => !dKeywords.includes(kwArg));\n                        });\n                        break;\n                    default:\n                        console.error(`${lc} Unknown keywordMode: ${keywordMode}`);\n                        break;\n                }\n            }\n            if (props) {\n                result = this.filterProps({ result, props, propsMode });\n            }\n            if (fnDatumPredicate) {\n                result = result.filter(x => fnDatumPredicate(x));\n            }\n            return result;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * executes the property filter on the given (intermediate) result.\n     */\n    private filterProps({\n        result,\n        props,\n        propsMode\n    }: {\n        result: LexDatum<TProps>[],\n        /**\n         * Filters either per prop or per the entire props object.\n         *\n         * Here are how they're defined atow. (see them for reference)\n         * PropsData = { [propName: string]: string; };\n         * PropsFilter<TProps> = FilterPerProp | FilterPerProps<TProps>;\n         * PropertyPredicate = (propName: string) => boolean;\n         * FilterPerProp = { [propName: string]: PropertyPredicate; };\n         * FilterPerProps<TProps> = (props: TProps) => boolean;\n         */\n        props: PropsFilter<TProps>,\n        propsMode: PropsFilterMode,\n    }): LexDatum<TProps>[] {\n        // not within a try...catch because used in a tight loop within another fn that catches it\n        if (propsMode === \"prop\") {\n            const propsFilter = props as FilterPerProp;\n            return result.filter(d => {\n                return Object.keys(propsFilter).every((propName: string) => {\n                    const propFn = propsFilter[propName];\n                    const dPropValue: any = !!d.props ? d.props[propName] as any : undefined;\n                    return propFn(dPropValue);\n                });\n            });\n        } else if (propsMode === \"props\") {\n            let propsFn = props as FilterPerProps<TProps>;\n            return result.filter(d => propsFn(d.props as TProps));\n        } else {\n            throw new Error(`Invalid propsMode: ${propsMode} (E: 216a926144d2436a900b81ffe0aa6174)`);\n        }\n    }\n\n    private filterLanguage(result: LexDatum<TProps>[], language: string): LexDatum<TProps>[] {\n        result = result.filter(d =>\n            // explicit language given\n            (d.language && d.language === language) ||\n            // default language is 2 letters and matches\n            (!d.language &&\n                this.defaultLanguage.length === 2 &&\n                language.startsWith(this.defaultLanguage)) ||\n            // default language is 4 letters and is equal\n            (!d.language && this.defaultLanguage === language));\n        return result;\n    }\n\n    /**\n     * Picks a randomesque datum from the given lexData, taking into\n     * account the weighting of each datum.\n     *\n     * @param lexData Filtered lexData from which to choose a random item, per the item's weighting\n     *\n     * @see LexDatum.weighting\n     */\n    private pickDatum(lexData: LexDatum<TProps>[]): LexDatum<TProps> | null {\n        const lc = `${this.lc}[${this.pickDatum.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: f95c8585a8274f78a1e724d6ab58ff22)`); }\n            if (!lexData) { throw new Error(`lexData required (E: cedb1fd9b67856c33b41c7dd4aab7c22)`); }\n            if (lexData.length === 0) {\n                return null;\n            } else if (lexData.length === 1) {\n                return lexData[0];\n            } else {\n                const totalWeight = lexData.reduce((agg, item) => {\n                    return agg + (item.weighting ? item.weighting : 1);\n                }, 0);\n                // normalized random number\n                const randomNumber = Math.random() * totalWeight;\n                let result: LexDatum<TProps> | null = null;\n                lexData.reduce((runningWeight, item) => {\n                    if (result) {\n                        // already got a result\n                        return -1;\n                    } else {\n                        runningWeight += (item.weighting ? item.weighting : 1);\n                        if (runningWeight >= randomNumber) { result = item; }\n                        return runningWeight;\n                    }\n                }, 0);\n                return result;\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n}\n\n/**\n * Contains a unit of speech, represented either by text, ssml, or both.\n * */\nexport interface OutputSpeech {\n    /**\n     * A string containing the type of output speech to render. Valid types are:\n     *   \"PlainText\": Indicates that the output speech is defined as plain text.\n     *   \"SSML\": Indicatesthat the output speech is text marked up with SSML.\n     */\n    type: OutputSpeechType;\n    /** A string containing the speech to render to the user. Use this when type is \"PlainText\" */\n    text?: string;\n    /** A string containing text marked up with SSML to render to the user. Use this when type is \"SSML\" */\n    ssml?: string;\n}\n\n/**\n * output speech is either text or ssml.\n */\nexport declare type OutputSpeechType = 'PlainText' | 'SSML';\nexport declare const OutputSpeechType: {\n    /**\n     * Indicates that the output speech is defined as plain text.\n     */\n    PlainText: OutputSpeechType;\n    /**\n     * Indicates that the output speech is text marked up with SSML.\n     */\n    SSML: OutputSpeechType;\n};\n\n/**\n * Builds an OutputSpeech object that contains both text and ssml.  The text is\n * convenient for showing information on cards, while building the ssml at the\n * same time.\n *\n * The OutputSpeech.type is always ssml.\n */\nexport class SpeechBuilder {\n    private lc: string = `[${SpeechBuilder.name}]`;\n\n    /**\n     * The builder accumulates speech bits and then composes these together when\n     * outputting.\n     */\n    private _bits: SpeechBit[];\n\n    constructor() {\n        const lc = `${this.lc}[ctor]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 38d63eb021d971a24d532aec75b60e22)`); }\n            this._bits = [];\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Static factory function for fluent-style speech building.\n     */\n    static with(): SpeechBuilder { return new SpeechBuilder(); }\n\n    /**\n     * Adds a bit of speech corresponding to bare (non-ssml/tagged) text.\n     *\n     * @param text text to add to the builder\n     */\n    text(text: string): SpeechBuilder {\n        let bit: SpeechBit = {\n            type: \"text\",\n            value: text + \"\"\n        };\n        this._bits.push(bit);\n        return this;\n    }\n    /**\n     * Adds a bit of speech corresponding to existing ssml.\n     *\n     * NOTE: This ssml should **NOT** contain a `<speak>` tag, as this\n     * is not automatically stripped. Also, if you choose\n     * `newParagraph`, ssml should **NOT** contain any hard-coded <p>\n     * tags\n     *\n     * @param ssml ssml to add to the builder. See NOTE in function description.\n     * @param newParagraph if true, wraps ssml in <p> tags. See NOTE in function description.\n     */\n    ssml(ssml: string, newParagraph: boolean = false): SpeechBuilder {\n        const bit = {\n            type: SpeechBitType.ssml,\n            value: newParagraph ? `<p>${ssml}</p>` : ssml\n        };\n        this._bits.push(bit);\n        return this;\n    }\n    /**\n     * Adds a pause (<break> tag) in the speech builder.\n     * Equivalent to `<break='${seconds}s'/>` ATOW.\n     *\n     * @param seconds amount of time to pause.\n     */\n    pause(seconds: number): SpeechBuilder {\n        const bit = {\n            type: SpeechBitType.break,\n            value: seconds\n        };\n        this._bits.push(bit);\n        return this;\n    }\n\n    /**\n     * Syntactic sugar for adding text of '\\n'\n     */\n    newLine(): SpeechBuilder {\n        const bit: SpeechBit = {\n            type: 'text',\n            value: '\\n'\n        };\n        this._bits.push(bit);\n        return this;\n    }\n\n    /**\n     * Syntactic sugar for adding text of '\\n\\n'\n     */\n    newParagraph(): SpeechBuilder {\n        const bit: SpeechBit = {\n            type: 'text',\n            value: '\\n\\n'\n        };\n        this._bits.push(bit);\n        return this;\n    }\n\n    /**\n     * Takes text and/or ssml from existing `OutputSpeech`\n     * object and adds it to the builder.\n     *\n     * For example, say you already have an outputSpeech and you just\n     * want to add an intro text to it. You would create the builder,\n     * add the intro text via `text` function and then call this\n     * function with your existing outputSpeech.\n     *\n     * @example `let outputWithIntro = SpeechBuilder.with().text('Some intro text').existing(prevOutputSpeech).outputSpeech();`\n     * @param outputSpeech existing `OutputSpeech` to weave into the builder.\n     */\n    existing(outputSpeech: OutputSpeech): SpeechBuilder {\n        const bit: SpeechBit = {\n            type: SpeechBitType.existingOutputSpeech,\n            value: outputSpeech\n        };\n        this._bits.push(bit);\n        return this;\n    }\n    /**\n     * Creates an `OutputSpeech` from the builder's state.\n     */\n    outputSpeech({\n        outputType = 'PlainText',\n    }: {\n        /**\n         * Somewhat vestigial, originally for use with Alexa skills (I had\n         * created ask-gib and this builder before Amazon's sdk was created.)\n         */\n        outputType?: OutputSpeechType,\n    }): OutputSpeech {\n        const lc = `${this.lc}[${this.outputSpeech.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 3820fa4816d7ca999489b45fff5e2622)`); }\n\n            outputType = outputType || 'PlainText';\n\n            let text = \"\", ssml = \"\";\n            if (logalot) { console.log(`${lc} about to do bits...`); }\n            if (logalot) { console.log(`${lc} bits: ${JSON.stringify(this._bits)}`); }\n            this._bits.forEach(bit => {\n                if (logalot) { console.log(`${lc} ssml: ${ssml}`); }\n                if (text || ssml) {\n                    text = text + \" \";\n                    ssml = ssml + \" \";\n                }\n                if (logalot) { console.log(`${lc} bit: ${JSON.stringify(bit)}`); }\n                switch (bit.type) {\n                    case \"text\":\n                        if (logalot) { console.log(`${lc} text in case`); }\n                        text += bit.value;\n                        ssml += bit.value;\n                        break;\n                    case \"ssml\":\n                        if (logalot) { console.log(`${lc} ssml in case`); }\n                        // do these in two steps to fully strip ssml.\n                        text += bit.value;\n                        text = Ssml.stripSsml(text);\n                        ssml += bit.value;\n                        break;\n                    case \"break\":\n                        if (logalot) { console.log(`${lc} break in case`); }\n                        // ridic edge case, if pause before any text/ssml.\n                        if (ssml === \" \") { ssml = \"\"; }\n                        // text doesn't change\n                        ssml += `<break time='${bit.value}s'/>`;\n                        break;\n                    case \"existingOutputSpeech\":\n                        if (logalot) { console.log(`${lc} existing in case`); }\n                        const existing = bit.value as OutputSpeech;\n                        if (existing.text && existing.ssml) {\n                            if (logalot) { console.log(`${lc} existing text and ssml`); }\n                            text += existing.text;\n                            ssml += Ssml.unwrapSsmlSpeak(existing.ssml);\n                        } else if (existing.text) {\n                            if (logalot) { console.log(`${lc} existing text only`); }\n                            text += existing.text;\n                            ssml += text;\n                        } else if (existing.ssml) {\n                            if (logalot) { console.log(`${lc} existing ssml only`); }\n                            let unwrapped = Ssml.unwrapSsmlSpeak(existing.ssml);\n                            // do these in two steps to fully strip ssml.\n                            text += unwrapped;\n                            text = Ssml.stripSsml(text);\n                            ssml += unwrapped;\n                        } else { // neither existing ssml nor text?\n                            throw new Error(\"both existing.ssml and existing.text are falsy? (E: 089138a6ce8e45038028828515d9cd0c)\")\n                        }\n                        break;\n                    case \"phoneme\":\n                        throw new Error(\"phoneme case not implemented\");\n                    // break\n                    default:\n                        throw new Error(`Unknown bit.type: ${bit.type}`);\n                }\n            });\n            if (logalot) {\n                console.log(`${lc} text: ${JSON.stringify(text)}`);\n                console.log(`${lc} ssml: ${JSON.stringify(ssml)}`);\n            }\n            const output: OutputSpeech = {\n                type: outputType,\n                text: text,\n                ssml: Ssml.wrapSsmlSpeak([ssml], /*addParaTags*/ false)\n            };\n            // console.log(`${lc} output: ${JSON.stringify(output)}`);\n            return output;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n}\nexport declare type SpeechBitType = \"text\" | \"ssml\" | \"break\" | \"phoneme\" | \"existingOutputSpeech\";\nexport declare const SpeechBitType: {\n    text: SpeechBitType;\n    ssml: SpeechBitType;\n    break: SpeechBitType;\n    phoneme: SpeechBitType;\n    existingOutputSpeech: SpeechBitType;\n};\n/**\n * OutputSpeech objects are basically just arrays of these.\n */\nexport interface SpeechBit {\n    type: SpeechBitType;\n    value: string | number | OutputSpeech;\n}\n", "import { Lex, LexData, LexDatum, PropsData, } from '@ibgib/helper-gib/dist/helpers/lex-helper.mjs';\nimport { Ssml } from '@ibgib/helper-gib/dist/helpers/ssml-helper.mjs';\nimport { clone } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { Gib, IbGibAddr, TjpIbGibAddr, TransformResult } from '@ibgib/ts-gib/dist/types.mjs';\nimport { IbGibData_V1, IbGibRel8ns_V1, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/index.mjs';\n\nimport {\n    WitnessData_V1, WitnessResultData, WitnessResultRel8ns, WitnessResultIbGib,\n} from '../witness-types.mjs';\nimport { CommentIbGib_V1 } from '../../common/comment/comment-types.mjs';\nimport { ROBBOT_TAG_TJP_ADDRS_REL8N_NAME } from './robbot-constants.mjs';\nimport { IbGibRobbotAny } from './robbot-base-v1.mjs';\nimport { WitnessWithContextData_V1, WitnessWithContextRel8ns_V1 } from '../witness-with-context/witness-with-context-types.mjs';\nimport { WitnessCmdData, WitnessCmdRel8ns, WitnessCmdIbGib, } from '../witness-cmd/witness-cmd-types.mjs';\n\n\nexport type RobbotTransparency = 'transparent' | 'translucent' | 'opaque';\n\nexport interface RobbotData_V1 extends WitnessWithContextData_V1 {\n\n    /**\n     * Name of a Robbot instance...after all, Robbie was only the first Robbot.\n     */\n    name: string;\n\n    /**\n     * Redeclared over {@link WitnessData_V1.uuid} making it a required field.\n     */\n    uuid: string;\n\n    /**\n     * For simpler robbots (i.e. early implementations), I'm not sure what this\n     * will entail. Ideally the function dependency graph is public but right\n     * now we're living with witness functionality \"off-chain\" (\"on-chain\"\n     * stored in git version control).\n     *\n     * I think atm this will mean that any weighting will be public. If a robbot\n     * has any randomness in its decision making, then this should be\n     * translucent at least.\n     *\n     * Of course, even in the future when there are more sovereign \"A\"Is,\n     * transparency doesn't mean you understand where he/she/it is coming from -\n     * only that the raw data is available to see.\n     */\n    // reasoningTransparency: RobbotTransparency;\n\n    /**\n     * Transparency of timing of planned ibgibs to be presented to the user in a\n     * context.\n     *\n     * For example, when the robbot is asked to process an ibgib context, it\n     * must decide when to add which ibgibs to it's output context.\n     */\n    // schedulingTransparency: RobbotTransparency;\n\n    /**\n     * Minimum amount of time between outputs allowed by the robbot.\n     */\n    // minSecondsBetweenPosts: number;\n\n    /**\n     * Robbots work with scheduling and executing ibgib processing. But\n     * it is often (always?) advantageous to give a certain amount of leeway\n     * within the algorithms for making scheduling decisions. This is a\n     * maximum time variance percentage per decision.\n     *\n     * So if there is a rigid schedule of every N days, then we allow that\n     * it may indeed schedule the ibgib N +- (N * variance/100). If N is 50,\n     * and max variance is 10, then this may schedule the output at\n     * 50 plus or minus up to 5; consequently a range from 45-55.\n     */\n    // maxTimeVariancePercentage: number;\n\n    /**\n     * If true, then this robbot will be started upon app startup, and perhaps\n     * in a background service in the future.\n     *\n     * if false, the robbot will schedule and execute a single \"round\" only when\n     * prompted by a user.\n     */\n    // active: boolean;\n    // for now, all robbot output will be passive, i.e., when you ask the robbot\n    // within a context using the bottom action bar.\n\n    /**\n     * Some ibgibs work at the date (day) level of granularity, while others\n     * work down to the time.\n     */\n    // scheduleGranularity: 'date' | 'time';\n\n    /**\n     * If provided, this will be prepended to any comments made by the robbot,\n     * as well as the output subcontext if {@link outputMode} is\n     * {@link RobbotOutputMode.subcontext}.\n     */\n    outputPrefix?: string;\n\n    /**\n     * If provided, this will be appended to any comments made by the robbot,\n     * as well as the output subcontext if {@link outputMode} is\n     * {@link RobbotOutputMode.subcontext}.\n     */\n    outputSuffix?: string;\n\n    /**\n     * There are multiple possibilities for where to output:\n     *\n     * 1. Inside the input context\n     * 2. In a different subcontext ibgib\n     * 3. In the robbot's ibgib (todo later)\n     * 4. Tagged but not \"inside\" an ibgib (not planned atm).\n     *\n     * Also, it is possible to tag all outputs regardless of where the ibgibs\n     * are placed originally. @see {@link tagOutput}\n     *\n     * ## thoughts\n     *\n     * Since the driving use case is to create drills, it would seem that inside\n     * a single grouping ibgib within the output context makes the most sense.\n     */\n    // outputMode?: RobbotOutputMode;\n\n    // /**\n    //  * If true, rel8s output context depending on {@link outputMode} to the latest\n    //  * tag(s) whose tjpAddr(s) are given in {@link RobbotRel8ns_V1}\n    //  * {@link ROBBOT_TAG_TJP_ADDRS_REL8N_NAME}.\n    //  */\n    // tagOutput?: boolean;\n\n\n    /**\n     * When relating to an ibGib, this is the default rel8n name.\n     *\n     * @see `RobbotBase_V1.rel8To`\n     */\n    defaultRel8nName?: string;\n    /**\n     * list of all rel8n names, e.g. {@link defaultRel8nName},\n     * that this robbot uses for \"my ibgibs\".\n     */\n    allRel8nNames?: string[];\n    /**\n     * escape sequence when requesting something from a robbot.\n     *\n     * So if a comment starts with this, then it's someone asking a robbot to do\n     * something.\n     */\n    requestEscapeString?: string;\n\n}\n\n/**\n * default value for a robbot request escape string (that string to signify\n * a comment is a request of a robbot)\n */\nexport const DEFAULT_ROBBOT_REQUEST_ESCAPE_STRING = '?';\nexport const DEFAULT_ROBBOT_REQUEST_MAX_LENGTH = 100;\n\n\n// /**\n//  * @see {@link RobbotData_V1.outputMode}\n//  */\n// export type RobbotOutputMode = 'context' | 'subcontext' | 'ask';\n// export const RobbotOutputMode = {\n//     /**\n//      * spread out within the target context\n//      */\n//     context: 'context' as RobbotOutputMode,\n//     /**\n//      * creates a single comment ibgib and outputs within that\n//      */\n//     subcontext: 'subcontext' as RobbotOutputMode,\n// }\n// export const VALID_ROBBOT_OUTPUT_MODES = Object.values(RobbotOutputMode);\n\nexport interface RobbotRel8ns_V1 extends WitnessWithContextRel8ns_V1 {\n    [ROBBOT_TAG_TJP_ADDRS_REL8N_NAME]?: TjpIbGibAddr[];\n}\n\n/**\n * A robbot's primary function when assigned to an ibgib is to analyze a context\n * ibgib as its input, and output ibgibs into the same or another context.\n *\n * This is quite similar to existing ideas of microservices, but with a few key\n * differences:\n *\n * 1. Robbots exist within the limited domain of ibgib transforms, i.e., `fork`,\n *    `mut8` & `rel8` transforms.\n * 2. Robbots themselves live \"on-chain\" alongside the data with which they\n *    interact.\n */\nexport interface RobbotIbGib_V1 extends IbGib_V1<RobbotData_V1, RobbotRel8ns_V1> {\n}\n\n\n\n/**\n * Cmds for interacting with ibgib spaces.\n *\n * Not all of these will be implemented for every space.\n *\n * ## todo\n *\n * change these commands to better structure, e.g., verb/do/mod, can/get/addrs\n * */\nexport type RobbotCmd =\n    'ib' | 'gib' | 'ibgib' | 'activate' | 'deactivate';\n/** Cmds for interacting with ibgib spaces. */\nexport const RobbotCmd = {\n    /**\n     * it's more like a grunt that is intepreted by context from the robbot.\n     *\n     * my initial use of this will be to add an ibgib to a robbot's\n     * awareness. (input)\n     */\n    ib: 'ib' as RobbotCmd,\n    /**\n     * it's more like a grunt that is intepreted by context from the robbot.\n     *\n     * my initial use of this will be to indicate to a robbot to add to a\n     * conversation. (output)\n     */\n    gib: 'gib' as RobbotCmd,\n    /**\n     * third placeholder command.\n     *\n     * I imagine this will be like \"what's up\", but who knows.\n     */\n    ibgib: 'ibgib' as RobbotCmd,\n    /**\n     * power on\n     */\n    activate: 'activate' as RobbotCmd,\n    /** power off */\n    deactivate: 'deactivate' as RobbotCmd,\n}\n\n/**\n * Flags to affect the command's interpretation.\n */\nexport type RobbotCmdModifier =\n    'ib' | 'gib' | 'ibgib';\n/**\n * Flags to affect the command's interpretation.\n */\nexport const RobbotCmdModifier = {\n    /**\n     * hmm...\n     */\n    ib: 'ib' as RobbotCmdModifier,\n    /**\n     * hmm...\n     */\n    gib: 'gib' as RobbotCmdModifier,\n    /**\n     * hmm...\n     */\n    ibgib: 'ibgib' as RobbotCmdModifier,\n}\n\n/** Information for interacting with spaces. */\nexport interface RobbotCmdData\n    extends WitnessCmdData<RobbotCmd, RobbotCmdModifier> {\n}\n\nexport interface RobbotCmdRel8ns extends WitnessCmdRel8ns {\n}\n\n/**\n * Shape of options ibgib if used for a robbot.\n *\n * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface RobbotCmdIbGib<\n    TIbGib extends IbGib_V1 = IbGib_V1,\n    TCmdData extends RobbotCmdData = RobbotCmdData,\n    TCmdRel8ns extends RobbotCmdRel8ns = RobbotCmdRel8ns,\n> extends WitnessCmdIbGib<TIbGib, RobbotCmd, RobbotCmdModifier, TCmdData, TCmdRel8ns> {\n}\n\n/**\n * Optional shape of result data to robbot interactions.\n *\n * This is in addition of course to {@link WitnessResultData}.\n *\n * ## notes\n *\n * * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface RobbotResultData extends WitnessResultData {\n}\n\n/**\n * Marker interface rel8ns atm...\n *\n * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface RobbotResultRel8ns extends WitnessResultRel8ns { }\n\n/**\n * Shape of result ibgib if used for a robbot.\n *\n * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface RobbotResultIbGib<\n    TIbGib extends IbGib_V1,\n    TResultData extends RobbotResultData,\n    TResultRel8ns extends RobbotResultRel8ns\n>\n    extends WitnessResultIbGib<TIbGib, TResultData, TResultRel8ns> {\n}\n\n/**\n * When a robbot creates a comment on a context ibgib, he/she also relates it to\n * itself via this rel8nName.\n *\n * @example robbot.rel8ns.my_comment = 'comment myawesomeopinion wordyrobbot123^ABC'\n *\n * ## notes\n *\n * * \"my\" prefix is used to differentiate between the robbot's comments and comments\n *   on the robbot itself.\n */\nexport const ROBBOT_MY_COMMENTS_REL8N_NAME = 'my_comment';\n/**\n * When a robbot participates in a conversation, that context is related via\n * this rel8n name.\n * @example robbot.rel8ns.context = 'comment someconvo^ABC'\n */\nexport const ROBBOT_CONTEXT_REL8N_NAME = 'context';\n/**\n * Used to rel8 session ibgibs to robbots.\n * @example robbot.rel8ns.session = ['session 123^ABC'];\n */\nexport const ROBBOT_SESSION_REL8N_NAME = 'session';\n/**\n * Used to rel8 interaction to sessions,\n * @example session.rel8ns.interaction = ['interaction 123^ABC'];\n */\nexport const ROBBOT_INTERACTION_REL8N_NAME = 'interaction';\n\nexport const ROBBOT_ATOM = \"robbot\";\nexport const ROBBOT_SESSION_ATOM = 'robbot_session';\nexport const ROBBOT_ANALYSIS_ATOM = 'robbot_analysis';\nexport const ROBBOT_INTERACTION_ATOM = 'robbot_interaction';\n\n\n/**\n * This is stimulus that is coming over the Context that a robbot is being\n * stimulated with.\n *\n * This is different than stimulus that the robbot provides for a given ibgib.\n */\nexport interface StimulusForRobbot {\n    /**\n     * The actual ibgib that is the stimulus.\n     *\n     * If falsy, `isClick` should be true.\n     */\n    ibGib?: IbGib_V1;\n    /**\n     * should be true if the user has typed in a request and added the\n     * comment to the context.\n     */\n    isRequest?: boolean;\n    /**\n     * The stimulus was generated from a click on a button, as opposed to a\n     * comment typed in or a picture/link/comment added/imported in a context.\n     *\n     * Should be true if `ibGib` is falsy.\n     */\n    isClick?: boolean;\n}\n\nexport type RobbotInteractionType = 'greeting' | 'stimulation' | 'farewell' | 'info' | 'help';\nexport const RobbotInteractionType = {\n    /**\n     * opening statement of a robbot\n     */\n    greeting: 'greeting' as RobbotInteractionType,\n    /**\n     * stimulates a certain ibgib.\n     */\n    stimulation: 'stimulation' as RobbotInteractionType,\n    /**\n     * closing statements of a robbot\n     */\n    farewell: 'farewell' as RobbotInteractionType,\n    /**\n     * small nudges of info, including possibly repeating previous statement.\n     */\n    info: 'info' as RobbotInteractionType,\n    /**\n     * providing info about context to aid the user in their options.\n     */\n    help: 'help' as RobbotInteractionType,\n}\n\n\nexport const DEFAULT_INTERACTION_SUBJECTTJPGIBS_DELIM = '_';\nexport const UNDEFINED_INTERACTION_SUBJECTTJPGIBS_STRING = 'undefined';\n\nexport interface RobbotInteractionIbInfo {\n    atom: string,\n    type: string,\n    timestampInTicks: string,\n    subjectTjpGibs?: Gib[],\n    addlDetailsText?: string,\n}\n\nexport interface RobbotInteractionData_V1 extends IbGibData_V1 {\n    timestamp: string;\n    /**\n     * type of this interaction. for now, this is strongly typed, but\n     * later I should add a catchall `| string` type to allow for\n     * expansion.\n     */\n    type: RobbotInteractionType;\n    /**\n     * The tjpGib of the interaction's context ibgib.\n     */\n    contextTjpGib: Gib;\n    /**\n     * When an interaction pertains to particular timelines, e.g. stimulating\n     * one or more ibgibs, those tjp gibs should be listed here.\n     */\n    subjectTjpGibs?: Gib[];\n    /**\n     * Produced comment text from the interaction. This should be the\n     * content of text that the robbot outputs to the context.\n     */\n    commentText?: string;\n    /**\n     * should be an interfaced data object that represents the details of the\n     * interaction, e.g. if a stimulation, then here is the simulation interface data.\n     *\n     * ## notes\n     *\n     * to create another generic interface here would be too unwieldy. (already may be!)\n     */\n    details?: any;\n    /**\n     * If interaction is associated with a session, here is the session tjp addr.\n     */\n    '@sessionTjp'?: TjpIbGibAddr;\n    /**\n     * If interaction is associated with a session, here is the session id.\n     */\n    sessionId?: string;\n    /**\n     * Flag to indicate if the interaction is expecting a response, like a\n     * question to be answered by the user.\n     */\n    expectingResponse?: boolean;\n}\nexport interface RobbotInteractionRel8ns_V1 extends IbGibRel8ns_V1 {\n}\nexport interface RobbotInteractionIbGib_V1\n    extends IbGib_V1<RobbotInteractionData_V1, RobbotInteractionRel8ns_V1> { }\n\nexport interface RobbotSessionData_V1 extends IbGibData_V1 {\n    timestamp: string;\n    /**\n     * Soft link to the context address where the session takes place.\n     */\n    '@context': IbGibAddr;\n    /**\n     * Soft link to the context's tjp address where the session takes place.\n     */\n    '@contextTjp': IbGibAddr;\n}\nexport interface RobbotSessionRel8ns_V1 extends IbGibRel8ns_V1 {\n    interaction?: IbGibAddr[];\n}\nexport interface RobbotSessionIbGib_V1 extends IbGib_V1<RobbotSessionData_V1, RobbotSessionRel8ns_V1> { }\n\n\n/**\n * These are used for raw words/phrases that compose larger, more complex\n * semantic ideas that use SemanticId.\n *\n * Because these are used in composition of lex data, they are not prefixed\n * with something like \"atomic_\", e.g. \"atomic_hi\".\n */\nexport type AtomicId =\n    'hi' | 'welcome' | 'bye' |\n    'yes' | 'no' |\n    'learn' |\n    'wtg';\nexport const AtomicId = {\n    hi: 'hi' as AtomicId,\n    welcome: 'welcome' as AtomicId,\n    bye: 'bye' as AtomicId,\n    yes: 'yes' as AtomicId,\n    no: 'no' as AtomicId,\n    learn: 'learn' as AtomicId,\n    wtg: 'wtg' as AtomicId,\n}\n\n/**\n * These are used for specific lex commands/intents/whatevers. Synonyms and\n * equivalency phrases ultimately get resolved to these.\n *\n * These are complex concepts, as opposed to the smaller atomic words/phrases, that\n * a robbot will use when interacting with users.\n *\n * ## example\n *\n * A robbot may say in a semantic greeting (SemanticId.hello) that incorporates\n * a lot of context-specific text. However, these individual greetings will\n * most likely include the usage of individual phrases like 'hi' or 'good day'.\n * These are small, raw \"atomic\" lexical atoms.\n */\nexport type SemanticId =\n    'semantic_help' |\n    'semantic_hello' | 'semantic_bye' |\n    'semantic_yes' | 'semantic_no' | 'semantic_cancel' |\n    'semantic_skip' | 'semantic_forget' | 'semantic_next' |\n    'semantic_please' |\n    'semantic_in_progress' |\n    'semantic_list' |\n    'semantic_request' |\n    'semantic_count' |\n    'semantic_options' |\n    'semantic_ready' |\n    'semantic_stop' |\n    'semantic_result' |\n    'semantic_unknown' | 'semantic_default' |\n    string; // have to do this for inheritance?\n/**\n * enum constant for use with {@link SemanticInfo}.\n */\nexport const SemanticId = {\n    help: 'semantic_help' as SemanticId,\n    hello: 'semantic_hello' as SemanticId,\n    bye: 'semantic_bye' as SemanticId,\n    yes: 'semantic_yes' as SemanticId,\n    no: 'semantic_no' as SemanticId,\n    cancel: 'semantic_cancel' as SemanticId,\n    skip: 'semantic_skip' as SemanticId,\n    forget: 'semantic_forget' as SemanticId,\n    next: 'semantic_next' as SemanticId,\n    please: 'semantic_please' as SemanticId,\n    in_progress: 'semantic_in_progress' as SemanticId,\n    list: 'semantic_list' as SemanticId,\n    request: 'semantic_request' as SemanticId,\n    count: 'semantic_count' as SemanticId,\n    options: 'semantic_options' as SemanticId,\n    ready: 'semantic_ready' as SemanticId,\n    stop: 'semantic_stop' as SemanticId,\n    result: 'semantic_result' as SemanticId,\n    unknown: 'semantic_unknown' as SemanticId,\n    default: 'semantic_default' as SemanticId,\n};\n\n/**\n * Info related to a semantic interpretation of one user (or ai/other) when\n * communicating to another witness.\n */\nexport interface SemanticInfo {\n    /**\n     * Id if already determined by runtime code.\n     */\n    semanticId?: SemanticId;\n    /**\n     * request (comment) ibgib if the semantic meaning maps to a request.\n     */\n    request?: CommentIbGib_V1;\n    /**\n     * placeholder per use case of another ibgib.\n     */\n    other?: IbGib_V1;\n    /**\n     * true if the semantic meaning is deemed a continuation of a previous\n     * semantic statement.\n     */\n    isContinuation?: boolean;\n}\n\nexport interface SemanticHandlerResult {\n    interaction: RobbotInteractionIbGib_V1 | null;\n    /**\n     * Should be set to true if the interaction is aborted (i.e. we're ignoring\n     * some stimulus). Like if we're expecting a response, but some other ibgib\n     * is given (maybe some users/other robbots are talking and it doesn't\n     * pertain to us).\n     */\n    ignored?: boolean;\n    /**\n     * If the handler is expecting a response (however the handler may interpret that response),\n     *\n     */\n    // responseSubject?: ReplaySubject<IbGib_V1 | null>;\n    // onResponse?: (response: IbGib_V1|null) => Promise<void>;\n}\nexport interface SemanticHandler {\n    /**\n     * This should be a unique id for this handler.\n     */\n    handlerId: string;\n    /**\n     * The semanticId that this handler is associated with.\n     */\n    semanticId: SemanticId;\n    /**\n     * If truthy, the robbot should execute this filter before\n     * attempting to execute this handler's {@link fnExec}\n     */\n    fnCanExec: (info: SemanticInfo) => Promise<boolean>;\n    /**\n     * Actual function of handler that gets executed if context is\n     * correct ({@link fnCanHandle} is true).\n     */\n    fnExec: (info: SemanticInfo) => Promise<SemanticHandlerResult>;\n    /**\n     * If the user cancels the response and this is truthy, this is called.\n     */\n    fnCancelResponse?: () => Promise<void>;\n    // handleSubject$: ReplaySubject<SemanticInfo>;\n    // handleResult$: ReplaySubject<SemanticHandlerResult>;\n}\n\nexport interface RobbotPropsData<TSemanticId extends SemanticId = SemanticId> extends PropsData {\n    /**\n     * This datum expects these template vars.\n     *\n     * This is not strictly necessary, but is used for documentation/aid to the\n     * caller on providing stuff for the datum for what is expected.\n     */\n    templateVars?: string;\n    /**\n     * If assigned, then this lex datum is a semantic entry, and this is the corresponding\n     * semantic id.\n     */\n    semanticId?: TSemanticId;\n    atomicId?: AtomicId;\n    /**\n     * Only use this lex datum if YES there is an active session in progress.\n     */\n    onlyInSession?: boolean;\n    /**\n     * Only use this lex datum if there is NOT an active session in progress.\n     */\n    onlyNotInSession?: boolean;\n    /**\n     * The robbot hasn't seen anything so has no knowledge/has nothing to work\n     * on.\n     */\n    blankSlate?: boolean;\n    /**\n     * Just starting a new session, i.e. no prev interactions exist.\n     */\n    freshStart?: boolean;\n    /**\n     * Flag to indicate if the lex datum corresponds to a user request.\n     */\n    isRequest?: boolean;\n}\n\nexport function toLexDatums_Semantics(semanticId: SemanticId, texts: string[]): LexDatum<RobbotPropsData>[] {\n    return texts.flatMap(t => {\n        return {\n            texts: [t],\n            language: 'en-US',\n            props: { semanticId },\n        } as LexDatum<RobbotPropsData>;\n    });\n}\nexport function toLexDatums_Atomics(atomicId: AtomicId, texts: string[]): LexDatum<RobbotPropsData>[] {\n    return texts.flatMap(t => {\n        return {\n            texts: [t],\n            language: 'en-US',\n            props: { atomicId },\n        } as LexDatum<RobbotPropsData>;\n    });\n}\n\nexport const DEFAULT_HUMAN_LEX_DATA_ENGLISH_SEMANTICS: LexData<RobbotPropsData> = {\n    [SemanticId.help]: [\n        ...toLexDatums_Semantics(SemanticId.help, [\n            'h', 'help', 'help me',\n        ]),\n    ],\n    [SemanticId.yes]: [\n        ...toLexDatums_Semantics(SemanticId.yes, [\n            'yes', 'y', 'yeah', 'yea', 'aye', 'yup', 'yep', 'sure', 'ok',\n            'sounds good', 'go for it', 'yes please', 'yes thanks', 'ok thanks',\n            'uh huh', 'god yes', 'affirmative', 'ten four', '10-4', 'roger',\n        ]),\n    ],\n    [SemanticId.no]: [\n        ...toLexDatums_Semantics(SemanticId.no, [\n            'no', 'n', 'nah', 'nay', 'nope', 'uh uh', 'no thanks', 'ick', 'nuh uh',\n            'god no', 'no way', 'not at all', 'negative', 'that\\'s a negative', 'nein',\n        ])\n    ],\n    [SemanticId.cancel]: [\n        ...toLexDatums_Semantics(SemanticId.cancel, [\n            'cancel', 'nm', 'nevermind', 'cancel that', 'don\\'t worry about it'\n        ])\n    ],\n    [SemanticId.skip]: [\n        ...toLexDatums_Semantics(SemanticId.skip, [\n            'skip', 'sk',\n        ])\n    ],\n    [SemanticId.forget]: [\n        ...toLexDatums_Semantics(SemanticId.forget, [\n            'forget', 'forget this', 'forget this one',\n        ])\n    ],\n    [SemanticId.next]: [\n        ...toLexDatums_Semantics(SemanticId.next, [\n            'next', // 'next $(please)' /* need to get this kind of thing working */\n        ])\n    ],\n    [SemanticId.bye]: [\n        ...toLexDatums_Semantics(SemanticId.bye, [\n            'bye', 'bye bye', 'see you later', 'see you',\n        ])\n    ],\n    [SemanticId.unknown]: [\n        ...toLexDatums_Semantics(SemanticId.unknown, [\n            'are you mocking me, human?', 'mmhmm...', 'i see...', 'does not compute...', 'indeed'\n        ])\n    ],\n};\nexport const DEFAULT_HUMAN_LEX_DATA_ENGLISH_ATOMICS: LexData<RobbotPropsData> = {\n    [AtomicId.hi]: [\n        ...toLexDatums_Atomics(AtomicId.hi, [\n            'hi', 'howdy', 'hello', 'greetings', 'good day', 'hello there', 'good day to you', 'yo',\n        ]),\n    ],\n    [AtomicId.welcome]: [\n        ...toLexDatums_Atomics(AtomicId.welcome, [\n            'welcome',\n        ]),\n    ],\n    [AtomicId.yes]: [\n        ...toLexDatums_Atomics(AtomicId.yes, [\n            'yes', 'y', 'yeah', 'yea', 'aye', 'yup', 'yep', 'sure', 'ok',\n            'sounds good', 'go for it', 'yes please', 'yes thanks', 'ok thanks',\n            'uh huh', 'god yes', 'affirmative', 'ten four', '10-4', 'roger',\n        ]),\n    ],\n    [AtomicId.no]: [\n        ...toLexDatums_Atomics(AtomicId.no, [\n            'no', 'n', 'nope', 'no thanks', 'no thank you',\n        ]),\n    ],\n    [AtomicId.bye]: [\n        ...toLexDatums_Atomics(AtomicId.bye, [\n            'bye', 'bye bye', 'adios', 'ciao', 'later',\n        ]),\n    ],\n    [AtomicId.learn]: [\n        ...toLexDatums_Atomics(AtomicId.learn, [\n            'learn', 'study', 'review',\n        ]),\n    ],\n    [AtomicId.wtg]: [\n        ...toLexDatums_Atomics(AtomicId.wtg, [\n            'wtg', 'nice', 'not bad', 'pretty good', 'good job',\n        ]),\n    ],\n}\nexport const DEFAULT_HUMAN_LEX_DATA_ENGLISH: LexData<RobbotPropsData> = {\n    ...DEFAULT_HUMAN_LEX_DATA_ENGLISH_SEMANTICS,\n    ...DEFAULT_HUMAN_LEX_DATA_ENGLISH_ATOMICS,\n}\nexport const DEFAULT_HUMAN_LEX_DATA: LexData<RobbotPropsData> = {\n    ...clone(DEFAULT_HUMAN_LEX_DATA_ENGLISH),\n};\n\nexport const DEFAULT_USER_LEX_DATA: LexData<RobbotPropsData> = {\n    ...clone(DEFAULT_HUMAN_LEX_DATA),\n}\n\n/**\n * This lex is to be used for parsing user responses.\n *\n * Also, you can use this in the robbot's responses, if you initialize the\n * robbot's lex to include this. This way, the robbot speaks as he/she expects\n * to be spoken to.\n *\n * So when a user says 'yes', we can interpret it via a lookup in the lex data.\n * we will find the id filter via keywords.\n */\nexport const DEFAULT_USER_LEX = new Lex<RobbotPropsData>(DEFAULT_USER_LEX_DATA, {\n    requestLanguage: \"en-US\", defaultLanguage: \"en-US\",\n    defaultCapitalize: \"none\",\n    defaultLineConcat: \"delim\", defaultDelim: \"\\n\\n\",\n    defaultKeywordMode: \"any\", defaultPropsMode: \"prop\",\n});\n\n/**\n * default phrases for the robbot to use when chatting.\n */\nexport const DEFAULT_ROBBOT_LEX_DATA: LexData<RobbotPropsData> = {\n    ...clone(DEFAULT_HUMAN_LEX_DATA),\n};\n// adjust for robbot-ness a bit\nDEFAULT_ROBBOT_LEX_DATA[SemanticId.bye].push(\n    {\n        texts: ['EOL',],\n        ssmls: [Ssml.sub('EOL', 'end of line'),],\n        language: 'en-US',\n        props: { semanticId: SemanticId.bye, },\n        weighting: 100,\n    }\n)\nDEFAULT_ROBBOT_LEX_DATA[SemanticId.unknown] = [\n    ...toLexDatums_Semantics(SemanticId.unknown, [\n        'i\\'m not quite sure what you mean', 'does not compute',\n    ])\n];\n\nexport type RobbotPromptResult = TransformResult<IbGibRobbotAny>;\n", "import { delay, getSaferSubstring, getTimestampInTicks, getUUID, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { Gib, Ib, } from '@ibgib/ts-gib/dist/types.mjs';\nimport { validateGib, validateIb, validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';\nimport { GIB, IbGib_V1, getGib, getGibInfo, } from '@ibgib/ts-gib/dist/V1/index.mjs';\n\n\nimport { IbGibTimelineUpdateInfo } from '../../common/other/other-types.mjs';\nimport { WitnessFormBuilder } from '../witness-form-builder.mjs';\nimport { IbGibRobbotAny } from './robbot-base-v1.mjs';\nimport {\n    DEFAULT_INTERACTION_SUBJECTTJPGIBS_DELIM,\n    UNDEFINED_INTERACTION_SUBJECTTJPGIBS_STRING,\n    DEFAULT_ROBBOT_REQUEST_ESCAPE_STRING,\n    RobbotData_V1, RobbotIbGib_V1, RobbotInteractionData_V1, RobbotInteractionIbGib_V1,\n    RobbotInteractionIbInfo, RobbotInteractionRel8ns_V1, RobbotInteractionType,\n    ROBBOT_INTERACTION_ATOM, ROBBOT_SESSION_ATOM, DEFAULT_ROBBOT_REQUEST_MAX_LENGTH, RobbotPromptResult,\n} from './robbot-types.mjs';\nimport { IbGibSpaceAny } from '../space/space-base-v1.mjs';\nimport { persistTransformResult, registerNewIbGib, rel8ToSpecialIbGib } from '../space/space-helper.mjs';\nimport { isComment, parseCommentIb } from '../../common/comment/comment-helper.mjs';\nimport { ROBBOT_REL8N_NAME } from './robbot-constants.mjs';\nimport { GLOBAL_LOG_A_LOT, ROBBOT_NAME_REGEXP, ROBBOT_PREFIX_SUFFIX_REGEXP, ROBBOT_PREFIX_SUFFIX_REGEXP_DESC } from '../../core-constants.mjs';\nimport { MetaspaceService } from '../space/metaspace/metaspace-types.mjs';\nimport { UUID_REGEXP } from '@ibgib/helper-gib/dist/constants.mjs';\n\n\nconst logalot = GLOBAL_LOG_A_LOT || false;\n\n\nexport function getRobbotResultMetadata({ robbot }: { robbot: IbGibRobbotAny }): string {\n    return `${robbot.ib} ${getTimestampInTicks()}`;\n}\n\n\nexport function validateCommonRobbotData({\n    robbotData,\n}: {\n    robbotData?: RobbotData_V1,\n}): string[] {\n    const lc = `[${validateCommonRobbotData.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n        if (!robbotData) { throw new Error(`robbotData required (E: 1ac78ffae5354b67acb64a34cfe23c2f)`); }\n        const errors: string[] = [];\n        const {\n            name, uuid, classname,\n            outputPrefix, outputSuffix,\n        } =\n            robbotData;\n\n        if (name) {\n            if (!name.match(ROBBOT_NAME_REGEXP)) {\n                errors.push(`name must match regexp: ${ROBBOT_NAME_REGEXP}`);\n            }\n        } else {\n            errors.push(`name required.`);\n        }\n\n        if (uuid) {\n            if (!uuid.match(UUID_REGEXP)) {\n                errors.push(`uuid must match regexp: ${UUID_REGEXP}`);\n            }\n        } else {\n            errors.push(`uuid required.`);\n        }\n\n        if (outputPrefix) {\n            if (!outputPrefix.match(ROBBOT_PREFIX_SUFFIX_REGEXP)) {\n                errors.push(`outputPrefix must match regexp: ${ROBBOT_PREFIX_SUFFIX_REGEXP}`);\n            }\n        }\n\n        if (outputSuffix) {\n            if (!outputSuffix.match(ROBBOT_PREFIX_SUFFIX_REGEXP)) {\n                errors.push(`outputSuffix must match regexp: ${ROBBOT_PREFIX_SUFFIX_REGEXP}`);\n            }\n        }\n\n        if (classname) {\n            if (!classname.match(ROBBOT_NAME_REGEXP)) {\n                errors.push(`classname must match regexp: ${ROBBOT_NAME_REGEXP}`);\n            }\n        }\n\n        return errors;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport async function validateCommonRobbotIbGib({\n    robbotIbGib,\n}: {\n    robbotIbGib: RobbotIbGib_V1,\n}): Promise<string[] | undefined> {\n    const lc = `[${validateCommonRobbotIbGib.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: f7b34d791a483b8c5a9d188da66d3f22)`); }\n        const intrinsicErrors: string[] = await validateIbGibIntrinsically({ ibGib: robbotIbGib }) ?? [];\n\n        if (!robbotIbGib.data) { throw new Error(`robbotIbGib.data required (E: 754a8d2540610696aff04b0d159daa23)`); }\n        const ibErrors: string[] = [];\n        let { robbotClassname, robbotName, robbotId } = parseRobbotIb({ robbotIb: robbotIbGib.ib });\n        if (!robbotClassname) { ibErrors.push(`robbotClassname required (E: 3234d39bf1c74ec3aff59f374282dfc8)`); }\n        if (!robbotName) { ibErrors.push(`robbotName required (E: b329dcc62ff548d7aa0681393b2c7057)`); }\n        if (!robbotId) { ibErrors.push(`robbotId required (E: b562c953bfaf4dd49e4d3a08304ee2fc)`); }\n\n        const dataErrors = validateCommonRobbotData({ robbotData: robbotIbGib.data });\n\n        let result = [...(intrinsicErrors ?? []), ...(ibErrors ?? []), ...(dataErrors ?? [])];\n        if (result.length > 0) {\n            return result;\n        } else {\n            return undefined;\n        }\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport function getRobbotIb({\n    robbotData,\n    classname,\n}: {\n    robbotData: RobbotData_V1,\n    classname?: string,\n}): Ib {\n    const lc = `[${getRobbotIb.name}]`;\n    try {\n        const validationErrors = validateCommonRobbotData({ robbotData });\n        if (validationErrors.length > 0) { throw new Error(`invalid robbotData: ${validationErrors} (E: 390316b7c4fb0bd104ddc4e6c2e12922)`); }\n        if (classname) {\n            if (robbotData.classname && robbotData.classname !== classname) { throw new Error(`classname does not match robbotData.classname (E: e21dbc830856fbcee1d3ab260b0c5922)`); }\n        } else {\n            classname = robbotData.classname;\n            if (!classname) { throw new Error(`classname required (E: e0519f89df8a468c8743cb932f436bfe)`); }\n        }\n\n        // ad hoc validation here. should centralize witness classname validation\n\n        const { name, uuid } = robbotData;\n        return `witness robbot ${classname} ${name} ${uuid}`;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    }\n}\n\n/**\n * Current schema is `witness robbot [classname] [robbotName] [robbotId]\n *\n * NOTE this is space-delimited\n */\nexport function parseRobbotIb({\n    robbotIb,\n}: {\n    robbotIb: Ib,\n}): {\n    robbotClassname: string,\n    robbotName: string,\n    robbotId: string,\n} {\n    const lc = `[${parseRobbotIb.name}]`;\n    try {\n        if (!robbotIb) { throw new Error(`robbotIb required (E: 4a35881058094f1a90bb4ea37052d6d7)`); }\n\n        const pieces = robbotIb.split(' ');\n\n        return {\n            robbotClassname: pieces[2],\n            robbotName: pieces[3],\n            robbotId: pieces[4],\n        };\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    }\n}\n\n\n/**\n * Prompts the user a form to build the robbot.\n *\n * Once prompted, the robbot is:\n * 1. validated\n * 2. persisted in the given {@link space}\n * 3. registered with the space\n * 4. related to the space's special robbots index\n * 5. new robbot is returned\n *\n * @returns newly created robbot ibgib (witness)\n */\nexport async function createNewRobbot({\n    fnPromptRobbot,\n    ibgibs,\n    space,\n}: {\n    fnPromptRobbot: (space: IbGibSpaceAny, ibGib: RobbotIbGib_V1 | null) => Promise<RobbotPromptResult | undefined>;\n    /**\n     * Either {@link common} or {@link ibgibs} is required\n     * @hack\n     */\n    ibgibs?: MetaspaceService,\n    /**\n     * space within which to create the robbot. if not provided, the\n     * defaults to the local user space via {@link common} or {@link ibgibs}.\n     */\n    space: IbGibSpaceAny,\n}): Promise<IbGibRobbotAny | undefined> {\n    const lc = `[${createNewRobbot.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n\n        if (!ibgibs) { throw new Error(`(UNEXPECTED) ibgibs service required. (E: 4be5d20dc81fcdabb8d7d4cd47458522)`); }\n\n        space = space ?? await ibgibs.getLocalUserSpace({ lock: true });\n\n        // prompt user to create the ibgib, passing in null because we're\n        // creating not editing.\n        let resRobbot = await fnPromptRobbot(space, /*ibGib because creating*/null);\n\n        if (!resRobbot) { throw new Error(`robbot prompt returned nothing. canceled? (E: 1a08529b53bd3d79c6587b196e5e0823)`); }\n\n        /** this should be the witness class itself at this point. */\n        const newRobbot = (resRobbot.newIbGib as IbGibRobbotAny);\n        // let loading = await common.loadingCtrl.create({ message: 'creating...' });\n        try {\n            // await loading.present();\n            await delay(1000); // ensure that the user sees a creating message\n            let allIbGibs: IbGib_V1[] = [];\n            allIbGibs.push(newRobbot);\n            resRobbot.intermediateIbGibs?.forEach(x => allIbGibs.push(x));\n            resRobbot.dnas?.forEach(x => allIbGibs.push(x));\n            for (let i = 0; i < allIbGibs.length; i++) {\n                const ibGib = allIbGibs[i];\n                const validationErrors = await validateIbGibIntrinsically({ ibGib });\n                if ((validationErrors ?? []).length > 0) { throw new Error(`(unexpected) invalid robbot ibgib created. validationErrors: ${validationErrors}. robbot: ${pretty(newRobbot.toIbGibDto())} (E: a683268621cd6dd3dd60310b164c4d22)`); }\n            }\n\n            await persistTransformResult({ resTransform: resRobbot, space });\n            const { zeroSpace, fnBroadcast, fnUpdateBootstrap } = ibgibs;\n            await registerNewIbGib({\n                ibGib: newRobbot,\n                space,\n                fnBroadcast: (x: IbGibTimelineUpdateInfo) => fnBroadcast(x),\n            });\n\n            await rel8ToSpecialIbGib({\n                type: \"robbots\",\n                rel8nName: ROBBOT_REL8N_NAME,\n                ibGibsToRel8: [newRobbot],\n                space,\n                zeroSpace,\n                fnUpdateBootstrap,\n                fnBroadcast,\n            });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n            // } finally {\n            // await loading.dismiss();\n        }\n        return newRobbot;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        return;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport class RobbotFormBuilder extends WitnessFormBuilder {\n    protected lc: string = `[${RobbotFormBuilder.name}]`;\n\n    constructor() {\n        super();\n        this.what = 'robbot';\n    }\n\n    outputPrefix({\n        of,\n        required,\n        defaultValue,\n    }: {\n        of: string,\n        required?: boolean,\n        defaultValue?: string,\n    }): RobbotFormBuilder {\n        this.addItem({\n            // witness.data.outputPrefix\n            name: \"outputPrefix\",\n            description: `Technical setting that sets a prefix for all text output of the robbot.`,\n            label: \"Output Prefix\",\n            regexp: ROBBOT_PREFIX_SUFFIX_REGEXP,\n            regexpErrorMsg: ROBBOT_PREFIX_SUFFIX_REGEXP_DESC,\n            dataType: 'textarea',\n            value: of,\n            defaultValue,\n            required,\n        });\n        return this;\n    }\n\n    outputSuffix({\n        of,\n        required,\n        defaultValue,\n    }: {\n        of: string,\n        required?: boolean,\n        defaultValue?: string,\n    }): RobbotFormBuilder {\n        this.addItem({\n            // witness.data.outputSuffix\n            name: \"outputSuffix\",\n            description: `Technical setting that sets a suffix for all text output of the ${this.what}. (like a signature)`,\n            label: \"Output Suffix\",\n            regexp: ROBBOT_PREFIX_SUFFIX_REGEXP,\n            regexpErrorMsg: ROBBOT_PREFIX_SUFFIX_REGEXP_DESC,\n            dataType: 'textarea',\n            value: of,\n            defaultValue,\n            required,\n        });\n        return this;\n    }\n\n}\n\n/**\n * checks to see if the comment is an ibgib and if that comment starts\n * with the escape sequence.\n */\nexport function isRequestComment({\n    ibGib,\n    requestEscapeString = DEFAULT_ROBBOT_REQUEST_ESCAPE_STRING,\n}: {\n    ibGib: IbGib_V1,\n    requestEscapeString?: string,\n}): boolean {\n    const lc = `${isRequestComment.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: d7c49619ffb7a9c26d9d74959b91ae22)`); }\n\n        if (!isComment({ ibGib })) { return false; /* <<<< returns early */ }\n\n        let { ib } = ibGib;\n        if (!ib) { throw new Error(`ib or ibGib.ib required (E: d92c26b15fc143977955a167b8b67522)`); }\n\n        requestEscapeString = requestEscapeString || DEFAULT_ROBBOT_REQUEST_ESCAPE_STRING;\n\n        let { safeIbCommentText } = parseCommentIb({ ib });\n\n        return safeIbCommentText.startsWith(requestEscapeString);\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * Strips the request escape string and any non-alphanumeric characters except spaces,\n * returning the rest fo the string up to `maxLength`.\n *\n * This does *not* interpret anything beyond this.\n */\nexport function getSpaceDelimitedSaferRequestText({\n    ibGib,\n    requestEscapeString = DEFAULT_ROBBOT_REQUEST_ESCAPE_STRING,\n    lowercase,\n    maxLength,\n}: {\n    ibGib: IbGib_V1,\n    requestEscapeString?: string,\n    lowercase?: boolean,\n    maxLength?: number,\n}): string {\n    const lc = `${getSpaceDelimitedSaferRequestText.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: b4cbe054fe254414b77204ad80e519aa)`); }\n\n        if (!isComment({ ibGib })) { throw new Error(`ibGib is not a comment (E: ab34df44eb57c170cec6c6db6f4f5722)`); }\n\n        let { data } = ibGib;\n        if (!data) { throw new Error(`ibGib.data required (E: 6155a49a0c1286c0bb8aa6f81c396522)`); }\n\n        let text: string = data.text;\n\n        requestEscapeString = requestEscapeString || DEFAULT_ROBBOT_REQUEST_ESCAPE_STRING;\n        const length = maxLength || DEFAULT_ROBBOT_REQUEST_MAX_LENGTH;\n\n        text = getSaferSubstring({\n            text: text,\n            length,\n            keepLiterals: [' ', requestEscapeString]\n        });\n\n        text = text\n            .substring(requestEscapeString.length) // remove the escape string\n            .trim();\n\n        if (lowercase) {\n            text = text.toLowerCase();\n        }\n\n        return text;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * Creates space-delimited ib. Extracts certain info from `data` and appends\n * addlDetailsText at the end.\n *\n * atow the schema is:\n *\n *     return addlDetailsText ?\n *         `${ROBBOT_INTERACTION_ATOM} ${data.type} ${timestampInTicks} ${subjectTjpGibsString} ${addlDetailsText}` :\n *         `${ROBBOT_INTERACTION_ATOM} ${data.type} ${timestampInTicks} ${subjectTjpGibsString}`;\n *\n * @returns space-delimited interaction ib\n */\nexport function getInteractionIb({\n    data,\n    addlDetailsText,\n}: {\n    data: RobbotInteractionData_V1,\n    addlDetailsText?: string,\n}): Ib {\n    const lc = `[${getInteractionIb.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 9ac657cab7e292e2bd587595757ab622)`); }\n        if (!data) { throw new Error(`data required (E: 8fac6ce2ae6dd521255dc8ba241a5222)`); }\n        if (!data.type) { throw new Error(`data.type required (E: 77786fe653be04c9fa33e30ac3b77f22)`); }\n        let saferType = getSaferSubstring({ text: data.type, length: 32 });\n        if (data.type !== saferType) { throw new Error(`invalid data.type (${data.type}). Should be safer like (${saferType}) (E: efe7888da08f148c8972c0923356b122)`); }\n\n        if (!data.timestamp) { throw new Error(`data.timestamp required (E: 8682a5af1cd48d0cb372b7f519a61e22)`); }\n        const dataTimestampIsInt = Number.isInteger(Number.parseInt(data.timestamp));\n        const timestampInTicks = dataTimestampIsInt ?\n            data.timestamp :\n            getTimestampInTicks(data.timestamp);\n\n        const subjectTjpGibs = data.subjectTjpGibs ?? [];\n        let subjectTjpGibsString: string;\n        if (subjectTjpGibs.length === 0) {\n            if (logalot) { console.log(`${lc} data.subjectTjpGibs is falsy. defaulting subjectTjpGibsString to ${UNDEFINED_INTERACTION_SUBJECTTJPGIBS_STRING} (I: 850477faa7316bb65e6e0e370dc54f22)`); }\n            subjectTjpGibsString = UNDEFINED_INTERACTION_SUBJECTTJPGIBS_STRING;\n        } else {\n            subjectTjpGibsString = subjectTjpGibs.join(DEFAULT_INTERACTION_SUBJECTTJPGIBS_DELIM)\n        }\n\n        if (addlDetailsText) {\n            let saferAddlDetailsText = getSaferSubstring({ text: addlDetailsText, length: 64 });\n            if (saferAddlDetailsText !== addlDetailsText) {\n                console.warn(`${lc} using safer version of addlDetailsText: ${saferAddlDetailsText}. (W: b5516dabaeab4c93996e726e8feffe7f)`)\n                addlDetailsText = saferAddlDetailsText;\n            }\n        }\n\n        return addlDetailsText ?\n            `${ROBBOT_INTERACTION_ATOM} ${data.type} ${timestampInTicks} ${subjectTjpGibsString} ${addlDetailsText}` :\n            `${ROBBOT_INTERACTION_ATOM} ${data.type} ${timestampInTicks} ${subjectTjpGibsString}`;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport function parseInteractionIb({\n    ib,\n}: {\n    ib: Ib,\n}): RobbotInteractionIbInfo {\n    const lc = `[${parseInteractionIb.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: ed5e959a2952fc6684a168ef8e9b6622)`); }\n        const ibValidationErrors = validateIb({ ib }) ?? [];\n        if (ibValidationErrors.length > 0) { throw new Error(`ib (${ib}) has validationErrors: ${ibValidationErrors} (E: c1b8c65524561ae67f58b237ba12fb22)`); }\n\n        let [atom, type, timestampInTicks, subjectTjpGibsString, addlDetailsText] = ib.split(' ');\n        if (atom !== ROBBOT_INTERACTION_ATOM) {\n            console.warn(`${lc} atom !== default robbot interaction atom (${atom} !== ${ROBBOT_INTERACTION_ATOM}) (W: 9102868391174bbc90c54cb53726a4de)`);\n        }\n        if (!Object.values(RobbotInteractionType).includes((type as any))) {\n            console.warn(`${lc} unknown robbot interaction type (${type}). (W: 68e85a9c495542f4a4a164752cc600e3)`);\n        }\n        let subjectTjpGibs: Gib[] | undefined = undefined;\n        if (subjectTjpGibsString !== UNDEFINED_INTERACTION_SUBJECTTJPGIBS_STRING) {\n            subjectTjpGibs =\n                subjectTjpGibsString.split(DEFAULT_INTERACTION_SUBJECTTJPGIBS_DELIM).filter(x => !!x);\n            const invalidTjpGibs = subjectTjpGibs.filter(gib => {\n                const validationErrors = validateGib({ gib }) ?? [];\n                if (validationErrors.length > 0) {\n                    console.error(`${lc} tjpGib (${gib}) has validation errors: ${validationErrors} (E: 679a654649ae4945932e85b3ded981be)`);\n                    return true;\n                } else {\n                    return false;\n                }\n            });\n            if (invalidTjpGibs.length > 0) { throw new Error(`ib contains invalid tjpGibs: ${invalidTjpGibs} (E: 7a5074e2e8685ec28c83954a1c12df22)`); }\n        }\n\n        return { atom, type, timestampInTicks, subjectTjpGibs, addlDetailsText };\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport function isInteraction({\n    ibGib,\n    ib,\n}: {\n    ibGib?: IbGib_V1,\n    ib?: Ib,\n}): boolean {\n    const lc = `[${isInteraction.name}]`;\n    try {\n        ib = ib ?? ibGib?.ib;\n        if (!ib) { throw new Error(`either ib or ibGib required (E: 15786fe75a5219ec7d925189f22d9f22)`); }\n        let info = parseInteractionIb({ ib });\n        return info.atom === ROBBOT_INTERACTION_ATOM;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    }\n}\n\n/**\n * creates an ibgib stone (no tjp) that contains the interaction info.\n *\n * @returns interaction ibgib stone\n */\nexport async function getInteractionIbGib_V1({\n    data,\n    rel8ns,\n    addlDetailsText,\n}: {\n    /**\n     * beginning data that may be mutated in this function.\n     */\n    data: RobbotInteractionData_V1,\n    /**\n     * beginning rel8ns that may be mutated in this function.\n     */\n    rel8ns?: RobbotInteractionRel8ns_V1,\n    /**\n     * for use in creating the ib per use case, if provided\n     *\n     * atow, I'm not using this.\n     */\n    addlDetailsText?: string,\n}): Promise<RobbotInteractionIbGib_V1> {\n    const lc = `[${getInteractionIbGib_V1.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 138e6a406e1c600aad5b64e58a250922)`); }\n\n        if (!data) { throw new Error(`data required (E: 7bdc46e1cfca9c286fc0dad9e8d60722)`); }\n\n        if (!data.uuid) { data.uuid = await getUUID(); }\n\n        rel8ns = rel8ns ?? {};\n        rel8ns.ancestor = [`${ROBBOT_INTERACTION_ATOM}^${GIB}`];\n        delete rel8ns.past;\n\n        const ib = getInteractionIb({ data, addlDetailsText });\n\n        const ibGib: RobbotInteractionIbGib_V1 = {\n            ib, data, rel8ns,\n        };\n        ibGib.gib = await getGib({ ibGib, hasTjp: false });\n\n        return ibGib;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport function getRobbotSessionIb({\n    robbot,\n    timestampInTicks,\n    sessionId,\n    contextTjpGib,\n    addlMetadata,\n}: {\n    robbot: IbGibRobbotAny,\n    timestampInTicks: string,\n    sessionId: string,\n    contextTjpGib: Gib,\n    addlMetadata?: string,\n}): string {\n    const lc = `[${getRobbotSessionIb.name}]`;\n    try {\n        // validate\n        if (logalot) { console.log(`${lc} starting... (I: 21206e0defe4bf23db96979fb456e822)`); }\n        if (!robbot) { throw new Error(`robbot required (E: 200b32bbc4cac516e56d9561a9ffae22)`); }\n        if (!robbot.data?.name) { throw new Error(`robbot.data.name required (E: d6470d5a146a1794811b9577ce881522)`); }\n        if (!robbot.data.classname) { throw new Error(`robbot.data.classname required (E: 42077779c80889f1079e582d45932e22)`); }\n        if (!robbot.data.uuid) { throw new Error(`robbot.data.uuid required (E: 34222f5639c329c99a2007ba6789bb22)`); }\n        if (!timestampInTicks) { throw new Error(`timestampInTicks required (E: 17447cb30277af2beea8f2b13266c722)`); }\n        if (!sessionId) { throw new Error(`sessionId required (E: 37a1737920996a55f311e79efe558422)`); }\n        if (!contextTjpGib) { throw new Error(`contextTjpGib required (E: ad967964b764b077f448121e8b63c822)`); }\n        if (addlMetadata) { if (!addlMetadata.match(/^\\w+$/)) { throw new Error(`addlMetadata must be alphanumerics only (E: 26f52b1378d1ad01f20f8ef5a5441722)`); } }\n\n        // prepare\n        const { name, classname, uuid } = robbot.data;\n        const robbotTjpGib = getGibInfo({ gib: robbot.gib }).tjpGib;\n\n        // main ib string\n        let resultIb = `${ROBBOT_SESSION_ATOM} ${timestampInTicks} ${name} ${classname} ${uuid} ${robbotTjpGib} ${sessionId} ${contextTjpGib}`;\n\n        // amend if addlMetadata provided\n        if (addlMetadata) { resultIb += ` ${addlMetadata}`; }\n\n        // returns\n        return resultIb;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport function parseRobbotSessionIb({\n    ib,\n}: {\n    ib: Ib,\n}): {\n    timestamp: string,\n    robbotName: string,\n    robbotClassname: string,\n    robbotId: string,\n    robbotTjpGib: Gib,\n    sessionId: string,\n    contextTjpGib: Gib,\n    addlMetadata: string,\n} {\n    const lc = `[${parseRobbotSessionIb.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 21206e0defe4bf23db96979fb456e822)`); }\n        if (!ib) { throw new Error(`ib required (E: c99627d871dbada4745474d9b63d4822)`); }\n\n        const pieces = ib.split(' ');\n        if (pieces.length !== 8 && pieces.length !== 9) { throw new Error(`invalid ib. should be space-delimited with 8 or 9 pieces, but there were ${pieces.length}. Expected pieces: atom, timestamp, robbotName, robbotClassname, robbotId, robbotTjpGib, sessionId, contextTjpGib, and optional addlMetadata. (E: 239ba7f599ce02a20271dd288c187d22)`); }\n\n        const [_, timestamp, robbotName, robbotClassname, robbotId, robbotTjpGib, sessionId, contextTjpGib, addlMetadata] = ib.split(' ');\n        return {\n            timestamp,\n            robbotName, robbotClassname, robbotId, robbotTjpGib,\n            sessionId,\n            contextTjpGib,\n            addlMetadata\n        };\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n", "/**\n * @module secret constants\n *\n * constants are in this file!\n */\n\n// /**\n//  * example enum-like type+const that I use in ibgib. sometimes i put\n//  * these in the types.mts and sometimes in the const.mts, depending\n//  * on context.\n//  */\n// export type SomeEnum =\n//     'ib' | 'gib';\n// export const SomeEnum = {\n//     ib: 'ib' as SomeEnum,\n//     gib: 'gib' as SomeEnum,\n// } satisfies { [key: string]: SomeEnum };\n// export const SOME_TYPE_VALUES: SomeEnum[] = Object.values(SomeEnum);\n\n/**\n * atom used in ibs\n */\nexport const SECRET_ATOM = 'secret';\n\n/**\n * default regexp for a simple name string.\n */\nexport const SECRET_NAME_REGEXP = /^[a-zA-Z0-9_\\-.]{1,255}$/;\n\n/**\n * A secrets ibgib uses this rel8n name for its children secrets.\n */\nexport const SECRET_REL8N_NAME = 'secret';\n\n/**\n * this is the length of the substring that we'll create when generating partial\n * hash substrings for password \"probably correct\" verification.  this check is\n * made only for the user's convenience to see if they \"probably\" typed in their\n * password correctly. If they typo the password or just type in the wrong one,\n * there is an approximately 1/250 chance on average\n *\n * @see `SecretInfo_Password.passwordProbablyCorrectInfo` in secret-types.mts\n *\n * READ THE DOCS FOR THAT LINK\n */\nexport const DEFAULT_PASSWORD_CHECK_SUBSTRING_LENGTH = 4;\n", "/**\n * @module outer-space\n * Outer spaces are spaces connecting local inner spaces.\n * ATOW there is just sync spaces, but definitely just the beginning.\n *\n * ## on future implementations, CRDT-like behavior\n *\n * I just realized that when merging, I can actually create a meta transform\n * ibgib to maintain the order of transforms.\n */\n\nimport { Ib, } from '@ibgib/ts-gib/dist/types.mjs';\nimport { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../../../core-constants.mjs';\nimport { SpaceType, SpaceSubtype, VALID_SPACE_SUBTYPES, VALID_SPACE_TYPES, } from '../space-types.mjs';\nimport { ParticipantInfo, StatusCode, StatusIbInfo, SyncSpaceIbGib, } from './outer-space-types.mjs';\nimport { OUTER_SPACE_DEFAULT_IB_DELIMITER } from './outer-space-constants.mjs';\nimport { IbGibSpaceAny } from '../space-base-v1.mjs';\nimport { getSpecialRel8dIbGibs } from '../space-helper.mjs';\nimport { SpecialIbGibType } from '../../../common/other/other-types.mjs';\nimport { SYNC_SPACE_REL8N_NAME } from '../space-constants.mjs';\nimport { SpaceFactoryFnMap } from '../metaspace/metaspace-types.mjs';\n\n\n/**\n * for verbose logging\n */\nconst logalot = GLOBAL_LOG_A_LOT;\n\n/**\n * Composes ib with given params info.\n *\n * @returns ib string with given info encoded\n */\nexport function getStatusIb({\n    sagaId,\n    statusCode,\n    spaceType,\n    spaceSubtype,\n    delimiter,\n}: StatusIbInfo): string {\n    const lc = `[${getStatusIb.name}]`;\n    try {\n        if (!sagaId) { throw new Error(`sagaId required. (E: cfc923bb29ee4aa788e947b6416740e6)`); }\n        if (statusCode === null || statusCode === undefined) { throw new Error(`status code required. (E: 4e0d232a9955496695012623c2e17ca2)`); }\n        if (!Object.values(StatusCode).includes(statusCode)) { throw new Error(`invalid status code (${statusCode}) (E: 91d7655424c44d9680fff099ee2b54d2)`); }\n        if (!spaceType) { throw new Error(`spaceType required. (E: 86e98694a56a4f599e98e50abf0eed43)`); }\n        if (!spaceSubtype) { throw new Error(`spaceSubtype required. (E: 4857d4677ee34e95aeb2251dd633909e)`); }\n\n        delimiter = delimiter || OUTER_SPACE_DEFAULT_IB_DELIMITER;\n\n        return `status ${sagaId} ${statusCode} ${spaceType} ${spaceSubtype}`;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\n/**\n * Parses the given `statusIb` and returns the info object.\n *\n * @returns info from parsing the status ib\n */\nexport function getStatusIbInfo({\n    statusIb,\n    delimiter,\n}: {\n    statusIb: Ib,\n    delimiter?: string,\n}): StatusIbInfo {\n    const lc = `[${getStatusIb.name}]`;\n    try {\n        if (!statusIb) { throw new Error(`statusIb required. (E: 09e23e8622cf456cadb0c3d0aadc3be9)`); }\n\n        delimiter = delimiter || OUTER_SPACE_DEFAULT_IB_DELIMITER;\n\n        // atow `status ${sagaId} ${statusCode} ${spaceType} ${spaceSubtype}`;\n        const pieces = statusIb.split(delimiter);\n\n        const sagaId = pieces[1];\n        if (sagaId === null || sagaId === undefined) { throw new Error(`sagaId is null/undefined. (E: 5de2861a6afb48e1a1c89d0402a4ea63)`); }\n\n        const statusCode = pieces[2] as StatusCode; // tenatively cast as StatusCode\n        if (!Object.values(StatusCode).includes(statusCode)) { throw new Error(`invalid/unknown status code (${statusCode}) (E: 7580860df7b344b3992148552e80a85e)`); }\n\n        const spaceType = pieces[3] as SpaceType;\n        if (spaceType === null || spaceType === undefined) { throw new Error(`spaceType is null/undefined. (E: 12473d35e77b451bb59bb05c03cb8b64)`); }\n        if (!VALID_SPACE_TYPES.includes(spaceType)) { throw new Error(`invalid/unknown spaceType (${spaceType}) (E: d3ba9add427f49dda34f265f3225d9db)`); }\n\n        const spaceSubtype = pieces[4] as SpaceSubtype;\n        if (spaceSubtype === null || spaceSubtype === undefined) { throw new Error(`spaceSubtype is null/undefined. (E: 6da7ae919d0b4a22b4ee685520b6c946)`); }\n        if (!VALID_SPACE_SUBTYPES.includes(spaceSubtype)) { throw new Error(`invalid/unknown spaceSubtype (${spaceSubtype}) (E: 703ed1aee44447a294b3e1cf0984baba)`); }\n\n        return { statusCode, spaceType, spaceSubtype, sagaId, delimiter };\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\nexport async function getSyncSpaces({\n    space,\n}: {\n    space: IbGibSpaceAny,\n}): Promise<SyncSpaceIbGib[]> {\n    const lc = `[${getSyncSpaces.name}]`;\n    try {\n        if (!space) { throw new Error(`space required. (E: c03f80eca6b045b9a73b0aafa44cdf26)`); }\n        let syncSpaces = await getSpecialRel8dIbGibs<SyncSpaceIbGib>({\n            type: SpecialIbGibType.outerspaces,\n            rel8nName: SYNC_SPACE_REL8N_NAME,\n            space,\n        });\n        return syncSpaces;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\n/**\n * gets the sync space ibgibs referenced in the given local {@link localSpace}\n * and loads them into their corresponding witness classes.\n *\n * note: atow (03/2024) this throws if a factory function isn't found for ANY of\n * the sync spaces found. later on, when multiple kinds of sync spaces are in\n * existence, this behavior should change because it would be quite possible\n * that we have multiple spaces that may not have a loaded factory function\n * available.\n *\n * @see {@link SpaceFactoryFnMap}\n *\n * @returns sync space witnesses\n */\nexport async function getSyncSpaces_witnesses({\n    localSpace,\n    spaceFactoryFns,\n}: {\n    /**\n     * user's local space that contains references to outer space \"proxy\"\n     * ibgibs.\n     */\n    localSpace: IbGibSpaceAny,\n    /**\n     * factory function map (by type/subtype) that generates the space witnesses\n     * from the space dtos.\n     *\n     * @see {@link SpaceFactoryFnMap}\n     */\n    spaceFactoryFns: SpaceFactoryFnMap,\n}): Promise<IbGibSpaceAny[]> {\n    const lc = `[${getSyncSpaces_witnesses.name}]`;\n    try {\n        if (!localSpace) { throw new Error(`localSpace required. (E: c03f80eca6b045b9a73b0aafa44cdf26)`); }\n        let resSpaceWitnesses: IbGibSpaceAny[] = [];\n\n        const syncSpaceDtos = await getSyncSpaces({ space: localSpace });\n        for (let i = 0; i < syncSpaceDtos.length; i++) {\n            const syncSpaceDto = syncSpaceDtos[i];\n            if (!syncSpaceDto.data) { throw new Error(`(UNEXPECTED) syncSpaceDto.data falsy? (E: 5404f124b8bb781c0a52b3cc9f8e6524)`); }\n            const { type, subtype } = syncSpaceDto.data;\n            if (!type) { throw new Error(`(UNEXPECTED) syncSpaceDto.data.type falsy? (E: b3461e0df562d301fc84d68d95f91424)`); }\n            if (!subtype) { throw new Error(`(UNEXPECTED) syncSpaceDto.data.subtype falsy? (E: 524c471119564b4b817261f9e1edcafb)`); }\n            const fnFactory_typeSubset = spaceFactoryFns[syncSpaceDto.data.type] ?? {};\n            const fnFactory = fnFactory_typeSubset[syncSpaceDto.data.subtype];\n            if (!fnFactory) { throw new Error(`(UNEXPECTED) no factory function found for type (${type}) and subtype (${subtype})? (E: fd726f9049ade511f679d1de621dec24)`); }\n            const spaceWitness = await fnFactory(syncSpaceDto);\n            resSpaceWitnesses.push(spaceWitness);\n        }\n\n        if (syncSpaceDtos.length !== resSpaceWitnesses.length) {\n            throw new Error(`(UNEXPECTED) syncSpaceDtos.length !== resSpaceWitnesses.length? (E: c85b1c93fce972a57683da727e6dc224)`);\n        }\n\n        return resSpaceWitnesses;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\nexport function getSrcLocalSpaceId({\n    participants,\n}: {\n    participants: ParticipantInfo[],\n}): string {\n    const lc = `[${getSrcLocalSpaceId.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 43c9a4f1fa1bbc944b98f8eed2f81924)`); }\n\n        const participants_src = participants.filter(x => x.s_d === 'src');\n        if (participants_src.length !== 1) { throw new Error(`(UNEXPECTED) participants_src.length !== 1? atow (03/2024) only one src participant is expected. (E: ed4b3ae15f5da34c77655553aaf82224)`); }\n\n        return participants_src.at(0)!.id;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n", "import { delay, getUUID, groupBy, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { encrypt, decrypt, } from '@ibgib/encrypt-gib/dist/encrypt-decrypt.mjs';\nimport { DEFAULT_ALPHABET_INDEXING_MODE_BLOCKMODE, DEFAULT_ALPHABET_INDEXING_MODE_LEGACY } from '@ibgib/encrypt-gib/dist/constants.mjs';\nimport { IbGib_V1, } from '@ibgib/ts-gib/dist/V1/types.mjs';\nimport { GIB, GIB_DELIMITER, IB, ROOT, } from '@ibgib/ts-gib/dist/V1/constants.mjs';\nimport { IbGibAddr, TjpIbGibAddr, TransformResult, } from '@ibgib/ts-gib/dist/types.mjs';\nimport { getIbGibAddr, } from '@ibgib/ts-gib/dist/helper.mjs';\nimport { getGib, getGibInfo, isPrimitive } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';\n\nimport { GLOBAL_LOG_A_LOT, GLOBAL_TIMER_NAME } from '../../../core-constants.mjs';\nimport {\n    DeleteIbGibOpts, DeleteIbGibResult,\n    GetIbGibOpts, GetIbGibResult,\n    PutIbGibOpts, PutIbGibResult\n} from '../../../common/other/other-types.mjs';\nimport { TagIbGib_V1 } from '../../../common/tag/tag-types.mjs';\nimport {\n    OuterSpaceData,\n    ParticipantInfo, StatusCode, SyncSagaInfo, SyncSpaceIbGib, SyncSpaceOptionsData,\n    SyncSpaceOptionsIbGib, SyncSpaceResultIbGib, SyncStatusIbGib,\n} from '../../../witness/space/outer-space/outer-space-types.mjs';\nimport { IbGibSpaceData, IbGibSpaceRel8ns, SpaceId } from '../../../witness/space/space-types.mjs';\nimport { IbGibSpaceAny } from '../../../witness/space/space-base-v1.mjs';\nimport { BootstrapIbGib } from '../../../witness/space/bootstrap/bootstrap-types.mjs';\nimport { IbGibTimelineUpdateInfo, SpecialIbGibType } from '../../../common/other/other-types.mjs';\nimport { RootData } from '../../../common/root/root-types.mjs';\nimport {\n    CiphertextData, CiphertextIbGib_V1, CiphertextRel8ns,\n    EncryptionData_V1, EncryptionIbGib_V1, EncryptionInfo_EncryptGib,\n    EncryptionMethod,\n} from '../../../common/encrypt/encrypt-types.mjs';\nimport { RobbotIbGib_V1 } from '../../../witness/robbot/robbot-types.mjs';\nimport { AppIbGib_V1 } from '../../../witness/app/app-types.mjs';\nimport { constantIbGib, getTimelinesGroupedByTjp, hasTjp } from '../../../common/other/ibgib-helper.mjs';\nimport {\n    getValidatedBootstrapIbGib, getLocalSpace, execInSpaceWithLocking,\n    updateBootstrapIbGib, getSpaceArgMetadata, createTagIbGibAndSundry,\n    getConfigAddr, setConfigAddr, setCurrentRoot, rel8ToCurrentRoot,\n    rel8ToSpecialIbGib, registerNewIbGib, persistTransformResult, getFromSpace,\n    putInSpace, deleteFromSpace, getLatestAddrs, getTjpIbGib, getSpecialIbGib,\n    getSpecialRel8dIbGibs, /*createRobbotIbGib, */ trash, archive, parseSpaceIb,\n} from '../../../witness/space/space-helper.mjs';\nimport { getDependencyGraph, GetDependencyGraphOptions } from '../../../common/other/graph-helper.mjs';\nimport { RobbotPromptResult } from '../../../witness/robbot/robbot-types.mjs';\nimport { createNewRobbot, validateCommonRobbotData, validateCommonRobbotIbGib } from '../../../witness/robbot/robbot-helper.mjs';\nimport { AppPromptResult } from '../../../witness/app/app-types.mjs';\nimport { createNewApp, } from '../../../witness/app/app-helper.mjs';\nimport { IbGibCacheService } from '../../../common/cache/cache-types.mjs';\nimport { BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY, BOOTSTRAP_IBGIB_ADDR } from '../../../witness/space/bootstrap/bootstrap-constants.mjs';\nimport { DEFAULT_SECONDS_VALID_LOCAL, SYNC_SPACE_REL8N_NAME } from '../../../witness/space/space-constants.mjs';\nimport {\n    CIPHERTEXT_ATOM, DEFAULT_ENCRYPTION_HASH_ALGORITHM,\n    DEFAULT_ENCRYPTION_INITIAL_RECURSIONS,\n    DEFAULT_ENCRYPTION_RECURSIONS_PER_HASH, DEFAULT_ENCRYPTION_SALT_STRATEGY,\n    ENCRYPTION_REL8N_NAME,\n} from '../../../common/encrypt/encrypt-constants.mjs';\nimport { ROBBOT_REL8N_NAME } from '../../../witness/robbot/robbot-constants.mjs';\nimport { APP_REL8N_NAME } from '../../../witness/app/app-constants.mjs';\nimport { AUTOSYNC_ALWAYS_REL8N_NAME } from '../../../common/other/other-constants.mjs';\nimport {\n    MetaspaceInitializeOptions, CreateLocalSpaceOptions,\n    LocalSpaceFactoryFunction, MetaspaceFactory\n} from './metaspace-types.mjs';\nimport { MetaspaceService, TempCacheEntry } from './metaspace-types.mjs';\nimport { newupSubject } from '../../../common/pubsub/subject/subject-helper.mjs';\nimport { ObservableWitness, } from '../../../common/pubsub/observable/observable-types.mjs';\nimport { SubjectWitness } from '../../../common/pubsub/subject/subject-types.mjs';\nimport { SubscriptionWitness } from '../../../common/pubsub/subscription/subscription-types.mjs';\nimport { fnObs } from '../../../common/pubsub/observer/observer-helper.mjs';\nimport { SecretData_V1, SecretIbGib_V1, SecretInfo_Password } from '../../../common/secret/secret-types.mjs';\nimport { SECRET_REL8N_NAME } from '../../../common/secret/secret-constants.mjs';\nimport { getSrcLocalSpaceId } from '../outer-space/outer-space-helper.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT;\n\n/**\n * All-purpose mega service (todo: which we'll need to break up!) to interact\n * with ibgibs at the app/device level.\n *\n * This works with the local app user space.\n *\n * ## regarding special ibgibs\n *\n * Special ibgibs' behaviors are what hold in other apps configuration data.\n * Of course the difference is that most special ibgibs can leverage the \"on-chain\"\n * functionality of \"regular\" ibgibs.\n *\n * There are a couple meta ibgibs (which I also call \"special\"):\n *   * roots^gib\n *     * tracks other special root^gib ibgibs, which are like local app-level indexes.\n *   * tags^gib\n *     * tracks other special tag^gib ibgibs, which you can apply to any ibgib\n *   * latest^gib\n *     * tracks mappings between tjp -> latest ib^gib address\n *     * ephemeral (deletes past rel8ns and past ibGib frames)\n *   * ...\n *\n * ## regarding latest ibgibs\n *\n * The tjp (temporal junction point) defines atow the beginning of an ibGib\n * timeline.  it's like the birthday for an ibGib. (Or you can think if it as\n * the id for the stream of ibgib frames in a given timeline.)\n *\n * The latest ibGib in that timeline is also special, because it's often what\n * you want to work with.\n *\n * So ideally, when an ibgib, A, has a tjp A1, and it is updated to A2, A3, An\n * via `mut8` and/or `rel8` transforms, that ibgib creates a single timeline.\n * This service attempts to track the relationship between that starting tjp\n * address and its corresponding latest frame in that timeline, i.e., A1 -> An.\n *\n * ### mapping persistence implementation details\n *\n * The latest ibGib service is backed by a special ibgib that maintains the\n * mapping index.  It does this by rel8-ing that special backing ibgib via the\n * tjp pointer, e.g. [special latest ibgib^XXX000].rel8ns[A^TJP123] ===\n * [A^N12345] . It does this via the ib^gib content address pointer, so this\n * becomes a mapping from A^TJP123 to A^N12345.\n *\n * This backing ibGib is special (even for special ibGibs) in that:\n *   * it does not relate itself with the current root of the application\n *   * it does not maintain references to its past (i.e. rel8ns['past'] === [])\n *   * it DELETES its previous incarnation from the files service\n *\n * In other words, this service is meant to be as ephemeral as possible. I am\n * keeping it as an ibGib and not some other data format (like straight in\n * storage/some other db) because I've found this is often useful and what I end\n * up doing anyway to leverage other ibgib behavior. For example, in the future\n * it may be good to take snapshots, which is a simple copy operation of the\n * file persistence.\n *\n * ### current naive implementation notes\n *\n * questions:\n *   * What do we want to do if we can't locate an ibGib record?\n *   * How/when do we want to alert the user/our own code that we've found\n *     multiple timelines for an ibGib with a tjp (usually a thing we want to\n *     avoid)?\n *   * Who do we want to notify when new ibGibs arrive?\n *   * How often do we want to check external sources for latest?\n *   * When do we get to merging ibGib timelines?\n *\n * This is behavior that is somewhat taken care of, e.g. in git, with the HEAD\n * pointer for a repo.  But we're talking about here basically as a metarepo or\n * \"repo of repos\", and unlike git, we don't want our HEAD metadata living \"off\n * chain\" (outside of the DLT itself that it's modifying).  So eventually, what\n * we want is just like what we want with ALL ibGibs: perspective. From \"the\n * app\"'s perspective, the latest is mapped. But really, apps can't view slices\n * of ibGib graphs in all sorts of interesting ways and still be productive &\n * beneficial to the ecosystem as a whole.\n */\nexport abstract class MetaspaceBase implements MetaspaceService {\n\n    // we won't get an object back, only a DTO ibGib essentially\n    protected lc: string = `[${MetaspaceBase.name}]`;\n\n    instanceId: string = (new Date()).toUTCString();\n\n    protected _initialized: boolean = false;\n    get initialized(): boolean { return this._initialized; }\n\n    protected _initializedSubj: SubjectWitness<any> | undefined;\n    initialized$: ObservableWitness<any> | undefined;\n\n    protected _initializing: boolean = false;\n    get initializing(): boolean { return this._initializing; }\n\n    protected _latestSubj: SubjectWitness<IbGibTimelineUpdateInfo> | undefined;\n    latestObs: ObservableWitness<IbGibTimelineUpdateInfo> | undefined;\n\n    /**\n     * gets the current local user space\n     */\n    async getLocalUserSpace({\n        lock = false,\n        localSpaceId,\n    }: {\n        /**\n         * If true, then we lock by bootstrap/spaceId before trying to retrieve.\n         *\n         * @default true\n         */\n        lock?: boolean,\n        /**\n         * If provided, will look for the space via this id in the bootstrap ibgib.\n         * If not provided, will use the bootstrap ibgib's default spaceId.\n         */\n        localSpaceId?: SpaceId,\n    }): Promise<IbGibSpaceAny | undefined> {\n        const lc = `${this.lc}[${this.getLocalUserSpace.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n\n            // if we're not explicit with skipLock, go by platform\n            // we only need to lock when doing the web, because we could\n            // have multiple tabs open.\n            lock ??= false;\n            // if (lock === undefined) {\n            //   if (!this._platform) { this._platform = Capacitor.getPlatform(); }\n            //   if (logalot) { console.log(`${this.lc} platform: ${this._platform}`); }\n            //   lock = this._platform === 'web';\n            // }\n\n            const bootstrapIbGib =\n                await getValidatedBootstrapIbGib({ zeroSpace: this.zeroSpace }) ?? undefined;\n\n            const localSpace =\n                await getLocalSpace<IbGibSpaceAny>({\n                    zeroSpace: this.zeroSpace,\n                    bootstrapIbGib,\n                    lock,\n                    callerInstanceId: this.instanceId,\n                    localSpaceId,\n                    fnDtoToSpace: (spaceDto: IbGib_V1) => this.metaspaceFactory.fnDtoToSpace!(spaceDto),\n                    localSpaceCacheSvc: this.cacheSvc,\n                });\n\n            return localSpace;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * gets all local user spaces known in bootstrap ibgib, according to\n     * spaceIds property\n     *\n     * (`bootstrapIbGib.data[BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY]` atow)\n     *\n     * ## example bootstrap ibgib atow\n     *\n      ```json\n      {\n          \"ib\":\"bootstrap\",\n          \"gib\":\"gib\",\n          \"data\":{\n              \"defaultSpaceId\":\"d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33\",\n              \"spaceIds\":[\"d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33\"]\n          },\n          \"rel8ns\":{\n              \"d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33\":[\n                  \"witness space IonicSpace_V1 oij d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33^B336251655E8C56B38E9E86F20E0E42E6C153785F1A0A798ADE6916E71CF055B\"\n              ]\n          }\n      }\n      ```\n     *\n     * so this enumerates `data.spaceIds` and gets the corresponding addrs in the `rel8ns`.\n     * it then gets the space ibgibs themselves via the local zero space.\n     *\n     * @returns array of known local user spaces\n     *\n     * @throws if no local user spaces found (there should be at least one atow i think)\n     */\n    async getLocalUserSpaces({\n        lock = false,\n    }: {\n        /**\n         * If true, then we lock by bootstrap/spaceId before trying to retrieve.\n         *\n         * @default true\n         */\n        lock?: boolean,\n    }): Promise<IbGibSpaceAny[]> {\n        const lc = `${this.lc}[${this.getLocalUserSpaces.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n\n            const localSpaces: IbGibSpaceAny[] = [];\n\n            // if we're not explicit with skipLock, go by platform\n            // we only need to lock when doing the web, because we could\n            // have multiple tabs open.\n            lock ??= false;\n            // if (lock === undefined) {\n            //   if (!this._platform) { this._platform = Capacitor.getPlatform(); }\n            //   if (logalot) { console.log(`${this.lc} platform: ${this._platform}`); }\n            //   lock = this._platform === 'web';\n            // }\n\n            const bootstrapIbGib =\n                await getValidatedBootstrapIbGib({ zeroSpace: this.zeroSpace });\n\n            // #region validate bootstrapIbGib\n            if (!bootstrapIbGib) { throw new Error(`(UNEXPECTED) bootstrapIbGib falsy (E: fff2de921a3ee56a1d70e4ac320e4122)`); }\n            if (!bootstrapIbGib.data) { throw new Error(`(UNEXPECTED) bootstrapIbGib data falsy (E: 7f9d08050f214078b2f85dd2ed47e005)`); }\n            if (!bootstrapIbGib.data[BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY]) { throw new Error(`(UNEXPECTED) bootstrapIbGib data invalid. data[${BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY}] falsy (E: 37614e2e8f914d6ab7c605cf064a80d2)`); }\n            if (bootstrapIbGib.data[BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY].length === 0) { throw new Error(`(UNEXPECTED) bootstrapIbGib data invalid. data[${BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY}] length === 0 (E: d57691d17e6b4d7ea3a8fed36c0f47e5)`); }\n            // #endregion validate bootstrapIbGib\n\n            const localSpaceIds = bootstrapIbGib.data[BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY];\n\n            for (let i = 0; i < localSpaceIds.length; i++) {\n                const localSpaceId = localSpaceIds[i];\n                if (!localSpaceId) { throw new Error(`(UNEXPECTED) localSpaceId falsy (E: 582c520897f5355d642229eae122ac22)`); }\n\n                const localSpace =\n                    await getLocalSpace<IbGibSpaceAny>({\n                        zeroSpace: this.zeroSpace,\n                        bootstrapIbGib,\n                        lock,\n                        localSpaceId,\n                        callerInstanceId: this.instanceId,\n                        fnDtoToSpace: (spaceDto: IbGib_V1) => this.metaspaceFactory.fnDtoToSpace!(spaceDto),\n                        // fnDtoToSpace: (spaceDto: IbGib_V1) => {\n                        //   return Promise.resolve(\n                        //     NodeFilesystemSpace_V1.createFromDto(spaceDto as IbGib_V1<NodeFilesystemSpaceData_V1, NodeFilesystemSpaceRel8ns_V1>)\n                        //   );\n                        // },\n                        localSpaceCacheSvc: this.cacheSvc,\n                    });\n\n                localSpaces.push(localSpace);\n            }\n\n            return localSpaces;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    abstract get zeroSpace(): IbGibSpaceAny;\n    // {\n    //     const lc = `${this.lc}[get zeroSpace]`;\n    //     if (!this._zeroSpace) { throw new Error(`this._zeroSpace falsy. should have been created on this.initialize (E: e723177fd2a74e25eb25e2299dfa4d23)`); }\n    //     return this._zeroSpace;\n    // }\n\n    // protected _localUserSpaceCurrentRoot: IbGib_V1<RootData> | undefined;\n\n    /**\n     * Just to prevent plaintext passwords from just sitting in memory,\n     * this is a slight layer of indirection for caching.\n     */\n    protected passwordCache: { [addr: string]: TempCacheEntry } = {};\n\n    // protected fnPromptSecret: (space: IbGibSpaceAny) => Promise<IbGib_V1 | undefined>;\n    // protected fnPromptEncryption: (space: IbGibSpaceAny) => Promise<IbGib_V1 | undefined>;\n    // protected fnPromptOuterSpace: (space: IbGibSpaceAny) => Promise<IbGib_V1 | undefined>;\n    // protected fnPromptUpdatePic: (space: IbGibSpaceAny, picIbGib: PicIbGib_V1) => Promise<UpdatePicPromptResult | undefined>;\n    // protected fnPromptUpdateComment: (space: IbGibSpaceAny, commentIbGib: CommentIbGib_V1) => Promise<UpdateCommentPromptResult | undefined>;\n    // fnPromptRobbot: ((space: IbGibSpaceAny, ibGib: RobbotIbGib_V1) => Promise<RobbotPromptResult | undefined>) | undefined = undefined;\n    // fnPromptApp: ((space: IbGibSpaceAny, ibGib: AppIbGib_V1) => Promise<AppPromptResult | undefined>) | undefined = undefined;\n\n    protected _syncing: boolean = false;\n    /**\n     * should only syncIbGibs when not already syncing.\n     */\n    get syncing(): boolean {\n        return this._syncing;\n    }\n\n    protected sagaInfoMap: { [sagaId: string]: SyncSagaInfo } = {};\n\n    /**\n     * unique set of tjp addresses that will auto sync to sync spaces.\n     */\n    protected _alwaysAutosyncTjpAddrsCache = new Set<TjpIbGibAddr>();\n\n    // /**\n    //  * Cached platform value via `Capacitor.getPlatform()`.\n    //  */\n    // protected _platform: string;\n\n    /**\n     * Hmm, hacky way of tracking if we're prompt the user for something.\n     * We don't want to prompt while we're already prompting, and this\n     * is a straight-forward approach.\n     *\n     * @see {@link getPasswordForSecrets}\n     */\n    protected isPrompting: boolean = false;\n\n    // #region sync uuids\n    /**\n     * getUUID is async. there are many times we want a throwaway id\n     * synchronously. So we'll prepopulate them here.\n     */\n    protected _precalculatedIds: string[] = [];\n    public getUUIDSync(): string {\n        const lc = `${this.lc}[${this.getUUIDSync.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            const id = this._precalculatedIds.pop();\n            if (!id) { throw new Error(`no precalculated ids? (E: 14915489b21d031ee9ca695737ac6923)`); }\n            if (this._precalculatedIds.length < 100) {\n                this.precalculateSomeUUIDsPlease(); // spins off\n                // only a race condition if we're consuming sync ids\n                // in a tight loop...\n            }\n            return id;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n    async precalculateSomeUUIDsPlease(): Promise<void> {\n        const lc = `${this.lc}[${this.precalculateSomeUUIDsPlease.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            const ids: string[] = [];\n            for (let i = 0; i < 500; i++) {\n                const id = await getUUID();\n                ids.push(id);\n            }\n            this._precalculatedIds = ids;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n    async initializeObservables(): Promise<void> {\n        const lc = `${this.lc}[${this.initializeObservables.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: f5dc6d6352eaf2f41809ddec76ea5923)`); }\n\n            // initialized\n            this._initializedSubj = await newupSubject({ replay: true });\n            this.initialized$ = this._initializedSubj.asObservable();\n\n            // latestObs\n            this._latestSubj = await newupSubject<IbGibTimelineUpdateInfo>();\n            this.latestObs = this._latestSubj.asObservable();\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n    // #endregion sync uuids\n\n    protected metaspaceFactory: MetaspaceFactory = {};\n\n    /**\n     * used in alerting user of things... carryover of mvp. should be in initialize\n     */\n    getFnAlert: (() => (arg: { title: string, msg: string, }) => Promise<void>) | undefined;\n    /**\n     * used in prompting user for passwords... carryover of mvp. should be in initialize\n     */\n    getFnPrompt: (() => ((arg: { title: string, msg: string }) => Promise<string>)) | undefined;\n    /**\n     * used in prompting user for passwords... carryover of mvp. should be in initialize\n     */\n    getFnPromptPassword: (() => (title: string, msg: string) => Promise<string | null>) | undefined;\n\n    constructor(\n        protected cacheSvc: IbGibCacheService | undefined,\n    ) {\n        const lc = `${this.lc}[ctor]`;\n        if (logalot) {\n            console.log(`${lc}${GLOBAL_TIMER_NAME}`);\n            console.timeLog(GLOBAL_TIMER_NAME);\n            console.log(`${lc} created. (I: 5fe7af9fccc2488282eecc8255729cec)`);\n        }\n    }\n\n    protected async initializeMetaspaceFactory({ metaspaceFactory }: { metaspaceFactory: MetaspaceFactory }): Promise<void> {\n        const lc = `[${this.initializeMetaspaceFactory.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 0b84dfb68c1e89e0af880d4461fe4b23)`); }\n            this.metaspaceFactory = metaspaceFactory;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    async initialize({\n        spaceName,\n        metaspaceFactory,\n        getFnAlert,\n        getFnPrompt,\n        getFnPromptPassword,\n    }: MetaspaceInitializeOptions): Promise<void> {\n        const lc = `${this.lc}[${this.initialize.name}]`;\n        try {\n            this.instanceId = await getUUID();\n\n            if (!getFnAlert) { throw new Error(`getFnAlert required (E: c7ded289d9b6265b6d1294988faba923)`); }\n            if (!getFnPrompt) { throw new Error(`getFnPrompt required (E: cce7733db0abbf9a41fa45b6b9bf9523)`); }\n            if (!getFnPromptPassword) { throw new Error(`getFnPromptPassword required (E: cadae9f5df9a7c310e76b63cb6afb623)`); }\n            this.getFnAlert = getFnAlert;\n            this.getFnPrompt = getFnPrompt;\n            this.getFnPromptPassword = getFnPromptPassword;\n\n            let timerName: string = `${lc}[timer]`;\n            if (logalot) {\n                timerName = lc + '[timer 71cbfa]';\n                console.log(`${lc} starting timer ${timerName}`);\n                console.time(timerName);\n            }\n\n            await this.precalculateSomeUUIDsPlease();\n            await this.initializeObservables();\n            if (logalot) { console.timeLog(timerName); }\n            await this.initializeMetaspaceFactory({ metaspaceFactory: metaspaceFactory ??= {} }); // wth is this ??= ???? no way I wrote this hmm...\n\n            // local space(s)\n            await this.initializeLocalSpaces({ spaceName });\n            if (logalot) { console.timeLog(timerName); }\n\n            // flexibility for descending classes\n            await this.initializeSpecialIbGibs_required({ timerName });\n            await this.initializeSpecialIbGibs_outerspaces({ timerName });\n            await this.initializeSpecialIbGibs_other({ timerName });\n\n            if (logalot) {\n                console.timeEnd(timerName);\n                console.log(`${lc} timer ${timerName} complete.`);\n            }\n\n            this._initialized = true;\n            await this._initializedSubj!.next(ROOT);\n\n            // always log when this is initialized (not just logalot)\n            console.log(`${lc} initialized (I: e3b3a9652c09445cb055013166ff089c)`);\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    protected async initializeSpecialIbGibs_required({ timerName }: { timerName: string }): Promise<void> {\n        const lc = `[${this.initializeSpecialIbGibs_required.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 8cb7f63d766ab38885dc63d8da9cd323)`); }\n\n            await this.getSpecialIbGib({ type: \"latest\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n\n            await this.getSpecialIbGib({ type: \"roots\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n\n            await this.getSpecialIbGib({ type: \"tags\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n\n            await this.getSpecialIbGib({ type: SpecialIbGibType.aliases, initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n\n            await this.getSpecialIbGib({ type: \"robbots\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n\n            await this.getSpecialIbGib({ type: \"apps\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n\n            await this.getSpecialIbGib({ type: \"secrets\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n\n            await this.getSpecialIbGib({ type: \"encryptions\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async initializeSpecialIbGibs_outerspaces({ timerName }: { timerName: string }): Promise<void> {\n        const lc = `[${this.initializeSpecialIbGibs_outerspaces.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 4f5ca25899384ceabd65e30cdf58f889)`); }\n\n            await this.getSpecialIbGib({ type: \"outerspaces\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n\n            await this.getSpecialIbGib({ type: \"autosyncs\", initialize: true });\n            if (logalot) { console.timeLog(timerName); }\n            await this.loadAutoSyncs();\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async initializeSpecialIbGibs_other({ timerName }: { timerName: string }): Promise<void> {\n        const lc = `[${this.initializeSpecialIbGibs_other.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 3cad0b16f5dac3686929dd1923ee3623)`); }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Make sure we have a bootstrapped space. This is like a node...kinda in peer\n     * to peer systems.\n     *\n     * For all intents and purposes here to begin with, I'm using this initially\n     * as where to put the settings ibGib that will contain pointers for this app, be it an\n     * ionic android/web app or a browser extension. This is because the initial\n     * intent of doing the spaces, besides it being necessary for the distributed\n     * nature of the architecture, is to obviate the use of ionic Storage.\n     * That is currently where we are storing things like the pointers to special\n     * ibGibs like tags^ibgib, roots ibgibs, etc.\n     */\n    protected async initializeLocalSpaces({\n        spaceName,\n    }: {\n        spaceName: string | undefined,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.initializeLocalSpaces.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n\n            // we're going to use the default zerospace first to find/load the actual user's space (if it exists)\n            let zeroSpace = this.zeroSpace;\n            if (!zeroSpace.gib) {\n                zeroSpace.gib = await getGib({ ibGib: zeroSpace, hasTjp: false });\n            }\n\n            if (logalot) { console.log(`${lc} getting bootstrap ibgib (I: a4ad1cfd5c6f895e879d9e6a5f607b22)`); }\n            // first call without locking, because we just want to see if it exists.\n            // note that because of race conditions, this may be out of date though.\n            const bootstrapAddr = BOOTSTRAP_IBGIB_ADDR;\n            let bootstrapIbGib = await getValidatedBootstrapIbGib({ zeroSpace });\n            if (bootstrapIbGib) {\n                // re-get it using locking to ensure we've gotten the correct one.\n                if (logalot) { console.log(`${lc} getting bootstrap ibgib with locking from zero space...`) }\n                bootstrapIbGib = await execInSpaceWithLocking<BootstrapIbGib>({\n                    space: zeroSpace,\n                    scope: bootstrapAddr,\n                    secondsValid: DEFAULT_SECONDS_VALID_LOCAL,\n                    fn: async () => {\n                        const bootstrapIbGib = await getValidatedBootstrapIbGib({ zeroSpace });\n                        if (!bootstrapIbGib) { throw new Error(`failed to get validated bootstrapIbGib (E: a4318a8183c3d8979981c29bd4ecb223)`); }\n                        return bootstrapIbGib;\n                    },\n                    callerInstanceId: this.instanceId,\n                });\n                if (logalot) { console.log(`${lc} got bootstrap ibgib with locking from zero space.`) }\n            } else {\n                if (logalot) { console.log(`${lc} getting from default space...not found. bootstrap space not found. will create... (I: 3170ac1a310d41f29f2b2b075cde6bdb)`); }\n                // bootstrap space ibgib not found, so first run probably for user.\n                // so create a new bootstrapGib and user space\n                await this.createLocalSpaceAndUpdateBootstrap({\n                    zeroSpace,\n                    allowCancel: false,\n                    createBootstrap: true,\n                    spaceName,\n                });\n            }\n\n        } catch (error) {\n            if (logalot) { console.log(`${lc} getting from default space...not found. bootstrap space not found. (E: 617bb62c3b6c4c01a5faec7f06c719fd)`); }\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #region create functions\n\n    /**\n     * wrapping dispatch factory function for creating local spaces.  If a factory\n     * functionis provided, will use that. If not, then will use\n     * this.fnDefaultLocalSpaceFactory function. Ifthat is also falsy, then this\n     * will default to the NodeFSSpace factory function\n     * `fnCreateNewLocalSpace_NodeFSSpace`.\n     *\n     * @returns newly created local space, or undefined if there was a problem.\n     */\n    createNewLocalSpace({\n        opts,\n        fnLocalSpaceFactory,\n    }: {\n        opts: CreateLocalSpaceOptions;\n        fnLocalSpaceFactory?: LocalSpaceFactoryFunction;\n    }): Promise<IbGibSpaceAny | undefined> {\n        const lc = `[${this.createNewLocalSpace.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: ac652df9d652459d98832be8483544d1)`); }\n            if (!opts) { throw new Error(`opts required (E: f1d50207b35c96985ba6c2e1a18a4e23)`); }\n            if (!opts.getFnPrompt) {\n                if (logalot) { console.log(`${lc} incoming opts getFnPrompt falsy. using this.getFnPrompt (I: 1f331752ac81ffc48e2da0b27dafba23)`); }\n                opts.getFnPrompt = this.getFnPrompt!;\n            }\n            fnLocalSpaceFactory ??= this.metaspaceFactory.fnDefaultLocalSpaceFactory;\n            if (!fnLocalSpaceFactory) {\n                throw new Error(`neither fnLocalSpaceFactory nor this.fnDefaultLocalSpaceFactory provided (E: 5142df9dbae63fd0ffef8165782dc423)`);\n            }\n            return fnLocalSpaceFactory(opts);\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    async createLocalSpaceAndUpdateBootstrap({\n        zeroSpace,\n        allowCancel,\n        createBootstrap,\n        spaceName,\n        getFnPrompt,\n    }: {\n        zeroSpace: IbGibSpaceAny,\n        allowCancel: boolean,\n        createBootstrap: boolean,\n        spaceName: string | undefined,\n        getFnPrompt?: () => ((arg: { title: string, msg: string }) => Promise<string>),\n    }): Promise<IbGibSpaceAny | undefined> {\n        const lc = `${this.lc}[${this.createLocalSpaceAndUpdateBootstrap.name}]`;\n        try {\n            let newLocalSpace: IbGibSpaceAny | undefined;\n\n            // first create the space\n            if (allowCancel) {\n                newLocalSpace = await this.createNewLocalSpace({\n                    opts: {\n                        allowCancel, spaceName, logalot, getFnPrompt: getFnPrompt ?? this.getFnPrompt!,\n                    },\n                });\n                if (!newLocalSpace) {\n                    // cancelled\n                    return undefined; /* <<<< returns early */\n                }\n            } else {\n                // can't cancel (first run of app? not applicable i.e. testing?)\n                do {\n                    newLocalSpace = await this.createNewLocalSpace({\n                        opts: {\n                            allowCancel, spaceName, logalot,\n                            getFnPrompt: getFnPrompt ?? this.getFnPrompt!,\n                        }\n                    });\n                } while (!newLocalSpace)\n            }\n\n            // create bootstrap if needed\n            // (bootstrap will be updated later in this function also)\n            if (createBootstrap) {\n                if (logalot) { console.log(`${lc} creating new bootstrap ibgib (I: ecc58dd4af21a0c69a16b3d71dad9c22)`); }\n                await updateBootstrapIbGib({\n                    space: newLocalSpace,\n                    zeroSpace,\n                    setSpaceAsDefault: true,\n                    createIfNotFound: true,\n                });\n            }\n\n            /**\n             * this is the put arg used in both put calls to zero space and new\n             * local space.\n             */\n            const argPutUserSpace = await zeroSpace.argy({\n                ibMetadata: getSpaceArgMetadata({ space: newLocalSpace }),\n                argData: {\n                    cmd: 'put',\n                    ibGibAddrs: [getIbGibAddr({ ibGib: newLocalSpace })],\n                },\n                ibGibs: [newLocalSpace],\n            });\n\n            // save the localSpace in zeroSpace\n            if (logalot) { console.log(`${lc} save the localSpace in default zero space (I: 1b34fb9f548042ab9d9ae0619377e370)`); }\n            const resZeroSpace = await zeroSpace.witness(argPutUserSpace);\n            if (resZeroSpace?.data?.success) {\n                if (logalot) { console.log(`${lc} default zero space witnessed the user space (I: b6314ea887d34609904db3bb76ae2f9b)`); }\n            } else {\n                throw new Error(`${resZeroSpace?.data?.errors?.join('|') || \"There was a problem with zeroSpace witnessing the new localSpace (E: b952e888a4954cc5b671034b8384e750)\"}`);\n            }\n\n            // save the localSpace in its own space(?)\n            if (logalot) { console.log(`${lc} save the new localSpace in its own space (I: e1f520f2cc614b1fa9c1ebd1c4dd6957)`); }\n            const resPutUserSpaceInUserSpace = await newLocalSpace.witness(argPutUserSpace);\n            if (resPutUserSpaceInUserSpace?.data?.success) {\n                // we now have saved the localSpace ibgib \"in\" its own space.\n                // but atow, this does NOT change the space's gib hash, so no\n                // need to update the space\n                if (logalot) { console.log(`${lc} user space witnessed itself`); }\n            } else {\n                throw new Error(`${resPutUserSpaceInUserSpace?.data?.errors?.join('|') || \"There was a problem with localSpace witnessing itself. (E: 33d4b1ffcca64160afe67046531958b5)\"}`);\n            }\n\n            // update the bootstrap ibgib to point to the new local space\n            await updateBootstrapIbGib({\n                space: newLocalSpace,\n                zeroSpace: this.zeroSpace,\n            });\n\n            return newLocalSpace;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            const alert = this.getFnAlert!();\n            alert({ title: 'failed', msg: `failed to initialize the local space. error: ${error.message}` });\n            throw error;\n        }\n    }\n\n    async createTagIbGib({\n        text,\n        icon,\n        description,\n        space,\n    }: {\n        text: string,\n        icon?: string,\n        description?: string,\n        space?: IbGibSpaceAny,\n    }): Promise<{ newTagIbGib: TagIbGib_V1, newTagsAddr: string }> {\n        const lc = `${this.lc}[${this.createTagIbGib.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (E: 18f846b645124210a2ff1611641a8daf)`); }\n\n            return createTagIbGibAndSundry({\n                text,\n                icon,\n                description,\n                space,\n                zeroSpace: this.zeroSpace,\n                fnBroadcast: (x) => this.fnBroadcast(x),\n                fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n            });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    async trash({\n        ibGib_Context,\n        rel8nName_Context,\n        addr,\n        space,\n    }: {\n        ibGib_Context: IbGib_V1,\n        rel8nName_Context: IbGibAddr,\n        addr: IbGibAddr,\n        space?: IbGibSpaceAny,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.trash.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 4cf73be6e3294124a78a4a45368bfbcc)`); }\n            if (!ibGib_Context) { throw new Error(`ibGib_Context required (E: 09dd5e5a9f784953a42d70b1827ba442)`); }\n            if (!rel8nName_Context) { throw new Error(`rel8nName_Context required (E: cb6edaaac586773b08fd18855fc11322)`); }\n            if (!addr) { throw new Error(`addr required (E: 14f27805749c499098cebc0b1b11bc57)`); }\n\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (E: f81574e3437a4b88acd044b2abdc1ae4)`); }\n\n            await trash({\n                ibGib_Context,\n                rel8nName_Context,\n                addr,\n                space,\n                zeroSpace: this.zeroSpace,\n                fnBroadcast: (x) => this.fnBroadcast(x),\n                fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n            });\n            // Toast.show({ text: `trashed '${addr.slice(0, 32)}...'`, duration: \"long\" }); // spins off...\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    async archive({\n        ibGib_Context,\n        rel8nName_Context,\n        addr,\n        space,\n    }: {\n        ibGib_Context: IbGib_V1,\n        rel8nName_Context: IbGibAddr,\n        addr: IbGibAddr,\n        space?: IbGibSpaceAny,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.archive.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 785b44dbb7b048cb8c210a907b73b4c8)`); }\n            if (!ibGib_Context) { throw new Error(`ibGib_Context required (E: dc277b47aa4f42118ad14bfc817bf1d5)`); }\n            if (!rel8nName_Context) { throw new Error(`rel8nName_Context required (E: 87bd7ffa820645e9bdfb17fc726249ba)`); }\n            if (!addr) { throw new Error(`addr required (E: f6ce4e1325c84aa9b3da31c5b9dcc787)`); }\n\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (E: d6e0b1618eec400e820de6ac37491d39)`); }\n\n            await archive({\n                ibGib_Context,\n                rel8nName_Context,\n                addr,\n                space,\n                zeroSpace: this.zeroSpace,\n                fnBroadcast: (x) => this.fnBroadcast(x),\n                fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n            });\n\n            // Toast.show({ text: `archived '${addr.slice(0, 32)}...'`, duration: \"long\" }); // spins off...\n            if (logalot) { console.log(`${lc} archived '${addr.slice(0, 32)}...' (I: 767b06c8cadd58c618924f0cd98a1723)`); }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #endregion\n\n    /**\n     * Gets a config addr from the current space via the given key\n     * as the space's rel8n name.\n     *\n     * For example, for `key = tags`, a space may look like:\n     *\n     * ```json\n     * {\n     *    ib: space xyz,\n     *    gib: e89ff8a1c4954db28432007615a78952,\n     *    rel8ns: {\n     *      past: [space xyz^21cb29cc353f45a491d2b49ff2f130db],\n     *      ancestor: [space^gib],\n     *      tags: [tags^99b388355f8f4a979ca30ba284d3a686], // <<< rel8n with name specified by key\n     *    }\n     * }\n     * ```\n     *\n     * @param key config key\n     * @returns addr in config if exists, else undefined\n     */\n    async getConfigAddr({\n        key,\n        space,\n    }: {\n        key: string,\n        space?: IbGibSpaceAny,\n    }): Promise<string | undefined> {\n        const lc = `${this.lc}[${this.getConfigAddr.name}](${key})`;\n        try {\n            if (logalot) { console.log(`${lc} getting...`) }\n\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and could not get local space. (E: b6e7fcc09c6244b99b2e6e6ece398db0)`); }\n\n            return getConfigAddr({ key, space });\n\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return undefined;\n        }\n    }\n\n    fnUpdateBootstrap = async (newSpace: IbGibSpaceAny) => {\n        // const space = await this.getLocalUserSpace({}); // cruft/wasted call?\n        await updateBootstrapIbGib({ space: newSpace, zeroSpace: this.zeroSpace });\n    }\n\n    fnBroadcast = (info: IbGibTimelineUpdateInfo) => {\n        // if (!getIbAndGib({ibGibAddr: info.latestAddr}).gib?.includes('.')) {\n        // need to know why tjp's continue to get published as the latest addrs\n        // }\n        // this._latestSubj.next({tjpAddr, latestAddr: ibGibAddr, latestIbGib: ibGib});\n        // let gib = getIbAndGib({ibGibAddr: info.latestAddr}).gib;\n        this._latestSubj!.next(info); // spins off\n    }\n\n    /**\n     * Takes the given `key`, which should be unique in the given space (or\n     * zerospace), and uses that to persist the given `addr` in that space.\n     *\n     * # notes\n     *\n     * configuration is stored in \"special\" ibgibs, and so we need only to persist\n     * the address of that configuration.\n     */\n    async setConfigAddr({\n        key,\n        addr,\n        space,\n    }: {\n        key: string,\n        addr: string,\n        space?: IbGibSpaceAny,\n    }): Promise<IbGibSpaceAny> {\n        const lc = `${this.lc}[${this.setConfigAddr.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: 2149c59ebd584a118304dd54656aa800)`); }\n\n            return await setConfigAddr({\n                key, addr, space, zeroSpace: this.zeroSpace,\n                fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n            });\n\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    async getCurrentRoot({\n        space,\n    }: {\n        space?: IbGibSpaceAny,\n    }): Promise<IbGib_V1<RootData> | undefined> {\n        const lc = `${this.lc}[${this.getCurrentRoot.name}]`;\n\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: 1f4dc5e9560341a993bf0b28accd75fe)`); }\n\n            while (this.initializing) {\n                if (logalot) { console.log(`${lc} hacky wait while initializing ibgibs service (I: 5fd759510e584cb69b232259b891cca1)`); }\n                await delay(100);\n            }\n            const roots = await this.getSpecialIbGib({ type: \"roots\", space });\n            if (!roots) { throw new Error(`Roots not initialized. (E: e7712dc3d183487e98cd44a2b4324bc2)`); }\n            if (!roots.rel8ns) { throw new Error(`Roots not initialized properly. No rel8ns. (E: 689f47f5d1da4a868d1c1ddd2ff13e17)`); }\n            if (!roots.rel8ns.current) { throw new Error(`Roots not initialized properly. No current root. (E: 962acd3f60474a329bfbd7682c003916)`); }\n            if (roots.rel8ns.current.length === 0) { throw new Error(`Invalid Roots: empty current root rel8n. (E: fbdc13c157514efa86ade1bf9a38bbd6)`); }\n            if (roots.rel8ns.current.length > 1) { throw new Error(`Invalid Roots: multiple current roots selected. (E: 370fe6e3920a4a1299f879e6fcbbc448)`); }\n\n            const currentRootAddr = roots.rel8ns.current[0]!;\n            const resCurrentRoot =\n                await this.get({ addr: currentRootAddr, space });\n            if (resCurrentRoot.ibGibs?.length === 1) {\n                return resCurrentRoot.ibGibs![0] as IbGib_V1<RootData>;\n            } else {\n                throw new Error(`could not get current root. addr: ${currentRootAddr} (E: 69de35c5f71e45a1a5d83228e136642b)`);\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return undefined;\n        }\n    }\n\n    async setCurrentRoot({\n        root,\n        space,\n    }: {\n        root: IbGib_V1<RootData>,\n        space?: IbGibSpaceAny,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.setCurrentRoot.name}]`;\n        try {\n            if (!root) { throw new Error(`root required.`); }\n\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: 222a3f5b39fc47ccb2a4aa3ddcd49969)`); }\n\n            return setCurrentRoot({\n                root,\n                space,\n                zeroSpace: this.zeroSpace,\n                fnBroadcast: (x) => this.fnBroadcast(x),\n                fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n            });\n\n            // how to let others know roots has changed?\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Every tjp should be related to one of the roots in a space.\n     *\n     * You should NOT relate every ibgib frame of a given ibGib.\n     */\n    async rel8ToCurrentRoot({\n        ibGib,\n        linked,\n        rel8nName,\n        space,\n    }: {\n        ibGib: IbGib_V1,\n        linked?: boolean,\n        rel8nName?: string,\n        space?: IbGibSpaceAny,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.rel8ToCurrentRoot.name}]`;\n\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: cbc4e519414a405eab7fe470eadbf8f0)`); }\n\n            return rel8ToCurrentRoot({\n                ibGib,\n                linked,\n                rel8nName,\n                space,\n                zeroSpace: this.zeroSpace,\n                fnBroadcast: (x) => this.fnBroadcast(x),\n                fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n            });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return;\n        }\n    }\n\n    /**\n     * rel8s given ibgibs to special ibgib.\n     * @see {@link rel8ToSpecialIbGib}\n     * @returns new special ibgib addr\n     */\n    async rel8ToSpecialIbGib(opts: {\n        type: SpecialIbGibType,\n        rel8nName: string,\n        /**\n         * multiple ibgibs to rel8\n         */\n        ibGibsToRel8?: IbGib_V1[],\n        /**\n         * multiple ibgibs to UNrel8.\n         * YOU CANNOT SET BOTH {@link ibGibsToUnRel8} AND {@link addrsToUnRel8}\n         * There is no technical reason for this, I'm just too tired to implement\n         * yagni overhead.\n         * @see {@link addrsToUnRel8}\n         */\n        ibGibsToUnRel8?: IbGib_V1[],\n        /**\n         * alternatively just specify addrs to unrel8.\n         * YOU CANNOT SET BOTH {@link ibGibsToUnRel8} AND {@link addrsToUnRel8}\n         * There is no technical reason for this, I'm just too tired to implement\n         * yagni overhead.\n         * @see {@link ibGibsToUnRel8}\n         */\n        addrsToUnRel8?: IbGibAddr[],\n        linked?: boolean,\n        /**\n         * Clears out the special.rel8ns.past array to an empty array.\n         *\n         * {@see deletePreviousSpecialIbGib} for driving use case.\n         */\n        severPast?: boolean,\n        /**\n         * Deletes the previous special ibGib.\n         *\n         * ## driving use case\n         *\n         * the latest ibGib is one that is completely ephemeral. It doesn't get attached\n         * to the current root, and it only has the current instance. So we don't want to\n         * keep around past incarnations.\n         */\n        deletePreviousSpecialIbGib?: boolean,\n        space?: IbGibSpaceAny,\n    }): Promise<IbGibAddr> {\n        const lc = `${this.lc}[${this.rel8ToSpecialIbGib.name}](type:${opts.type},rel8nName:${opts.rel8nName})`;\n        try {\n            let {\n                type,\n                rel8nName,\n                ibGibsToRel8,\n                ibGibsToUnRel8,\n                addrsToUnRel8,\n                linked,\n                severPast,\n                deletePreviousSpecialIbGib,\n                space,\n            } = opts;\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: af863928bbc945549ffc4dcca830a70a)`); }\n\n            // return rel8ToSpecialIbGib({\n            //     type,\n            //     rel8nName,\n            //     ibGibsToRel8,\n            //     ibGibsToUnRel8,\n            //     linked,\n            //     severPast,\n            //     deletePreviousSpecialIbGib,\n            //     space,\n            //     zeroSpace: this.zeroSpace,\n            //     fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n            //     fnBroadcast: (x) => this.fnBroadcast(x),\n            // });\n            // note: 05/2025, I had added addrsToUnRel8 to signature but didn't do this maintenance and wasted a few hours debugging this. So changing this to spread with opts so we don't have to change this if we do this again. need to keep an eye out for this in the future (personally)\n            return rel8ToSpecialIbGib({\n                ...opts,\n                space,\n                zeroSpace: this.zeroSpace,\n                fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n                fnBroadcast: (x) => this.fnBroadcast(x),\n            });\n\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Used for tracking tjpAddr -> latest ibGibAddr.\n     *\n     * Call this when you create a new ibGib.\n     *\n     * Need to put this in another service at some point, but crunch crunch\n     * like pacman's lunch.\n     */\n    async registerNewIbGib({\n        ibGib,\n        space,\n    }: {\n        ibGib: IbGib_V1,\n        space?: IbGibSpaceAny,\n    }): Promise<void> {\n        let lc = `${this.lc}[${this.registerNewIbGib.name}]`;\n        try {\n            const ibGibAddr: IbGibAddr = getIbGibAddr({ ibGib });\n            lc = `${lc}[${ibGibAddr}]`;\n\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: d7e6d609a784449087cbaf1bbfb6b0c2)`); }\n\n            if (logalot) { console.log(`${lc} starting...`); }\n\n            return registerNewIbGib({\n                ibGib,\n                space,\n                fnBroadcast: (x) => this.fnBroadcast(x),\n            });\n\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Will trigger a latest info event to be fired.\n     * @param param0\n     */\n    async pingLatest_Local({\n        ibGib,\n        tjpIbGib,\n        space,\n        useCache,\n    }: {\n        ibGib: IbGib_V1<any>,\n        tjpIbGib: IbGib_V1<any> | undefined,\n        space?: IbGibSpaceAny,\n        /**\n         * If true, then will check the latest ibgib cache first. if found, will\n         * just return that.\n         */\n        useCache: boolean,\n    }): Promise<void> {\n        let lc = `${this.lc}[${this.pingLatest_Local.name}]`;\n        if (logalot) { console.log(`${lc} starting...`); }\n        try {\n            if (!ibGib) {\n                if (logalot) { console.log(`${lc} ibGib falsy.`); }\n                return; /* <<<< returns early */\n            }\n            if (isPrimitive({ ibGib })) {\n                console.warn(`${lc} tried to ping latest for primitive. returning early... (W: 06c50cfe028cc04cca67e97a48e6fe22)`);\n                return; /* <<<< returns early */\n            }\n\n            if (ibGib.ib.startsWith(`witness space IonicSpace_V1`)) {\n                // pinging a local user space, which for better or worse, does not\n                // have a tjp (nor is it kept up to date via the latest index).\n                // I can't remember, but I think there was a reason for the last bit,\n                // but I probably should have given it a tjp. Anyway, the latest\n                // \"index\" for local spaces is in the bootstrap. (Also the space is\n                // not necessarily contained in the passed in `space` arg.)\n                const { spaceId } = parseSpaceIb({ spaceIb: ibGib.ib });\n                const latestSpace =\n                    await this.getLocalUserSpace({ localSpaceId: spaceId });\n                // if (latestSpace.gib !== ibGib.gib) { // leavin this in for now. delete after awhile of normal operation. see https://github.com/wraiford/ibgib/commit/2247235a6f25945000fef419c08d5518ba2cfb48\n                await this._latestSubj!.next({\n                    ib: 'IbGibTimelineUpdateInfo',\n                    latestIbGib: latestSpace,\n                    latestAddr: getIbGibAddr({ ibGib: latestSpace }),\n                    tjpAddr: `${ibGib.ib}^gib`\n                });\n                // }\n                return; /* <<<< returns early */\n            }\n\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) {\n                console.warn(`${lc} space falsy and localUserSpace not initialized. (W: e6708e58618947a6b66f6a49406cbf35)`);\n                return;\n            }\n\n            let latestIbGib: IbGib_V1;\n            let ibGibAddr = getIbGibAddr({ ibGib });\n            let tjpAddr: IbGibAddr;\n\n            // if (!latestIbGib || !latestAddr) {\n            // not found in cache or caller didn't allow using the cache\n            let latestAddr = await this.getLatestAddr({ ibGib, tjp: tjpIbGib, space }) ?? ibGibAddr;\n\n            // get the tjp for the rel8nName mapping, and also for some checking logic\n            if (!tjpIbGib) {\n                tjpIbGib = await this.getTjpIbGib({ ibGib, space });\n                if (!tjpIbGib) {\n                    console.warn(`${lc} tjp not found for ${ibGibAddr}? Should at least just be the ibGib's address itself. (W: 15d9c6daca7e442e968af36b4c18b8f7)`);\n                    tjpIbGib = ibGib;\n                }\n            }\n            tjpAddr = getIbGibAddr({ ibGib: tjpIbGib });\n\n            if (latestAddr === ibGibAddr) {\n                if (logalot) { console.log(`${lc} latestAddr === ibGibAddr (I: f38042421fcc3d148a26ed56651c2522)`); }\n                latestIbGib = ibGib;\n            } else {\n                if (logalot) { console.log(`${lc} later version found. ibGibAddr: ${ibGibAddr}\\nlatestAddr: ${latestAddr} (I: 53cabd1643df7d43635af642e4c90922)`); }\n                let resLatestIbGib = await this.get({ addr: latestAddr, space });\n                if (!resLatestIbGib.success || resLatestIbGib.ibGibs?.length !== 1) { throw new Error(`latest not found (E: bc54e433573a5a89c6436dc6a3b60922)`); }\n                latestIbGib = resLatestIbGib.ibGibs![0];\n\n                // if (useCache) {\n                //   // we tried to use cache but it wasn't there, so put it for the next time.\n                //   if (logalot) { console.log(`${lc} putting in getLatest cache (I: 5f264edf03940a0f7e72252fd6fe0d22)`); }\n                //   console.log(`${lc} putting in getLatest cache (I: 5f264edf03940a0f7e72252fd6fe0d22)`);\n                //   setTimeout(async () => {\n                //     await this.latestCacheSvc.put({\n                //       addr: latestAddr,\n                //       ibGib: latestIbGib,\n                //       tjpAddr,\n                //       tjpIbGib: tjpIbGib,\n                //     });\n                //   }, Math.ceil(Math.random() * 10000));\n                // }\n            }\n            // }\n\n            if (latestIbGib && latestAddr && tjpAddr) {\n                await this._latestSubj!.next({\n                    ib: 'IbGibTimelineUpdateInfo',\n                    latestIbGib,\n                    latestAddr,\n                    tjpAddr\n                });\n            } else {\n                debugger; // before error\n                throw new Error(`(UNEXPECTED) latestIbGib, latestAddr and tjpAddr should all be truthy. (E: 20e71fa1a72c45deb1dc5083903a8622)`);\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #region space facade (e.g. get, getLatest___, put, etc.)\n\n    /**\n     * Convenience function for persisting a transform result, which has\n     * a newIbGib and optionally intermediate ibGibs and/or dnas.\n     *\n     * it persists these ibgibs into the given space, else the current space.\n     */\n    async persistTransformResult({\n        resTransform,\n        force,\n        space,\n    }: {\n        resTransform: TransformResult<IbGib_V1>,\n        force?: boolean,\n        space?: IbGibSpaceAny,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.persistTransformResult.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: f8b3d06006874b479240eb45f4015628)`); }\n\n            return persistTransformResult({\n                resTransform,\n                force,\n                space,\n            });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Wrapper for retrieving ibgib from a given space, else the current space.\n     */\n    async get({\n        addr,\n        addrs,\n        isDna,\n        space,\n    }: GetIbGibOpts): Promise<GetIbGibResult> {\n        let lc = `${this.lc}[${this.get.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: 86ccdcf3417a45b4a3a8c280fb9a6df7)`); }\n\n            return getFromSpace({ addr, addrs, isDna, space });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return Promise.resolve({ errorMsg: error.message });\n        }\n    }\n\n    /**\n     * Wrapper for saving ibgib in a given space, else the current space.\n     */\n    async put({\n        ibGib,\n        ibGibs,\n        isDna,\n        force,\n        space,\n    }: PutIbGibOpts): Promise<PutIbGibResult> {\n        const lc = `${this.lc}[${this.put.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: a00eebe0e3d348d09fda62a6be486b6c)`); }\n\n            return putInSpace({ ibGib, ibGibs, isDna, force, space });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return Promise.resolve({ errorMsg: error.message });\n        }\n    }\n\n    /**\n     * Wrapper for removing ibgib from the a given space, else the current space.\n     */\n    async delete({\n        addr,\n        isDna,\n        space,\n    }: DeleteIbGibOpts): Promise<DeleteIbGibResult> {\n        const lc = `${this.lc}[${this.delete.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: b4250b0045dc40629447f2cbd162faaa)`); }\n\n            return deleteFromSpace({ addr, isDna, space });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return Promise.resolve({ errorMsg: error.message });\n        }\n    }\n\n    /**\n     * Wrapper for `getDependencyGraph` fn in `helper/space.ts`, but using\n     * `this.localUserSpace` as default space.\n     *\n     * (refactoring!)\n     *\n     * ## note on space\n     *\n     * pass in `null` for space if you want to\n     *\n     * ## warning\n     *\n     * This does not (YET) have a flag that gets the latest ibgibs for the graph.\n     * It only climbs the current graph, which may not cover all ibgibs when you\n     * deal with ibGibs with tjps (timelines). We're going to eventually\n     * combat this with auto-updating our rel8ns, but for now we're just going\n     * to earmark this for the future.\n     *\n     * todo: auto-update or better\n     *\n     * @returns map of addr => ibGib\n     */\n    async getDependencyGraph(opts: GetDependencyGraphOptions): Promise<{ [addr: string]: IbGib_V1 }> {\n        const lc = `${this.lc}[${this.getDependencyGraph.name}]`;\n        try {\n            opts.space = opts.space ?? await this.getLocalUserSpace({}) ?? null;\n            if (!opts.space) { throw new Error(`(UNEXPECTED) space falsy and localUserSpace not initialized (?) (E: e2a35a23d12d48ebadcfd4f1a396d6c1)`); }\n\n            return getDependencyGraph(opts);\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Wrapper for getting the latest addr in the given space.\n     *\n     * ## warnings\n     *\n     * * This was written early and makes many assumptions.\n     * * Meant to work with Ionic space atow.\n     *\n     * @returns latest addr in a given space (or localUserSpace) or undefined if does not exist\n     */\n    async getLatestAddr({\n        ibGib,\n        addr,\n        tjpAddr,\n        tjp,\n        space,\n    }: {\n        ibGib?: IbGib_V1<any>,\n        addr?: IbGibAddr,\n        tjpAddr?: IbGibAddr,\n        tjp?: IbGib_V1<any>,\n        space?: IbGibSpaceAny,\n    }): Promise<IbGibAddr | undefined> {\n        let lc = `${this.lc}[${this.getLatestAddr.name}]`;\n        if (logalot) { console.log(`${lc} starting...`); }\n        try {\n            if (!ibGib && !tjp && !tjpAddr && !addr) {\n                throw new Error(`ibGib && tjp && tjpAddr && addr are all falsy (E: fe725654342c4d80a33219160b5d81d3)`);\n            }\n\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: fd01bb85e91f4c54bfe8b35714d48a38)`); }\n\n            const resGetLatest = await getLatestAddrs({\n                ibGibs: ibGib ? [ibGib] : undefined,\n                addrs: addr ? [addr] : undefined,\n                tjpAddrs: tjpAddr ? [tjpAddr] : undefined,\n                tjps: tjp ? [tjp] : undefined,\n                space,\n            });\n\n            if (!resGetLatest) { throw new Error(`resGetLatest falsy (E: 3851bbe4427ae11771f222234e8c6622)`); }\n            if (!resGetLatest.data) { throw new Error(`invalid resGetLatest: data falsy (E: 134e0f1f65edc69c6951c32e00a4bb22)`); }\n            if (resGetLatest.data.success) {\n                // Should have addrs map\n                const latestAddrsMap = resGetLatest.data.latestAddrsMap;\n                if (!latestAddrsMap) {\n                    // fallback to old way just in case? Or just error.\n                    // The error I saw had latestAddrsMap but no addrs.\n                    // So we should look at the map.\n                    if (resGetLatest.data.addrs?.length === 1) {\n                        return resGetLatest.data.addrs[0];\n                    } else if (resGetLatest.data.addrsNotFound?.length === 1) {\n                        return undefined;\n                    }\n                } else {\n                    // We have the map. Ideally we want the one entry.\n                    const keys = Object.keys(latestAddrsMap);\n                    if (keys.length === 1) {\n                        return latestAddrsMap[keys[0]] || undefined;\n                    } else if (keys.length === 0) {\n                        // could be not found?\n                        if (resGetLatest.data.addrsNotFound?.length === 1) {\n                            return undefined;\n                        } else {\n                            // If we didn't find it, and success is true, maybe it's just undefined?\n                            // But usually getLatestAddrs returns map entries for found ones.\n                            return undefined;\n                        }\n                    } else {\n                        throw new Error(`(UNEXPECTED) latestAddrsMap has multiple entries? We only asked for one. (E: 790518290f6b46729017684698539222)`);\n                    }\n                }\n\n                if (resGetLatest.data.addrsErrored?.length === 1) {\n                    const emsg = resGetLatest.data.errors?.join('|') ?? \"[unspecified error(s)] (E: 24f338036aa84ac99e3c39a660207222)\";\n                    throw new Error(`resGetLatest had error(s): ${emsg}`);\n                } else {\n                    throw new Error(`unknown error, invalid resGetLatest: ${pretty(resGetLatest)} (E: 6aa5aa225ebf49b588664370cb8feb22)`);\n                }\n            } else {\n                const emsg = resGetLatest.data.errors?.join('|') ?? \"[unspecified error(s)] (E: dcd6dcd6ec052fd112a4d48f1afa2922)\";\n                throw new Error(`resGetLatest had error(s): ${emsg}`);\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Gets the tjpIbGib for the given `ibGib` in the given `space`.\n     * atow, naive must be true.\n     *\n     *\n     *\n     * @returns tjpIbGib for the given `ibGib`\n     */\n    async getTjpIbGib({\n        ibGib,\n        naive = true,\n        space,\n    }: {\n        ibGib: IbGib_V1<any>,\n        naive?: boolean,\n        space?: IbGibSpaceAny,\n    }): Promise<IbGib_V1<any> | undefined> {\n        const lc = `${this.lc}[${this.getTjpIbGib.name}]`;\n\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: 0ec806bd2c5641c4844a3698c922e1f6)`); }\n            if (!space) {\n                console.warn(`${lc} space falsy and localUserSpace not initialized.`);\n                return ibGib;\n            }\n            return getTjpIbGib({ ibGib, naive, space });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Gets one of the app's special ibGibs, e.g., TagsIbGib.\n     *\n     * When initializing tags, this will generate some boilerplate tags.\n     * I'm going to be doing roots here also, and who knows what else, but each\n     * one will have its own initialize specifics.\n     *\n     * @param initialize initialize (i.e. create) ONLY IF IbGib not found. Used for initializing app (first run).\n     *\n     * @see {@link createSpecial}\n     * @see {@link createTags}\n     */\n    async getSpecialIbGib({\n        type,\n        initialize,\n        space,\n        lock,\n        dontWarnIfNotExist,\n    }: {\n        type: SpecialIbGibType,\n        initialize?: boolean,\n        space?: IbGibSpaceAny,\n        lock?: boolean,\n        /**\n         * if true, won't warn about non-existent/non-initialized things.\n         * useful if you are just checking to see if a special ibgib exists.\n         */\n        dontWarnIfNotExist?: boolean,\n    }): Promise<IbGib_V1 | null> {\n        const lc = `${this.lc}[${this.getSpecialIbGib.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({ lock });\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: e08e85d8422e479f9d101194fd26cbda)`); }\n\n            while (this.initializing) {\n                if (logalot) { console.log(`${lc} hacky wait while initializing ibgibs service (I: 497d4becb94f4515a2ec389630420d6c)`); }\n                await delay(100);\n            }\n\n            return getSpecialIbGib({\n                type,\n                initialize,\n                space,\n                zeroSpace: this.zeroSpace,\n                fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n                fnBroadcast: (x) => this.fnBroadcast(x),\n                fnGetInitializing: () => { return this._initializing; },\n                fnSetInitializing: (value: boolean) => { this._initializing = value; },\n                dontWarnIfNotExist,\n            });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return null;\n        }\n    }\n\n    async getSpecialRel8dIbGibs<TIbGib extends IbGib_V1 = IbGib_V1>({\n        type,\n        rel8nName,\n        space,\n    }: {\n        type: SpecialIbGibType,\n        rel8nName: string,\n        space?: IbGibSpaceAny,\n    }): Promise<TIbGib[]> {\n        const lc = `${this.lc}[${this.getSpecialRel8dIbGibs.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: 476c7d7c68f34197b740be5df09238a2)`); }\n\n            return getSpecialRel8dIbGibs({ type, rel8nName, space });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    // #endregion space facade (e.g. get, getLatest___, put, etc.)\n\n    /**\n     * Feels klugy.\n     */\n    async getPasswordForSecrets({\n        secretIbGibs,\n        fnPromptPassword,\n        dontPrompt,\n        checkCacheFirst,\n        cacheAfter,\n    }: {\n        secretIbGibs: IbGib_V1<SecretData_V1>[],\n        fnPromptPassword: (title: string, msg: string) => Promise<string | null>,\n        /**\n         * i think this was added because I didn't want it prompting in the\n         * background in case we were trying to sync in the background and the\n         * user hadn't entered the password (and cached it).\n         */\n        dontPrompt?: boolean,\n        checkCacheFirst?: boolean,\n        cacheAfter?: boolean,\n    }): Promise<string | null> {\n        const lc = `${this.lc}[${this.getPasswordForSecrets.name}]`;\n        /** Flag that we'll check in finally clause */\n        let erroredDueToPromptTimeout = false;\n        try {\n            let tries = 0;\n            while (this.isPrompting) {\n                if (logalot) { console.log(`${lc} hacky wait while already prompting (I: 852007c8549d42c096defe0105b5e2e6)`); }\n                await delay(100);\n                tries++;\n                if (tries > 1000) {\n                    erroredDueToPromptTimeout = true;\n                    throw new Error(`attempted to prompt for user password, but already prompting for quite awhile now. (E: 8bd4dc907422dd95862b2038ffe2b822)`);\n                }\n            }\n\n\n            // used if we `checkCacheFirst` AND/OR if we `cacheAfter`\n            const secretsCacheKey =\n                secretIbGibs.map(ibGib => getIbGibAddr({ ibGib })).join('');\n\n            if (checkCacheFirst) {\n                const cachedPassword =\n                    await this.getCachedSecretPassword({ cacheKey: secretsCacheKey });\n\n                if (cachedPassword) {\n                    // do NOT log the actual cachedPassword!!\n                    if (logalot) { console.log(`${lc} using cachedPassword.`); }\n                    return cachedPassword;\n                }\n            }\n\n            if (dontPrompt) {\n                return null; /* <<<< returns early */\n            }\n\n            // build prompt message\n            this.isPrompting = true;\n\n            let secretInfos: SecretInfo_Password[] = [];\n            for (let i = 0; i < secretIbGibs.length; i++) {\n                const secretIbGib = secretIbGibs[i];\n                if (!secretIbGib.data) { throw new Error(`invalid secretIbGib. data falsy.`); }\n                if (secretIbGib.data!.type === 'password') {\n                    const secretInfo = secretIbGib.data as SecretInfo_Password;\n                    secretInfos.push(secretInfo);\n                } else {\n                    throw new Error(`Only password secrets are implemented atm.`);\n                }\n            }\n            const separator = '-------------';\n            const secretInfosMsgBlock = secretInfos.map(secretInfo => {\n                return `name:        ${secretInfo.name}\n                description: ${secretInfo.description}\n                hint:        ${secretInfo.hint}`;\n            }).join('\\n' + separator + '\\n');\n\n            // prompt user\n            const title = `Gimme a password.`;\n            const msg =\n                `Enter the password corresponding to the following secret(s):\\n\n        ${separator}\\n\\n\n        ${secretInfosMsgBlock}\n        `;\n            let password = await fnPromptPassword(title, msg);\n\n            // cache if applicable\n            if (password && cacheAfter) {\n                await this.setCachedSecretPassword({\n                    cacheKey: secretsCacheKey,\n                    secretPassword: password,\n                });\n            }\n\n            // we're done\n            return password;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (!erroredDueToPromptTimeout) {\n                // if we errored due to prompt timeout, then some other call to this\n                // function is prompting and we don't want to turn off their flag.\n                this.isPrompting = false;\n            }\n        }\n    }\n\n    /**\n     * creates a ciphertext ibgib (stone) based on the given plaintext.\n     */\n    async getCiphertextIbGib<TEncryptionIbGib extends IbGib_V1<EncryptionData_V1>, TMetadata = any>({\n        plaintext,\n        password,\n        encryptionIbGib,\n        confirm,\n        persist,\n        ibRoot,\n        publicIbMetadata,\n        publicMetadata,\n    }: {\n        /**\n         * Um...data...to...erm...encrypt...(as a string)\n         */\n        plaintext: string,\n        /**\n         * Password to perform the encryption.\n         */\n        password: string,\n        /**\n         * Information about encryption, i.e. encryption settings.\n         */\n        encryptionIbGib: TEncryptionIbGib,\n        /**\n         * Confirms encryption succeeds by doing an immediate decrypt and checking against original data.\n         */\n        confirm?: boolean,\n        /**\n         * If true, will persist the ibgib\n         */\n        persist?: boolean,\n        /**\n         * If you provide this, the resulting ibgib will have the following format:\n         * `${ibRoot} ${publicIbMetadata}`. Otherwise, this will default to:\n         * `ciphertext ${publicIbMetadata}`, or just `ciphertext` if\n         * `publicIbMetadata` is falsy.\n         */\n        ibRoot?: string,\n        /**\n         * If you want to include metadata in the ib itself of the\n         * ciphertext ibgib. This will of course make this metadata\n         * available without loading the full ibgib, but will increase\n         * storage size because every address linking to the ibgib will\n         * include this as well.\n         */\n        publicIbMetadata?: string,\n        /**\n         * If you want to include public, unencrypted metadata in the ibgib's\n         * data body itself.\n         */\n        publicMetadata?: TMetadata,\n    }): Promise<TransformResult<CiphertextIbGib_V1>> {\n        const lc = `${this.lc}[${this.getCiphertextIbGib.name}]`;\n        try {\n            const encryptionInfo = encryptionIbGib.data;\n            if (encryptionInfo?.method !== EncryptionMethod.encrypt_gib) {\n                throw new Error('only encrypt-gib is implemented. (E: 1d8eb1be6d3f44f0a79b498f237147e6');\n            }\n            const info: EncryptionInfo_EncryptGib = encryptionInfo;\n            const resEncrypt = await encrypt({\n                dataToEncrypt: plaintext,\n                secret: password,\n                initialRecursions: info.initialRecursions,\n                recursionsPerHash: info.recursionsPerHash,\n                salt: info.salt,\n                saltStrategy: info.saltStrategy,\n                hashAlgorithm: info.hashAlgorithm,\n                encryptedDataDelimiter: info.encryptedDataDelimiter,\n                blockMode: encryptionInfo.blockMode ? encryptionInfo.blockModeOptions : undefined,\n                indexingMode: encryptionInfo.indexingMode,\n                confirm,\n            });\n\n            if (resEncrypt.warnings?.length ?? 0 > 0) { console.warn(`${lc} warnings: ${resEncrypt.warnings!.join('\\n')}`); }\n            if (resEncrypt.errors?.length ?? 0 > 0) { throw new Error(resEncrypt.errors!.join('\\n')); }\n            if (!resEncrypt.encryptedData) { throw new Error(`encryptedData is falsy`) }\n\n            const data: CiphertextData = {\n                ciphertext: resEncrypt.encryptedData,\n                uuid: await getUUID(),\n            };\n            if (publicMetadata) { data.metadata = publicMetadata; }\n\n            const ciphertextIbGib = await constantIbGib<CiphertextData, CiphertextRel8ns>({\n                parentPrimitiveIb: ibRoot || CIPHERTEXT_ATOM,\n                ib:\n                    publicIbMetadata ?\n                        `${ibRoot || CIPHERTEXT_ATOM} ${publicIbMetadata}` :\n                        `${ibRoot || CIPHERTEXT_ATOM}`,\n                data,\n                rel8ns: undefined,\n            }) as CiphertextIbGib_V1;\n            const resTransform: TransformResult<CiphertextIbGib_V1> = {\n                newIbGib: ciphertextIbGib\n            }\n\n            if (persist) {\n                await this.persistTransformResult({ resTransform });\n            }\n\n            return resTransform;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Brings together a ciphertext and secretIbGibs to decrypt\n     * the `ciphertextIbGib.data.ciphertext`\n     * @returns plaintext string of `ciphertextIbGib.data.ciphertext`\n     */\n    async getPlaintextString({\n        ciphertextIbGib,\n        secretIbGibs,\n        fnPromptPassword,\n        dontPrompt,\n        space,\n    }: {\n        ciphertextIbGib: CiphertextIbGib_V1,\n        secretIbGibs: SecretIbGib_V1[],\n        fnPromptPassword: (title: string, msg: string) => Promise<string | null>,\n        dontPrompt?: boolean,\n        space: IbGibSpaceAny,\n    }): Promise<string> {\n        const lc = `${this.lc}[${this.getPlaintextString.name}]`;\n        try {\n            // validate\n            if ((secretIbGibs || []).length === 0) { throw new Error(`secretIbGibs required. (E: 99a605b540c54b6db4d2ffe2caeb226a)`); }\n            if (!ciphertextIbGib.data) { throw new Error(`ciphertextIbGib.data falsy (E: 598fc6473149e240a7d6916ecf642323)`); }\n            if (!ciphertextIbGib.data.ciphertext) { throw new Error(`ciphertextIbGib.data.ciphertext falsy (E: 0e764a71ec214132a5a528f17f495a7c)`); }\n            if (!ciphertextIbGib.rel8ns?.encryption) { throw new Error(`ciphertextIbGib.rel8ns.encryption falsy (E: a0b4d5d8674b4d0191fa619164153022)`) }\n            if (ciphertextIbGib.rel8ns!.encryption!.length !== 1) { throw new Error(`ciphertextIbGib.rel8ns!.encryption!.length !== 1 (E: a4a463e1ef0e45b4917eb04cb40d8173)`); }\n\n            // get corresponding encryption ibgib for encryption settings\n            const encryptionAddr = ciphertextIbGib.rel8ns!.encryption![0];\n            const resEncryption = await this.get({ addr: encryptionAddr, space });\n            if (!resEncryption.success) { throw new Error(`get encryption failed (E: feef34c05fae439c81ade7fc23037af1)`); }\n            if ((resEncryption.ibGibs || []).length !== 1) { throw new Error(`get encryption retrieved non-1 length (eesh) (E: 5d7e2023cc2b4e349574c17d5cfc8867)`); }\n            const encryptionIbGib = resEncryption.ibGibs![0] as IbGib_V1<EncryptionData_V1>;\n            if (!encryptionIbGib.data) { throw new Error(`encryptionIbGib.data falsy (E: 409a243afbf24c20987524f6588816fa)`); }\n\n            // prompt user for the password\n            const password = await this.getPasswordForSecrets({\n                secretIbGibs,\n                fnPromptPassword,\n                dontPrompt,\n                checkCacheFirst: true,\n                cacheAfter: true,\n            });\n\n            // we're about the decrypt, but maybe the data doesn't have everything.\n            // So WARN for any defaults we're using.\n            if (!encryptionIbGib.data.initialRecursions) { console.warn(`${lc} using default initialRecursions because encryptionIbGib does not state this explicitly (W: 66774cbfccd44423949d34167da6d50b)`); }\n            if (!encryptionIbGib.data.recursionsPerHash) { console.warn(`${lc} using default recursionsPerHash because encryptionIbGib does not state this explicitly (W: 29e264094f384d259319ba8587cd4f63)`); }\n            if (!encryptionIbGib.data.saltStrategy) { console.warn(`${lc} using default saltStrategy because encryptionIbGib does not state this explicitly (W: 7a5acadb8d634c7e87f62c86b57ac7a2)`); }\n            if (!encryptionIbGib.data.hashAlgorithm) { console.warn(`${lc} using default hashAlgorithm because encryptionIbGib does not state this explicitly(W: 2254db3569534b239a8c471b700c8500)`); }\n\n            const defaultIndexingMode = encryptionIbGib.data.blockMode ?\n                DEFAULT_ALPHABET_INDEXING_MODE_BLOCKMODE :\n                DEFAULT_ALPHABET_INDEXING_MODE_LEGACY;\n            if (encryptionIbGib.data.blockMode) {\n                if (!encryptionIbGib.data.blockModeOptions) { throw new Error(`invalid encryptionIbGib.data. blockMode is truthy but blockModeOptions is falsy. (E: 84bbc27a5248b7c4734a1674e41dd224)`); }\n                if (!encryptionIbGib.data.indexingMode) {\n                    console.warn(`${lc} not complete. using default indexingMode ${defaultIndexingMode} because encryptionIbGib does not state this explicitly. (W: c15797cd8d0740ea886a348c10be2e5c)`)\n                }\n            }\n\n            // do actual decryption\n            if (logalot) { console.log(`${lc} starting decrypt... (I: e14176ebc9a7470fb977d2184f1e2430)`); }\n            const timerName = 'sync_log decrypt';\n            console.time(timerName);\n            console.timeLog(timerName, 'decrypting...');\n            const resDecrypt = await decrypt({\n                encryptedData: ciphertextIbGib.data.ciphertext,\n                secret: password ?? '',\n                initialRecursions:\n                    encryptionIbGib.data.initialRecursions || DEFAULT_ENCRYPTION_INITIAL_RECURSIONS,\n                recursionsPerHash:\n                    encryptionIbGib.data.recursionsPerHash || DEFAULT_ENCRYPTION_RECURSIONS_PER_HASH,\n                salt: encryptionIbGib.data.salt,\n                saltStrategy:\n                    encryptionIbGib.data.saltStrategy || DEFAULT_ENCRYPTION_SALT_STRATEGY,\n                hashAlgorithm:\n                    encryptionIbGib.data.hashAlgorithm || DEFAULT_ENCRYPTION_HASH_ALGORITHM,\n                encryptedDataDelimiter: encryptionIbGib.data.encryptedDataDelimiter,\n                blockMode: encryptionIbGib.data.blockMode ? encryptionIbGib.data.blockModeOptions! : undefined,\n                indexingMode: encryptionIbGib.data.indexingMode || defaultIndexingMode,\n            });\n            console.timeLog(timerName, 'decrypting complete.');\n            console.timeEnd(timerName);\n            if (logalot) { console.log(`${lc} decrypt complete. (I: 15a8182230294a8a96504ba3667f039a)`); }\n            if (resDecrypt.errors?.length ?? 0 > 0) { throw new Error(resDecrypt.errors!.join('|')); }\n\n            if (!resDecrypt.decryptedData) { throw new Error(`(UNEXPECTED) resDecrypt has no errors but resDecrypt.decryptedData falsy? (E: 06e73992fb02e45e3c18db33f9a61b23)`); }\n\n            // we're done\n            return resDecrypt.decryptedData;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    // async unwrapEncryptedSyncSpace({\n    //     encryptedSpace,\n    //     fnPromptPassword,\n    //     dontPrompt,\n    //     space,\n    //     fnSpaceFactory,\n    // }: {\n    //     encryptedSpace: IbGibSpaceAny,\n    //     fnPromptPassword: (title: string, msg: string) => Promise<string | null>,\n    //     dontPrompt?: boolean,\n    //     space?: IbGibSpaceAny,\n    //     fnSpaceFactory: (syncSpaceIbGib: SyncSpaceIbGib) => Promise<IbGibSpaceAny>,\n    // }): Promise<IbGibSpaceAny> {\n    //     const lc = `${this.lc}[${this.unwrapEncryptedSyncSpace.name}]`;\n    //     try {\n    //         // validation\n    //         if (!space) { throw new Error(`space required (E: d4d3eaa2d7b9143cf1173b8ae6344c23)`); }\n    //         if (!encryptedSpace.rel8ns?.ciphertext) { throw new Error(`encryptedSpace is not a ciphertext (E: be5504a5e2b84f3eaa8fbd6e13aab659)`); }\n    //         if (encryptedSpace.rel8ns!.ciphertext!.length !== 1) { throw new Error(`only 1 ciphertext rel8n allowed... (E: e8ab2ec38ad844dfb229efc5b8981946)`); }\n\n    //         // get ciphertext ibgib\n    //         const ciphertextAddr = encryptedSpace.rel8ns!.ciphertext![0];\n    //         const resCiphertext = await this.get({ addr: ciphertextAddr, space });\n    //         if (!resCiphertext.success) { throw new Error(`get ciphertext failed (E: e58b3471c0334cd7bc626998106e6547)`); }\n    //         if ((resCiphertext.ibGibs || []).length !== 1) { throw new Error(`get ciphertext retrieved non-1 length (eesh) (E: a3a1f00e827b4f88a42b4a7433cf1065)`); }\n    //         const ciphertextIbGib = resCiphertext.ibGibs![0] as CiphertextIbGib_V1;\n\n    //         // get secrets associated with enciphered space\n    //         if (!encryptedSpace.rel8ns?.secret) { throw new Error(`!encryptionIbGib.rel8ns?.secret (E: 8bfed1541976433da9402d7d3a9138dd)`); }\n    //         const secretAddrs = encryptedSpace.rel8ns!.secret!;\n    //         const localUserSpace = await this.getLocalUserSpace({});\n    //         if (!localUserSpace) { throw new Error(`(UNEXPECTED) could not get localUserSpace? (E: 3c5687a15b3b58e3dcf1eca4f5fe5723) (E: c123b340177647968e10a6b119d84d2b)`); }\n    //         const argGetSecrets = await localUserSpace.argy({\n    //             argData: { ibGibAddrs: secretAddrs, cmd: 'get', }\n    //         });\n    //         const resSecrets = await localUserSpace.witness(argGetSecrets);\n    //         if (!resSecrets.data?.success || (resSecrets.ibGibs || []).length === 0) {\n    //             throw new Error(`couldn't get secret ibgibs (E: cb17687f842f4296a9ecf89d9a568e46)`);\n    //         }\n    //         const secretIbGibs = resSecrets.ibGibs.concat() as IbGib_V1<SecretData_V1>[];\n\n    //         // get plaintext now that we have the ciphertext ibgib and secret ibgib(s)\n    //         const plaintextString = await this.getPlaintextString({\n    //             ciphertextIbGib,\n    //             fnPromptPassword,\n    //             dontPrompt,\n    //             secretIbGibs,\n    //             space,\n    //         });\n\n    //         const syncSpaceData = JSON.parse(plaintextString) as OuterSpaceData;\n    //         if (syncSpaceData.type !== 'sync') { throw new Error(`syncSpaceData.type !== 'sync'...this is the only one implemented right now (E: 509b2373d6f8445ebe5bd6f27f62af93)`); }\n    //         if (syncSpaceData.subtype !== 'aws-dynamodb') { throw new Error(`syncSpaceData.subtype !== 'aws-dynamodb'...only one right now dude (E: b5caaf3b4c60438eb2cee58ce8e1d3f6)`); }\n\n    //         // this is the original aws only implementation. I've just added (untested)\n    //         // a quick factory function where the consumer would do the following code.\n    //         const unwrappedSpace = await fnSpaceFactory(syncSpaceData);\n    //         return unwrappedSpace;\n    //         // so we have a syncspace data (only aws-dynamodb space right now).\n    //         // load this data into a space class with behavior (not just the dto).\n    //         // const awsSpace = new AWSDynamoSpace_V1(syncSpaceData, null);\n    //         // awsSpace.gib = await getGib({ ibGib: awsSpace, hasTjp: false });\n    //         // if (logalot) { console.log(`awsSpace.gib: ${awsSpace.gib}`); }\n    //         // return awsSpace;\n\n    //     } catch (error) {\n    //         console.error(`${lc} ${error.message}`);\n    //         throw error;\n    //     }\n    // }\n\n    /**\n     * Caching user password secret in memory only.\n     *\n     * Just to prevent plaintext passwords from just sitting in memory,\n     * this is a slight layer of indirection for caching\n     *\n     * @returns user password\n     */\n    protected async getCachedSecretPassword({\n        cacheKey,\n    }: {\n        cacheKey: string,\n    }): Promise<string | undefined> {\n        const lc = `${this.lc}[${this.getCachedSecretPassword.name}]`;\n        try {\n            if (!cacheKey) { throw new Error(`secretAddr required`); }\n            let entry = this.passwordCache[cacheKey];\n            if (!entry) {\n                if (logalot) { console.log(`${lc} secretAddr not cached: ${cacheKey}`); }\n                return undefined;\n            }\n\n            // settings must match, but I'm feeling lazy on DRYing\n\n            if (logalot) { console.log(`${lc} starting decrypt...`); }\n            let resDecrypt = await decrypt({\n                encryptedData: entry.encryptedPassword,\n                secret: entry.tempMetaPassword,\n                initialRecursions: 10000,\n                recursionsPerHash: 5,\n                salt: entry.salt,\n                saltStrategy: 'appendPerHash',\n                hashAlgorithm: 'SHA-512',\n            });\n            if (logalot) { console.log(`${lc} decrypt complete.`); }\n\n            if (!resDecrypt.decryptedData) { throw new Error(`resDecrypt.decryptedData falsy`); }\n\n            return resDecrypt.decryptedData;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return undefined;\n        }\n    }\n\n    protected async setCachedSecretPassword({\n        cacheKey,\n        secretPassword,\n        force,\n    }: {\n        cacheKey: string,\n        secretPassword: string,\n        force?: boolean,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.getCachedSecretPassword.name}]`;\n        try {\n            if (!cacheKey) { throw new Error(`secretAddr required`); }\n\n            if (this.passwordCache[cacheKey]) {\n                if (force) {\n                    if (logalot) { console.log(`already cached, but force is true: ${cacheKey}`); }\n                    delete this.passwordCache[cacheKey];\n                } else {\n                    if (logalot) { console.log(`already cached: ${cacheKey}`); }\n                    return undefined;\n                }\n            }\n\n            const tempMetaPassword = await getUUID(256);\n            const salt = await getUUID();\n            // settings must match, but I'm feeling lazy on DRYing\n            let resEncrypt = await encrypt({\n                dataToEncrypt: secretPassword,\n                secret: tempMetaPassword,\n                initialRecursions: 10000,\n                recursionsPerHash: 5,\n                salt: salt,\n                saltStrategy: 'appendPerHash',\n                hashAlgorithm: 'SHA-512',\n            });\n            if (!resEncrypt.encryptedData) { throw new Error(`resEncrypt.encryptedData falsy`); }\n            const encryptedPassword = resEncrypt.encryptedData!;\n\n            let entry: TempCacheEntry =\n                { tempMetaPassword, salt, encryptedPassword, };\n\n            this.passwordCache[cacheKey] = entry;\n            if (logalot) { console.log(`${lc} entry added for ${cacheKey}.`); }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return undefined;\n        }\n    }\n\n    /**\n     * If we don't have outerspaces/cloud endpoints, we'll do that here.\n     *\n     * @returns true if creation was successfully created, else false.\n     */\n    protected async _createOuterspaceAndRequiredIbGibs({\n        space,\n        fnPromptSecret,\n        fnPromptEncryption,\n        fnPromptOuterSpace,\n    }: {\n        space: IbGibSpaceAny,\n        fnPromptSecret: (space: IbGibSpaceAny) => Promise<SecretIbGib_V1 | undefined>,\n        fnPromptEncryption: (space: IbGibSpaceAny) => Promise<EncryptionIbGib_V1 | undefined>,\n        fnPromptOuterSpace: (space: IbGibSpaceAny) => Promise<IbGibSpaceAny | undefined>,\n    }): Promise<boolean> {\n        const lc = `${this.lc}[${this._createOuterspaceAndRequiredIbGibs.name}]`;\n        try {\n            const createdSecret = await this._createSecret({ space, fnPromptSecret });\n            if (logalot) { console.log(`${lc} createdSecret: ${createdSecret} (I: 9fc011d8ecb1e10c86c86025be4d5c22)`); }\n            if (!createdSecret) { return false; } // <<<< returns early\n\n            const createdEncryption = await this._createEncryption({ space, fnPromptEncryption });\n            if (logalot) { console.log(`${lc} createdEncryption: ${createdEncryption} (I: 6796bbeb7338471e965cf1806d0dea9c)`); }\n            if (!createdEncryption) { return false; } // <<<< returns early\n\n            const createdOuterspace = await this._createOuterspace({ space, fnPromptOuterSpace });\n            if (logalot) { console.log(`${lc} createdOuterspace: ${createdOuterspace} (I: 6796bbeb7338471e965cf1806d0dea9c)`); }\n            return createdOuterspace;\n\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return false;\n        }\n    }\n\n    protected async _createSecret({\n        space,\n        fnPromptSecret,\n    }: {\n        space: IbGibSpaceAny,\n        fnPromptSecret: (space: IbGibSpaceAny) => Promise<SecretIbGib_V1 | undefined>,\n    }): Promise<boolean> {\n        const lc = `${this.lc}[${this._createSecret.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            const alert = this.getFnAlert!();\n\n            let secretIbGibs: IbGib_V1[] = await this.getSpecialRel8dIbGibs({\n                type: \"secrets\",\n                rel8nName: SECRET_REL8N_NAME,\n                space,\n            });\n            if (secretIbGibs.length === 0) {\n                await alert({\n                    title: 'first create some stuff...',\n                    msg: \"First we'll need to do a couple things, like create a secret password, an encryption setting, and a cloud endpoint.\",\n                });\n            }\n            while (secretIbGibs.length === 0) {\n                let secretIbGib = await fnPromptSecret(space);\n                if (secretIbGib === undefined) {\n                    await alert({ title: 'cancelled', msg: 'Cancelled.' });\n                    return false;\n                }\n                await this.registerNewIbGib({ ibGib: secretIbGib, });\n                await this.rel8ToSpecialIbGib({\n                    type: \"secrets\",\n                    rel8nName: SECRET_REL8N_NAME,\n                    ibGibsToRel8: [secretIbGib],\n                    space,\n                });\n                secretIbGibs = await this.getSpecialRel8dIbGibs({\n                    type: \"secrets\",\n                    rel8nName: SECRET_REL8N_NAME,\n                    space,\n                });\n            }\n            return true;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async _createEncryption({\n        space,\n        fnPromptEncryption,\n    }: {\n        space: IbGibSpaceAny,\n        fnPromptEncryption: (space: IbGibSpaceAny) => Promise<EncryptionIbGib_V1 | undefined>,\n    }): Promise<boolean> {\n        const lc = `${this.lc}[${this._createEncryption.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            const alert = this.getFnAlert!();\n\n            let encryptionIbGibs: IbGib_V1[] = await this.getSpecialRel8dIbGibs({\n                type: \"encryptions\",\n                rel8nName: ENCRYPTION_REL8N_NAME,\n                space,\n            });\n            if (encryptionIbGibs.length === 0) {\n                await alert({\n                    title: 'next create an encryption...',\n                    msg: \"Now we need to create an encryption setting. If you don't know what this is, just fill in the requirements and leave the others as defaults.\",\n                });\n            }\n            while (encryptionIbGibs.length === 0) {\n                let encryptionIbGib = await fnPromptEncryption(space);\n                if (encryptionIbGib === undefined) {\n                    await this.getFnAlert!()({ title: 'cancelled', msg: 'Cancelled.' });\n                    return false;\n                }\n                await this.registerNewIbGib({ ibGib: encryptionIbGib, space });\n                await this.rel8ToSpecialIbGib({\n                    type: \"encryptions\",\n                    rel8nName: ENCRYPTION_REL8N_NAME,\n                    ibGibsToRel8: [encryptionIbGib],\n                    space,\n                });\n                encryptionIbGibs = await this.getSpecialRel8dIbGibs({\n                    type: \"encryptions\",\n                    rel8nName: ENCRYPTION_REL8N_NAME,\n                    space,\n                });\n            }\n            return true;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async _createOuterspace({\n        space,\n        fnPromptOuterSpace,\n    }: {\n        space: IbGibSpaceAny,\n        fnPromptOuterSpace: (space: IbGibSpaceAny) => Promise<IbGibSpaceAny | undefined>,\n    }\n    ): Promise<boolean> {\n        const lc = `${this.lc}[${this._createOuterspace.name}]`;\n        try {\n            const alert = this.getFnAlert!();\n            let outerspaceIbGibs: IbGib_V1[] = await this.getSpecialRel8dIbGibs({\n                type: \"outerspaces\",\n                rel8nName: SYNC_SPACE_REL8N_NAME,\n                space,\n            });\n            if (outerspaceIbGibs.length === 0) {\n                await alert({\n                    title: 'Now to outerspace...',\n                    msg: `Great! Now we can create an outerspace ibgib, which is like a connection from this local space to other spaces (like the cloud).`,\n                });\n            }\n            while (outerspaceIbGibs.length === 0) {\n                let outerspaceIbGib = await fnPromptOuterSpace(space);\n                if (outerspaceIbGib === undefined) { break; }\n                await this.registerNewIbGib({ ibGib: outerspaceIbGib, space });\n                await this.rel8ToSpecialIbGib({\n                    type: \"outerspaces\",\n                    rel8nName: SYNC_SPACE_REL8N_NAME,\n                    ibGibsToRel8: [outerspaceIbGib],\n                    space,\n                });\n                await alert({\n                    title: 'Good job',\n                    msg: `Great! Now we can use this space to synchronize & import ibgibs.`,\n                });\n                outerspaceIbGibs = await this.getSpecialRel8dIbGibs({\n                    type: \"outerspaces\",\n                    rel8nName: SYNC_SPACE_REL8N_NAME,\n                    space,\n                });\n            }\n            if (outerspaceIbGibs.length > 0) {\n                return true;\n            } else {\n                await alert({ title: 'cancelled', msg: 'Cancelled.' });\n                return false;\n            }\n        } catch (error) {\n            console.log(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    // async getSyncSpaces({\n    //     createIfNone,\n    //     dontPrompt,\n    //     space,\n    //     outerspaceIds,\n    //     // fnSpaceFactory,\n    //     fnPromptSecret,\n    //     fnPromptEncryption,\n    //     fnPromptOuterSpace,\n    // }: {\n    //     // unwrapEncrypted: boolean,\n    //     createIfNone: boolean,\n    //     /**\n    //      * If true, don't prompt the user if we don't have it already cached.\n    //      *\n    //      * We don't want the user to hit the page and then always have to type in\n    //      * the password, just because my password code sucks atow.\n    //      */\n    //     dontPrompt?: boolean,\n    //     space?: IbGibSpaceAny,\n    //     /**\n    //      * @see {@link syncIbGibs} arg of the same name\n    //      */\n    //     outerspaceIds?: SpaceId[],\n    //     // fnSpaceFactory: (unencryptedSpaceData: any) => Promise<IbGibSpaceAny>,\n    //     fnPromptSecret: (space: IbGibSpaceAny) => Promise<SecretIbGib_V1 | undefined>,\n    //     fnPromptEncryption: (space: IbGibSpaceAny) => Promise<EncryptionIbGib_V1 | undefined>,\n    //     fnPromptOuterSpace: (space: IbGibSpaceAny) => Promise<IbGibSpaceAny | undefined>,\n    // }): Promise<SyncSpaceIbGib[]> {\n    //     const lc = `${this.lc}[${this.getSyncSpaces.name}]`;\n    //     try {\n    //         space = space ?? await this.getLocalUserSpace({});\n    //         if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: bf09346708ba4d6e9a1389bd1b66d500)`); }\n\n    //         // get existing\n    //         let resSyncSpaces: SyncSpaceIbGib[] =\n    //             await this.getSpecialRel8dIbGibs<SyncSpaceIbGib>({\n    //                 type: \"outerspaces\",\n    //                 rel8nName: SYNC_SPACE_REL8N_NAME,\n    //                 space,\n    //             });\n\n    //         // filter if applicable\n    //         const hasOuterspaceIds = (outerspaceIds?.length ?? 0) > 0;\n    //         if (hasOuterspaceIds) {\n    //             resSyncSpaces = resSyncSpaces.filter(x => outerspaceIds!.includes(x.data!.uuid!));\n    //         }\n\n    //         // create if applicable\n    //         if (resSyncSpaces.length === 0) {\n    //             if (createIfNone) {\n    //                 if (hasOuterspaceIds) { throw new Error(`(UNEXPECTED) both createIfNone true and outerspaceIds (filter) also true? you cannot have both of these set, it's one of the other. (E: 9caaa121dee3e41e6e29916614cd4e24)`); }\n    //                 const createdReqs = await this._createOuterspaceAndRequiredIbGibs({\n    //                     space,\n    //                     fnPromptSecret,\n    //                     fnPromptEncryption,\n    //                     fnPromptOuterSpace,\n    //                 });\n    //                 if (createdReqs) {\n    //                     resSyncSpaces = await this.getSpecialRel8dIbGibs<SyncSpaceIbGib>({\n    //                         type: \"outerspaces\",\n    //                         rel8nName: SYNC_SPACE_REL8N_NAME,\n    //                         space,\n    //                     });\n    //                 }\n    //             } else {\n    //                 throw new Error(`No sync spaces found. First create a sync outerspace (like a cloud sync space) in order to synchronize with it (E: 8f395f226ac7b558b9317befefbcb724)`);\n    //             }\n    //         }\n\n    //         // unwrap if requested\n    //         // let resSpaces: SyncSpaceIbGib[] = [];\n    //         // if (unwrapEncrypted) {\n    //         //     for (let i = 0; i < syncSpaceIbGibs.length; i++) {\n    //         //         let syncSpace = syncSpaceIbGibs[i];\n\n    //         //         if (syncSpace.rel8ns) {\n    //         //             if (syncSpace.rel8ns.ciphertext) {\n    //         //                 syncSpace = await this.unwrapEncryptedSyncSpace({\n    //         //                     encryptedSpace: syncSpace,\n    //         //                     fnPromptPassword: this.getFnPromptPassword!(),\n    //         //                     dontPrompt,\n    //         //                     space,\n    //         //                     fnSpaceFactory,\n    //         //                 });\n    //         //             }\n\n    //         //             resSpaces.push(syncSpace);\n    //         //         } else {\n    //         //         }\n\n    //         //     }\n    //         // } else {\n    //         // still (probably) encrypted\n    //         // resSpaces = syncSpaceIbGibs;\n    //         // }\n\n    //         // return resSpaces;\n    //         return resSyncSpaces;\n    //     } catch (error) {\n    //         console.error(`${lc} ${error.message}`);\n    //         return [];\n    //     }\n    // }\n\n    // async createRobbotIbGib({\n    //   robbotData,\n    //   space,\n    // }: {\n    //   robbotData: RobbotData_V1,\n    //   space?: IbGibSpaceAny,\n    // }): Promise<{ newRobbotIbGib: RobbotIbGib_V1, newRobbotsAddr: string }> {\n    //   const lc = `${this.lc}[${this.createRobbotIbGib.name}]`;\n    //   try {\n    //     space = space ?? await this.getLocalUserSpace({});\n    //     if (!space) { throw new Error(`space falsy and localUserSpace not initialized (E: 33ea7f4633484afa984225d037478ac4)`); }\n\n    //     return createRobbotIbGib({\n    //       robbotData,\n    //       space,\n    //       zeroSpace: this.zeroSpace,\n    //       fnBroadcast: (x) => this.fnBroadcast(x),\n    //       fnUpdateBootstrap: (x) => this.fnUpdateBootstrap(x),\n    //     });\n    //   } catch (error) {\n    //     console.error(`${lc} ${error.message}`);\n    //     throw error;\n    //   }\n    // }\n\n    async getAppRobbotIbGibs({\n        createIfNone,\n        fnPromptRobbot,\n        space,\n    }: {\n        createIfNone: boolean,\n        fnPromptRobbot: (space: IbGibSpaceAny, ibGib: RobbotIbGib_V1 | null) => Promise<RobbotPromptResult | undefined>;\n        space?: IbGibSpaceAny,\n    }): Promise<RobbotIbGib_V1[]> {\n        const lc = `${this.lc}[${this.getAppRobbotIbGibs.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: bf09346708ba4d6e9a1389bd1b66d500)`); }\n\n            // get existing. Note that these are not the robbot witnesses, but only\n            // the robbot ibgib (dtos). They do not have a `witness` function on them\n            // at this point.\n            let appRobbots_MaybeOutOfDate: RobbotIbGib_V1[] =\n                await this.getSpecialRel8dIbGibs<RobbotIbGib_V1>({\n                    type: \"robbots\",\n                    rel8nName: ROBBOT_REL8N_NAME,\n                    space,\n                });\n\n            let appRobbots: RobbotIbGib_V1[] = [];\n            for (let i = 0; i < appRobbots_MaybeOutOfDate.length; i++) {\n                let robbotIbGib = appRobbots_MaybeOutOfDate[i];\n                let robbotAddr = getIbGibAddr({ ibGib: robbotIbGib });\n                const latestAddr = await this.getLatestAddr({ ibGib: robbotIbGib, space });\n                if (latestAddr && latestAddr !== robbotAddr) {\n                    // robbot has a newer ibgib in its timeline\n                    let resGet = await this.get({ addr: latestAddr, space });\n                    if (!resGet || !resGet?.success || (resGet?.ibGibs ?? []).length === 0) {\n                        throw new Error(`could not get newer robbot ibgib (E: 15fa346c8ac17edb96e4b0870104c122)`);\n                    }\n                    robbotIbGib = resGet.ibGibs![0] as RobbotIbGib_V1;\n                    robbotAddr = getIbGibAddr({ ibGib: robbotIbGib });\n                }\n\n                const errors = await validateCommonRobbotIbGib({ robbotIbGib });\n                if ((errors ?? []).length === 0) {\n                    // only add if robbot doesn't have validation errors\n                    appRobbots.push(robbotIbGib);\n                } else {\n                    console.error(`${lc} robbot ibGib (${robbotAddr}) has validation errors: ${errors}`)\n                }\n            }\n\n            // create if applicable\n\n            if (appRobbots.length === 0 && createIfNone) {\n                console.error(`${lc} creating new robbot but should be not casting this on next line in src code. (E: 3252c5917e11421dbc1c26b280b8aeef)`);\n                let robbot = await createNewRobbot({ ibgibs: this as any, space, fnPromptRobbot });\n                if (robbot) {\n                    appRobbots = await this.getSpecialRel8dIbGibs<RobbotIbGib_V1>({\n                        type: \"robbots\",\n                        rel8nName: ROBBOT_REL8N_NAME,\n                        space,\n                    });\n                }\n            }\n\n            return appRobbots;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return [];\n        }\n    }\n\n    async getAppAppIbGibs({\n        createIfNone,\n        fnPromptApp,\n        space,\n    }: {\n        createIfNone: boolean,\n        /**\n         * factory function for creating/editing an app ibgib.\n         *\n         * @param space space within which we're working\n         * @param ibGib set if editing app, null if creating\n         * @returns TransformResult<IbGibAppAny> for app ibgib created/edited\n         */\n        fnPromptApp: (space: IbGibSpaceAny, ibGib: AppIbGib_V1 | null) => Promise<AppPromptResult | undefined>,\n        space?: IbGibSpaceAny,\n    }): Promise<AppIbGib_V1[]> {\n        const lc = `${this.lc}[${this.getAppAppIbGibs.name}]`;\n        try {\n            space = space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`space falsy and localUserSpace not initialized (?) (E: a5aec4d94f764c6a964179bbb743b577)`); }\n\n            // get existing. Note that these are not the app witnesses, but only\n            // the app ibgib (dtos). They do not have a `witness` function on them\n            // at this point.\n            let appApps_MaybeOutOfDate: AppIbGib_V1[] =\n                await this.getSpecialRel8dIbGibs<AppIbGib_V1>({\n                    type: \"apps\",\n                    rel8nName: APP_REL8N_NAME,\n                    space,\n                });\n\n            let appApps: AppIbGib_V1[] = [];\n            for (let i = 0; i < appApps_MaybeOutOfDate.length; i++) {\n                const appIbGib = appApps_MaybeOutOfDate[i];\n                const appAddr = getIbGibAddr({ ibGib: appIbGib });\n                const latestAddr = await this.getLatestAddr({ ibGib: appIbGib });\n                if (latestAddr && latestAddr !== appAddr) {\n                    // app has a newer ibgib in its timeline\n                    let resGet = await this.get({ addr: latestAddr, space });\n                    if (!resGet || !resGet?.success || (resGet?.ibGibs ?? []).length === 0) {\n                        throw new Error(`could not get newer app ibgib (E: de6a77634b1e4e16914ef110bb263d7c)`);\n                    }\n                    appApps.push(resGet.ibGibs![0] as AppIbGib_V1);\n                } else {\n                    appApps.push(appIbGib);\n                }\n            }\n\n            // create if applicable\n            if (appApps.length === 0 && createIfNone) {\n                console.error(`${lc} creating new app but should be not casting this on next line in src code. (E: 3252c5917e11421dbc1c26b280b8aeef)`);\n                let app = await createNewApp({ ibgibs: this as any, space, fnPromptApp });\n                if (app) {\n                    appApps = await this.getSpecialRel8dIbGibs<AppIbGib_V1>({\n                        type: \"apps\",\n                        rel8nName: APP_REL8N_NAME,\n                        space,\n                    });\n                }\n            }\n\n            return appApps;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            return [];\n        }\n    }\n\n    // #region syncIbGibs related\n\n    protected subSagaSyncTimeLog: SubscriptionWitness | undefined;\n\n    async syncIbGibs({\n        localSpace,\n        dependencyGraphIbGibs,\n        syncSpaceIbGibs,\n        // watch,\n    }: {\n        /**\n         * @see {@link MetaspaceService.syncIbGibs}\n         */\n        localSpace: IbGibSpaceAny,\n        /**\n         * @see {@link MetaspaceService.syncIbGibs}\n         */\n        dependencyGraphIbGibs?: IbGib_V1[],\n        /**\n         * @see {@link MetaspaceService.syncIbGibs}\n         */\n        syncSpaceIbGibs: IbGibSpaceAny[],\n        // /**\n        //  * If true, will watch ibgibs in dependency graph that have timelines\n        //  * (tjps).\n        //  */\n        // watch?: boolean,\n    }): Promise<SyncSagaInfo[] | undefined> {\n        const lc = `${this.lc}[${this.syncIbGibs.name}]`;\n        // map of saga infos across all spaces\n        // const sagaInfoMap: { [spaceGib: string]: SyncSagaInfo } = {};\n        try {\n            if (this.syncing) {\n                console.warn(`already syncing. (E: dfa3ad58e97f4b18b4e4d7dc252208fb)`);\n                return;\n            }\n            if (Object.values(this.sagaInfoMap).length > 0) { throw new Error(`this._syncing is false but sagaInfoMap not cleaned up(?). (E: bb69c808877c4931b5481585043c18e7)(UNEXPECTED)`); }\n\n            this._syncing = true;\n\n            // have to make sagaId and syncStatus$ early to enable timeLog calls\n            const sagaId = (await getUUID()).slice(0, 24);\n            const syncStatus$ = await newupSubject<SyncStatusIbGib>({ replay: true });\n            const syncTimelogName = `sync_log ${sagaId}`;\n            console.time(syncTimelogName);\n            console.timeLog(syncTimelogName, 'start');\n            this.subSagaSyncTimeLog = await syncStatus$.subscribe(fnObs<SyncStatusIbGib>({\n                next: async (status) => {\n                    // debugger; // metaspacebase syncIbGibs next\n                    if (logalot) { console.log(`${lc}[obs.next] next called (I: 9af8d3267b0ff473fe5f8024f0dbed23)`); }\n                    if (status.data?.statusCode === StatusCode.completed) {\n                        console.timeLog(syncTimelogName, 'StatusCode.complete');\n                    }\n                },\n                error: async (_: any) => {\n                    // debugger; // metaspacebase syncIbGibs error\n                    if (logalot) { console.log(`${lc}[obs.error] error called (I: 976b08ab82d64299b17927eac16b1693)`); }\n                    console.timeEnd(syncTimelogName)\n                    if (!this.subSagaSyncTimeLog) {\n                        console.error(`${lc}[obs.error] (unexpected) this.subSagaSyncTimeLog falsy (E: e1e82df8a1d94e7fbe55f638f3b4a53e)`)\n                    }\n                    await this.subSagaSyncTimeLog!.unsubscribe();\n                },\n                complete: async () => {\n                    // debugger; // metaspacebase syncIbGibs complete\n                    if (logalot) { console.log(`${lc}[obs.complete] complete called (I: 72307340e2b34b22b0787e3a3c906c06)`); }\n                    console.timeEnd(syncTimelogName)\n                    if (!this.subSagaSyncTimeLog) {\n                        console.error(`${lc}[obs.complete] (unexpected) this.subSagaSyncTimeLog falsy (E: 89429f426206444d8d6431492e585213)`)\n                    }\n                    await this.subSagaSyncTimeLog?.unsubscribe();\n                }\n            }));\n\n            // #region validate\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (!dependencyGraphIbGibs || dependencyGraphIbGibs.length === 0) { throw new Error(`dependencyGraphIbGibs required. (E: 404c36475fb84fc285a23a67c0b8fcb2)`); }\n            if (!syncSpaceIbGibs || syncSpaceIbGibs.length === 0) { throw new Error(`syncSpaceIbGibs required (E: c5a022454b9ce34856e141e61e337d24)`); }\n            // #endregion\n\n            const localUserSpace = localSpace ?? await this.getLocalUserSpace({});\n            if (!localUserSpace?.data) { throw new Error(`localUserSpace?.data falsy (E: e7ff57e4d529cde903619078ee9b6e23)`); }\n            if (!localUserSpace.gib) { throw new Error(`localUserSpace.gib falsy (E: 884d86d20e7a4468b3c8b2c3ab7dba7e)`); }\n\n            // #region get sync spaces and build participant infos\n            if (logalot) { console.log(`${lc} get sync spaces (returns if none)`); }\n            const participants: ParticipantInfo[] = [\n                // local user space is the src\n                { id: localUserSpace.data.uuid, gib: localUserSpace.gib, s_d: 'src', },\n\n                // each sync space is a destination\n                ...syncSpaceIbGibs.map(s => {\n                    if (!s.data) { throw new Error(`syncSpaceIbGib.data required. (E: 3c192771e84445a4b6476d5193b07e9d)`); }\n                    if (!s.data.uuid) { throw new Error(`syncSpaceIbGib.data.uuid required. (E: d27e9998227840f99d45a3ed245f3196)`); }\n                    if (!s.gib) { throw new Error(`syncSpaceIbGib.gib required. (E: db73aceb2f8445d8964ae49b59957072)`); }\n                    return { id: s.data.uuid, gib: s.gib, s_d: 'dest', } satisfies ParticipantInfo;\n                }),\n            ];\n            // #endregion\n\n            // _NOW_ we can finally put/merge into sync spaces.\n            // this returns to us the most recent versions which we can update\n            // our local timelines if we so choose (which we will).\n            // NOTE: we won't worry about what if different sync spaces have different\n            // versions atm. We're just going to do this assuming sync spaces\n            // are nice and coordinated (which they aren't).\n\n            if (logalot) { console.log(`${lc} syncing to spaces in parallel...`); }\n            const multiSpaceOpId = await getUUID();\n            const allSagaInfos: SyncSagaInfo[] = [];\n            const startSyncPromises: Promise<void>[] = syncSpaceIbGibs.map(async syncSpace => {\n                // create the info that will track progress over entire sync saga\n                const sagaInfo =\n                    await this._createNewSyncSagaInfo({\n                        multiSpaceOpId,\n                        allIbGibsToSync: dependencyGraphIbGibs,\n                        syncSpace,\n                        participants,\n                        sagaId,\n                        syncStatus$,\n                    });\n                this.sagaInfoMap[sagaInfo.sagaId] = sagaInfo;\n                allSagaInfos.push(sagaInfo);\n                try {\n                    // _startSync creates a status observable that can keep us up to date\n                    // on the status updates throughout the sync saga. We can handle\n                    // updating our own local space based on those status updates.\n\n                    // taking out watch for now\n                    // await this._startSync({ syncSagaInfo: sagaInfo, watch: false, syncTimelogName });\n                    await this._startSync({ syncSagaInfo: sagaInfo, syncTimelogName });\n                } catch (error) {\n                    // if this throws, then that is unexpected. The above result should\n                    // always be returned, and if it's errored then it should indicate as\n                    // such.\n                    console.error(`${lc} (UNEXPECTED) ${error.message}`);\n                    throw error;\n                }\n            });\n\n            // await just the initial starting of each space's sync operation.  when\n            // this promise is awaited, the sync operation is not done, only the\n            // starting of all sync sagas across all spaces.\n            console.timeLog(syncTimelogName, 'awaiting all startSyncPromises starting...');\n            await Promise.all(startSyncPromises);\n            console.timeLog(syncTimelogName, 'awaiting all startSyncPromises complete.');\n\n            // at this point, all spaces have prepared and are going. the sync saga\n            // info attached to each arg/result ibgib has the observable syncStatus$\n            // that will produce the status updates which can be interpreted &\n            // responded to.\n            await this._handleSagaUpdates();\n            return allSagaInfos;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            await this._finalizeAllSyncSagas_NoThrow({ error });\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async _finalizeSyncSaga({\n        sagaInfo,\n        error,\n    }: {\n        sagaInfo: SyncSagaInfo,\n        error?: any,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this._finalizeSyncSaga.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (sagaInfo.complete) { return; }\n            if (!sagaInfo.syncStatus$) { throw new Error(`(UNEXPECTED) this.syncStatus$ falsy? (E: 1fc3817823752f66a6a190b8107fe523)`); }\n            // if (!sagaInfo.syncStatus$.closed) {\n            if (!sagaInfo.syncStatus$.isCompleteOrErrored) {\n                if (error) {\n                    const emsg =\n                        typeof (error) === 'string' ? error : error.message ??\n                            `${lc} something went wrong (E: d7db873d9e8b4f14b5b490cadd9730f4)`;\n                    console.error(emsg);\n                    if (!sagaInfo.syncStatus$.error) { throw new Error(`(UNEXPECTED) sagaInfo.syncStatus$.error is falsy? (E: 8522f275dbbf0885db75aead27d72923)`); }\n                    await sagaInfo.syncStatus$.error!(emsg);\n                }\n                // we don't call complete() from within a next() (i don't think)\n                // if (!sagaInfo.syncStatus$.complete) { throw new Error(`(UNEXPECTED) sagaInfo.syncStatus$.complete is falsy? (E: 836f42d8f7084ff9afd73696134d41e6)`); }\n                // if (!sagaInfo.syncStatus$.isCompleteOrErrored) {\n                //     await sagaInfo.syncStatus$.complete();\n                // }\n            }\n            // I think $.complete() closes subscriptions, but to be double sure...\n            let toUnsubscribe: SubscriptionWitness[] = [];\n            const subscriptions = (sagaInfo.syncStatusSubscriptions ?? []);\n            for (let i = 0; i < subscriptions.length; i++) {\n                const sub = subscriptions[i];\n                let unsubscribed = await sub.unsubscribed();\n                if (!unsubscribed) {\n                    await sub.unsubscribe();\n                }\n            }\n\n            if (logalot) { console.log(`${lc} setting sagaInfo.complete to true (I: 85c34469cdac404782c2024ad6b6fbd1)`); }\n            sagaInfo.complete = true;\n            this._updateSagaInfoMapAndIsSyncingFlag();\n\n            if (logalot) { console.log(`${lc} complete.`); }\n        } catch (err) {\n            console.error(`${lc} ${err.message}`);\n            if (logalot) { console.log(`${lc} setting sagaInfo.complete to true (I: 23de6ef45eaf47a1918038dce3da7d78)`); }\n            sagaInfo.complete = true;\n            throw err;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async _finalizeAllSyncSagas_NoThrow({\n        error,\n    }: {\n        error?: any,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this._finalizeAllSyncSagas_NoThrow.name}]`;\n        try {\n            const syncSagaInfos_NotComplete =\n                Object.values(this.sagaInfoMap).filter(x => !x.complete);\n            for (let i = 0; i < syncSagaInfos_NotComplete.length; i++) {\n                const sagaInfo = syncSagaInfos_NotComplete[i];\n                await this._finalizeSyncSaga({ sagaInfo, error });\n            }\n        } catch (error) {\n            console.error(`${lc}(UNEXPECTED) ${error.message}`);\n            // caller expects does NOT rethrow!\n        } finally {\n            this._updateSagaInfoMapAndIsSyncingFlag();\n        }\n    }\n\n    protected _updateSagaInfoMapAndIsSyncingFlag(): void {\n        const lc = `${this.lc}[${this._updateSagaInfoMapAndIsSyncingFlag.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n\n            const sagaInfoKeys = Object.keys(this.sagaInfoMap || {});\n\n            if (sagaInfoKeys.length === 0) {\n                this.sagaInfoMap = {};\n                if (this._syncing) { this._syncing = false; }\n                return; /* <<<< returns early */\n            }\n\n            const sagaInfos = Object.values(this.sagaInfoMap);\n            if (sagaInfos.every(info => info.complete)) {\n                if (logalot) { console.log(`${lc} all sagaInfos are complete. finalizing sync. (I: f6d94deb5509e6b2e5371b9bfc007422)`); }\n                this.sagaInfoMap = {};\n                this._syncing = false;\n                if (logalot) { console.log(`${lc} this._syncing is now false.`); }\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async _createNewSyncSagaInfo({\n        multiSpaceOpId,\n        allIbGibsToSync,\n        syncSpace,\n        participants,\n        sagaId,\n        syncStatus$,\n    }: {\n        multiSpaceOpId: string,\n        allIbGibsToSync: IbGib_V1[],\n        syncSpace: IbGibSpaceAny,\n        participants: ParticipantInfo[],\n        /**\n         * have to make this early to enable the console.time/Log calls.\n         */\n        sagaId: string,\n        /**\n         * have to make this early to enable the console.time/Log calls.\n         */\n        syncStatus$: SubjectWitness<SyncStatusIbGib>,\n    }): Promise<SyncSagaInfo> {\n        const lc = `${this.lc}[${this._createNewSyncSagaInfo.name}]`;\n        try {\n            if (!multiSpaceOpId) { throw new Error(`multiSpaceOpId required. (E: a7e228dbd63948d784a67ddbb342e4f7)`); }\n            if (!syncSpace.data) { throw new Error(`syncSpace.data required. (E: 1c44334cf4545de147ef2dc675406a23)`); }\n\n            // do the addrs outside of info initializer\n            const syncAddrs_All = allIbGibsToSync.map(x => getIbGibAddr({ ibGib: x }));\n            const syncAddrs_All_WithTjps = allIbGibsToSync\n                .filter(x => hasTjp({ ibGib: x }))\n                .map(x => getIbGibAddr({ ibGib: x }));\n            const syncAddrs_All_AreTjps = allIbGibsToSync\n                .filter(x => x.gib !== GIB && x.data?.isTjp === true)\n                .map(x => getIbGibAddr({ ibGib: x }));\n            const syncAddrs_All_WithoutTjps =\n                syncAddrs_All.filter(addr => !syncAddrs_All_WithTjps.includes(addr));\n\n            // do the info initializer\n            const syncSagaInfo: SyncSagaInfo = {\n                multiSpaceOpId,\n                outerSpace: syncSpace,\n                // spaceGib: syncSpace.gib,\n                spaceId: syncSpace.data.uuid,\n                sagaId,\n                participants,\n                witnessFnArgsAndResults$: await newupSubject<SyncSpaceOptionsIbGib | SyncSpaceResultIbGib>({ replay: true }),\n\n                // syncStatus$: new ReplaySubject<SyncStatusIbGib>(),\n                syncStatus$,\n                syncStatusSubscriptions: [],\n\n                syncIbGibs_All: allIbGibsToSync,\n                syncAddrs_All,\n                syncAddrs_All_AreTjps,\n                syncAddrs_All_WithTjps,\n                syncAddrs_All_WithoutTjps,\n                syncAddrs_Skipped: [],\n                syncAddrs_ToDo: [],\n                syncAddrs_InProgress: [],\n                syncAddrs_Failed: [],\n            };\n\n            const syncTimelogName = `sync_log ${syncSagaInfo.sagaId}`;\n            // console.time(syncTimelogName);\n            console.timeLog(syncTimelogName);\n            // return it\n            return syncSagaInfo;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * this {@link IbGibsService} acts as the local app space intermediary,\n     * a broker between the local space and the sync space(s). So this\n     * function's job is to coordinate sending the given ibgibs\n     * to a single sync space and return the observable (subject)\n     * corresponding to the multi-step sync process.\n     *\n     * The caller will be responsible for coordinating among sync\n     * space results and handling updates to local space ibgib's,\n     * such as rebasing/updating/etc.\n     *\n     * @returns\n     */\n    protected async _startSync({\n        syncSagaInfo,\n        // watch,\n        syncTimelogName,\n    }: {\n        syncSagaInfo: SyncSagaInfo,\n        // watch?: boolean,\n        syncTimelogName: string,\n    }): Promise<SyncSpaceResultIbGib> {\n        const lc = `${this.lc}[${this._startSync.name}]`;\n        try {\n            const {\n                multiSpaceOpId, participants, sagaId, outerSpace: syncSpace,\n                syncIbGibs_All,\n                syncAddrs_All, syncAddrs_All_WithTjps: syncAddrs_All_Tjps, syncAddrs_All_WithoutTjps: syncAddrs_All_NonTjps,\n            } = syncSagaInfo;\n\n            // first we want to get the ball rolling\n            // we will get back an ibGib that we can use to track the progress of the\n            // entire operation wrt this space.\n            console.timeLog(syncTimelogName, `getLocalUserSpace starting...`);\n            const localUserSpace = await this.getLocalUserSpace({});\n            if (!localUserSpace) { throw new Error(`localUserSpace required (E: e01fc13ce7c5a802b50aa0f9b2c13a23)`); }\n            if (!localUserSpace.data) { throw new Error(`localUserSpace.data required (E: e01fc13ce7c5a802b50aa0f9b2c13a23)`); }\n            console.timeLog(syncTimelogName, `getLocalUserSpace complete.`);\n\n            const argStartSync: SyncSpaceOptionsIbGib = await syncSpace.argy({\n                argData: {\n                    // cmd: 'put', cmdModifiers: watch ? ['sync', 'watch'] : ['sync'],\n                    cmd: 'put', cmdModifiers: ['sync'],\n                    sagaId,\n                    participants,\n                    ibGibAddrs: syncAddrs_All,\n                    ibGibAddrs_All_Tjps: syncAddrs_All_Tjps,\n                    ibGibAddrs_All_NonTjps: syncAddrs_All_NonTjps,\n                } as SyncSpaceOptionsData,\n                ibGibs: syncIbGibs_All, // do we need to do this yet?\n                ibMetadata: `sync src ${localUserSpace.data.name} srcId ${localUserSpace.data.uuid}`,\n            });\n            argStartSync.syncSagaInfo = syncSagaInfo;\n\n            // atow we only have one cycle. in the future, I think we will be having the possibility\n            // of multiple cycles, which is why I have this structured as an observable\n            // and not hard-coding a single arg/result in the saga info.\n            syncSagaInfo.witnessFnArgsAndResults$.next(argStartSync);\n            console.timeLog(syncTimelogName, `syncSpace witness starting...`);\n            const resStartSync: SyncSpaceResultIbGib = await syncSpace.witness(argStartSync);\n            console.timeLog(syncTimelogName, `syncSpace witness complete.`);\n            if (!resStartSync.data?.statusTjpAddr) { throw new Error(`resStartSync.data.statusTjpAddr is falsy. sagaId: ${sagaId} (E: 727b5cc1a0254497bc6e06e9c6760564)`); }\n            syncSagaInfo.witnessFnArgsAndResults$.next(resStartSync);\n\n            // in our return, we can check for updates since our last communication.\n            // if (Object.keys(resStartSync.data.watchTjpUpdateMap ?? {}).length > 0) {\n            //   if (logalot) { console.log(`${lc} resStartSync.data.watchTjpUpdateMap: ${pretty(resStartSync.data.watchTjpUpdateMap)}`); }\n            //   console.timeLog(syncTimelogName, `handleWatchTjpUpdates starting...`);\n            //   await this.handleWatchTjpUpdates({\n            //     outerSpace: syncSpace,\n            //     updates: resStartSync.data.watchTjpUpdateMap,\n            //     localUserSpace,\n            //   });\n            //   console.timeLog(syncTimelogName, `handleWatchTjpUpdates complete.`);\n            // }\n\n            // most of our handling will be in subscription to syncStatus$ updates.\n            return resStartSync;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Coming in to this function, we have results from one or more\n     * sync spaces. Here are the combinations of expected outcomes:\n     *\n     * 1. All success, each returns the exact same new ib^gib address(es).\n     * 2. All success, but different spaces return different ib^gib address(es).\n     * 3. Some success, which returns exact same new ib^gib, some error.\n     * 4. Some success, more than one ib^gib address(es), some error.\n     * 5. All error.\n     *\n     * For the first naive implementation, we will always be optimistic,\n     * assuming that errors will be resolved with enough attempts. This\n     * is closely related to our initial optimistic strategy of\n     * \"access is authorization\" + \"unordered dna equivalence\". These\n     * strategies mean that we are simply, optimistically, and\n     * naively applying incoming dna transforms to ibgib timelines.\n     * So failure should only result from a failure at the communication\n     * layer, assuming non-adversarial conditions.\n     *\n     * ## future\n     *\n     * The handling of this should absolutely be generalized to the\n     * requirements for interspatial relationships. This is the language\n     * that must be implemented to deal with this in a dynamic fashion.\n     *\n     * This does not equate to only \"ad hoc\" in the sense of untested/untried.\n     * This means that we have an \"on-chain\", public linked requirement\n     * for consensus as opposed to a hard-coded consensus as is defined\n     * in this function.\n     *\n     * It is in this generalization that byzantine resolution can be\n     * achieved through whichever mechanism is correct for the use case.\n     */\n    protected async _handleSagaUpdates(): Promise<void> {\n        const lc = `${this.lc}[${this._handleSagaUpdates.name}]`;\n        try {\n            // at this point in execution, each space has returned the result ibgib\n            // which has a syncStatus$ observable.\n\n            const infos = Object.values(this.sagaInfoMap);\n            for (let i = 0; i < infos.length; i++) {\n                const sagaInfo = infos[i];\n\n                let sub = await sagaInfo.syncStatus$\n                    .subscribe(fnObs({\n                        next: async (status: SyncStatusIbGib) => {\n                            // debugger; // metaspacebase handlesagaupdates next\n                            if (logalot) { console.log(`${lc}(sagaId: ${sagaInfo.sagaId}) subscribe next triggered. status: ${status?.data?.statusCode} (I: 41e1f61e5e1b422ead1d72a1c92c7d51)`); }\n                            await this._handleSyncStatusIbGib({ status, sagaInfo });\n                        },\n                        error: async (error: string) => {\n                            // debugger; // metaspacebase handlesagaupdates error\n                            const emsg = `${lc}(sagaId: ${sagaInfo.sagaId}) syncStatus$.error: ${error}`;\n                            console.error(emsg);\n                            // await this.getFnAlert!()({title: 'couldnt this.syncIbGibs...', msg: emsg});\n                            await this._finalizeSyncSaga({ sagaInfo, error: emsg });\n                        },\n                        complete: async () => {\n                            // debugger; // metaspacebase handlesagaupdates complete\n                            if (logalot) { console.log(`${lc}(sagaId: ${sagaInfo.sagaId}) syncStatus$.complete.`); }\n                            await sub.unsubscribe(); // differs from rxjs\n                        },\n                    }));\n                // changing this to in the complete handler because i think\n                // my rx design and rxjs differs. they had some sort of\n                // reference counting/scope magic that would kill the\n                // observable if no subscriptions or something. i don't\n                // remember. anyway, i think I can just unsubscribe in\n                // complete with mine.\n                // if (sagaInfo.syncStatusSubscriptions) { sagaInfo.syncStatusSubscriptions.push(sub); }\n                // if (!sagaInfo.syncStatusSubscriptions) { throw new Error(`sagaInfo.syncStatusSubscriptions array falsy? (E: f6d834beaa164c6ea1073d35b9fecd01)`) }\n                // sagaInfo.syncStatusSubscriptions.push(sub);\n            }\n\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    protected async _handleSyncStatusIbGib({\n        status,\n        sagaInfo,\n    }: {\n        status: SyncStatusIbGib,\n        sagaInfo: SyncSagaInfo,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this._handleSyncStatusIbGib.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            // #region validate\n            if (!status) { throw new Error(`falsy status. (E: 8da370a9f3df48a98cc08f1cccf5f2dc)`); }\n            if (!status.data) { throw new Error(`falsy status.data. (E: 996d458c5cde4622ba1ed54c7e188815)`); }\n            if (!status.data.statusCode) { throw new Error(`falsy status.data.statusCode (E: 7f2bec6b9dd0484eb7ef97966e6dd027)`); }\n            // #endregion validate\n\n            const localSpaceId = getSrcLocalSpaceId({ participants: sagaInfo.participants });\n            const localSpace = await this.getLocalUserSpace({ lock: false, localSpaceId });\n            if (!localSpace) { throw new Error(`(UNEXPECTED) couldn't get the local space (id: ${localSpaceId}) in the middle of a saga? (E: b921a1530148ccdae688cb8a13715324)`); }\n            const resStoreStatusLocally =\n                await this.put({ ibGibs: status.statusIbGibGraph, space: localSpace });\n            if (!resStoreStatusLocally.success) {\n                // just log for now...the saving is supposed to the the log in the first place.\n                console.error(`${lc}(UNEXPECTED) couldn't save status graph locally? sagaId: ${sagaInfo.sagaId} (E: b472101897824195b96b658c441dfb55)`);\n            }\n            const statusCode = status.data.statusCode;\n            if (logalot) { console.log(`${lc} status update received. statusCode: ${statusCode}. sagaId: ${sagaInfo.sagaId}. spaceId: ${sagaInfo.spaceId}`); }\n\n            switch (statusCode) {\n                case StatusCode.started:\n                    // nothing to do on start? hmm...\n                    break;\n\n                case StatusCode.inserted:\n                    // await this.handleSyncComplete_Inserted({sagaInfo, status});\n                    // nothing further to do? hmm...\n                    break;\n\n                case StatusCode.updated:\n                    // await this.handleSyncComplete_Updated({sagaInfo, status});\n                    // nothing further to do? hmm...\n                    break;\n\n                case StatusCode.merged_dna:\n                    await this._handleSyncStatus_Merged({ status, sagaInfo });\n                    break;\n\n                case StatusCode.merged_state:\n                    await this._handleSyncStatus_Merged({ status, sagaInfo });\n                    break;\n\n                case StatusCode.already_synced:\n                    // await this.handleSyncComplete_AlreadySynced({sagaInfo, status});\n                    // nothing further to do? hmm...\n                    break;\n\n                case StatusCode.completed:\n                    await this._handleSyncStatus_Complete({ sagaInfo });\n                    break;\n\n                case StatusCode.undefined:\n                    // atow undefined is used in primitive status parentage\n                    throw new Error(`statusCode is \"undefined\". Maybe published a primitive? sagaId: ${sagaInfo.sagaId} (E: c98376f35b194adf9bf12ff9259a2569)`);\n\n                default:\n                    // ?\n                    throw new Error(`(UNEXPECTED) unknown status.data.statusCode (${status.data.statusCode}). sagaId: ${sagaInfo.sagaId} (E: e4872abfc1ae4c27905793ca0f937a9b)`);\n            }\n            if (logalot) { console.log(`${lc} complete.`); }\n        } catch (error) {\n            const emsg = `${lc} ${error.message}`;\n            console.error(emsg);\n            if (!sagaInfo.syncStatus$?.error) {\n                throw new Error(`(UNEXPECTED) sagaInfo.syncStatus$.error falsy? (E: 36cc488835aeb12e1ae6b7a49d0d8523)`);\n            }\n            await sagaInfo.syncStatus$.error(emsg);\n        }\n    };\n\n    protected async _handleSyncStatus_Merged({\n        status,\n        sagaInfo,\n    }: {\n        status: SyncStatusIbGib,\n        sagaInfo: SyncSagaInfo,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this._handleSyncStatus_Merged.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            // #region validate\n\n            // not necessarily the case, if we only have changes on the store side, we apply no dna and create no side effects\n            if ((status.createdIbGibs ?? []).length === 0 &&\n                (status.storeOnlyIbGibs ?? []).length === 0\n            ) { throw new Error('status.createdIbGibs and/or status.storeOnlyIbGibs required when merging. (E: d118bde47fb9434fa95d747f8e4f6b33)'); }\n\n            if (Object.keys(status.ibGibsMergeMap ?? {}).length === 0) { throw new Error('status.ibGibsMergeMap required when merging. (E: 0f06238e5535408f8980e0f9f82cf564)'); }\n\n            // #endregion validate\n\n            if (logalot) { console.log(`${lc} validated.`); }\n\n            const localSpaceId = getSrcLocalSpaceId({ participants: sagaInfo.participants });\n            const localSpace = await this.getLocalUserSpace({ localSpaceId });\n            if (!localSpace) { throw new Error(`(UNEXPECTED) couldn't get src participant with space id (${localSpaceId}) in the middle of a saga? (E: c75732b748f6a168254e38dc5548e824)`); }\n\n            // first, we will store the newly created ibgibs in the local space. Then\n            // we want to rebase our local timeline to point to the new one. I believe\n            // we can do this simply by registering the latest created ibgib which\n            // will record it as the local latest ibgib in the tjp timeline. It may be\n            // best to somehow tag the rebased ibgib, which would enable us to\n            // optionally see this later without modifying the ibgib timeline by a\n            // mut8 or rel8 function directly on the now-vestigial/abandoned timeline.\n\n            /**\n             * groups the incoming `ibGibsToRegister` by tjp and registers each latest.\n                   *\n                   * @param ibGibsToRegister will call `registerNewIbGib` on the lastest in each timeline\n             */\n            const registerLatestInTimelines = async (ibGibsToRegister: IbGib_V1[]) => {\n                const timelines =\n                    getTimelinesGroupedByTjp({ ibGibs: ibGibsToRegister });\n                for (let i = 0; i < Object.keys(timelines).length; i++) {\n                    const tjpAddr = Object.keys(timelines)[i];\n                    const timeline = timelines[tjpAddr];\n                    const latestIbGibInTimeline = timeline[timeline.length - 1];\n                    // registerNewIbGib is idempotent if already registered as latest\n                    await this.registerNewIbGib({ ibGib: latestIbGibInTimeline, space: localSpace });\n                }\n            };\n\n            // first, we will store the newly created ibgibs (if any) in the local space.\n            // created ibgibs may not exist if only the sync space branch has changed.\n            // meanwhile, we must collect all ibgib timelines (with tjps) to register\n            if (status.createdIbGibs?.length ?? 0 > 0) {\n                if (logalot) { console.log(`${lc} putting createdIbGibs (${status.createdIbGibs!.length}): ${status.createdIbGibs!.map(x => getIbGibAddr({ ibGib: x })).join('\\n')}.`); }\n                const resPutCreated = await this.put({ ibGibs: status.createdIbGibs, space: localSpace });\n                if (!resPutCreated.success) { throw new Error(`Couldn't save created ibGibs locally? (E: f8bc91259c5043d589cd2e7ad2220c1f)`); }\n                if (status.storeOnlyIbGibs) {\n                    await registerLatestInTimelines(status.storeOnlyIbGibs)\n                }\n            } else {\n                if (logalot) { console.log(`${lc} no createdIbGibs`); }\n            }\n\n\n            if (status.storeOnlyIbGibs?.length ?? 0 > 0) {\n                if (logalot) { console.log(`${lc} putting into local space the storeOnlyIbGibs (${status.storeOnlyIbGibs!.length}): ${status.storeOnlyIbGibs!.map(x => getIbGibAddr({ ibGib: x })).join('\\n')}.`); }\n                console.warn(`${lc} putting storeOnlyIbGibs (${status.storeOnlyIbGibs!.length}): ${status.storeOnlyIbGibs!.map(x => getIbGibAddr({ ibGib: x })).join('\\n')}.`);\n                const resPutStoreOnly = await this.put({ ibGibs: status.storeOnlyIbGibs, space: localSpace });\n                if (!resPutStoreOnly.success) { throw new Error(`Couldn't save storeonly ibGibs locally? (E: c5ab044718ab42bba27f5852149b7ddc)`); }\n                await registerLatestInTimelines(status.storeOnlyIbGibs!)\n            } else {\n                if (logalot) { console.log(`${lc} no storeOnlyIbGibs`); }\n            }\n\n            // download any dependency ibgibs from the new latest ibgib that we don't have already.\n\n            // register the new latest ibgib.\n            // merge map goes from old latest addr -> latest ibGib that was the result of the merge.\n            let newLatestIbGibs = Object.values(status.ibGibsMergeMap ?? {});\n            for (let i = 0; i < newLatestIbGibs.length; i++) {\n                const latestIbGib = newLatestIbGibs[i];\n                if (logalot) { console.log(`${lc} registering latestIbGib in localUserSpace: ${getIbGibAddr({ ibGib: latestIbGib })}`); }\n                await this.registerNewIbGib({ ibGib: latestIbGib, space: localSpace });\n            }\n\n            if (logalot) { console.log(`${lc} complete.`); }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    protected async _handleSyncStatus_Complete({\n        sagaInfo,\n    }: {\n        sagaInfo: SyncSagaInfo,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this._handleSyncStatus_Complete.name}]`;\n        try {\n            // cleanup just this saga, which corresponds to a single sync space.\n            await this._finalizeSyncSaga({ sagaInfo });\n\n            // if this is the last saga across all spaces, clean up the rest.\n            const allSagaInfos = Object.values(this.sagaInfoMap);\n            if (allSagaInfos.every(x => x.complete)) {\n                await this._finalizeAllSyncSagas_NoThrow({});\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            await this._finalizeAllSyncSagas_NoThrow({ error });\n        }\n    }\n\n    protected async _getLatestIbGibsWithTjps({\n        ibGibs,\n        warnIfMultipleLocalTimelines,\n    }: {\n        ibGibs: IbGib_V1[],\n        /**\n         * I've already written the code to check for this. But I think\n         * this will be normal when put/merging.\n         */\n        warnIfMultipleLocalTimelines?: boolean,\n    }): Promise<IbGib_V1[]> {\n        const lc = `${this.lc}[${this._getLatestIbGibsWithTjps.name}]`;\n        try {\n            const result: IbGib_V1[] = [];\n            const ibGibsWithTjp_Ungrouped = ibGibs.filter(x =>\n                x.data?.isTjp || (x.rel8ns?.tjp?.length ?? 0) > 0 || x.gib?.includes(GIB_DELIMITER)\n            );\n            // group them by tjp\n            const ibGibsWithTjp_GroupedByTjpGib =\n                groupBy({ items: ibGibsWithTjp_Ungrouped, keyFn: x => getGibInfo({ gib: x.gib }).tjpGib ?? '' });\n            const tjpGibs = Object.keys(ibGibsWithTjp_GroupedByTjpGib);\n            for (let i = 0; i < tjpGibs.length; i++) {\n                const group = ibGibsWithTjp_GroupedByTjpGib[tjpGibs[i]];\n                if (warnIfMultipleLocalTimelines) {\n                    // quick check to warn if we have multiple n's for a tjpGib (multi-timeline)\n                    let nCounts: { [key: number]: number } = {};\n                    for (const ibGibFrame of group) {\n                        let n = ibGibFrame.data?.isTjp ? -1 : (ibGibFrame.data?.n ?? -2);\n                        if (n === -2) { throw new Error(`ibGibFrame.data.n is undefined. We're only working with those with n right now!`); }\n                        nCounts[n] = (nCounts[n] ?? 0) + 1;\n                    }\n                    if (Object.values(nCounts).some(count => count > 1)) {\n                        console.warn(`${lc} we have multiple local timelines.`)\n                    }\n                }\n\n                // sort by n (ascending) and then grab the latest one\n                const latestIbGibInGroup =\n                    group.sort((a, b) => (a.data?.n ?? -1) > (b.data?.n ?? -1) ? 1 : -1)[group.length - 1];\n                result.push(latestIbGibInGroup);\n            }\n\n            // we're done\n            return result;\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        }\n    }\n\n    // #endregion syncIbGibs related\n\n    // #region autosync\n\n    async enableAutosync({\n        tjpIbGibs,\n    }: {\n        tjpIbGibs: IbGib_V1[],\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.enableAutosync.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if ((tjpIbGibs ?? []).length === 0) { throw new Error(`tjps required. (E: 3e3bb6ef1a3d483795440e0efcef8e04)`); }\n\n            // validate tjps\n            if (tjpIbGibs.some(tjp => !tjp.data?.isTjp)) {\n                const wonkyTjpAddrs =\n                    tjpIbGibs\n                        .filter(tjp => !tjp.data?.isTjp)\n                        .map(x => getIbGibAddr({ ibGib: x }));\n                console.warn(`${lc} unrelating tjp whose data.isTjp is false. tjpAddrs: ${wonkyTjpAddrs.join('|')} (W: 03b3d7a94e6d4ccaace3df4657a82322)`);\n            }\n\n            // we'll use addrs to compare to cache and autosync special ibgib\n            let tjpAddrs = tjpIbGibs.map(tjp => getIbGibAddr({ ibGib: tjp }));\n\n            // if we're already autosyncing all tjps, warn and return early check\n            // locally since this is very fast/cheap\n            let notAlreadySyncingTjpAddrs =\n                tjpAddrs.filter(tjpAddr => !this._alwaysAutosyncTjpAddrsCache.has(tjpAddr));\n            if (notAlreadySyncingTjpAddrs.length === 0) {\n                console.warn(`${lc} all tjpAddrs already auto syncing. tjpAddrs: ${tjpAddrs.join('\\n')} (W: 7fbe51c8187840efa1b259417053bd22)`);\n                return; /* <<<< returns early */\n            }\n\n            // ...and double check in autosyncs itself, more expensive though\n            const autosyncsIbGib = await this.getSpecialIbGib({ type: \"autosyncs\" });\n            if (!autosyncsIbGib?.rel8ns) { throw new Error(`autosyncsIbGib?.rel8ns falsy (E: 963313139e919c09aade8b8c412d7b23)`); }\n            const alreadySyncing = autosyncsIbGib.rel8ns[AUTOSYNC_ALWAYS_REL8N_NAME] ?? [];\n            notAlreadySyncingTjpAddrs = tjpAddrs.filter(tjpAddr => !alreadySyncing.includes(tjpAddr));\n            if (notAlreadySyncingTjpAddrs.length === 0) {\n                console.error(`${lc} (UNEXPECTED) all tjpAddrs already auto syncing per special ibgib. Proceeding without throwing here, but this means that the cache is out of sync with the special ibgib also. tjpAddrs: ${tjpAddrs.join('\\n')} (E: 574e163118f043fa8c50cfd575e62122)`);\n                return; /* <<<< returns early */\n            }\n\n            // map back from tjp addrs to the tjp ibgibs\n            const notAlreadySyncingTjps = notAlreadySyncingTjpAddrs.map(tjpAddr => {\n                return tjpIbGibs.filter(tjp => getIbGibAddr({ ibGib: tjp }) === tjpAddr)[0];\n            });\n\n            // execute rel8 transform and plumbing\n            await this.rel8ToSpecialIbGib({\n                type: 'autosyncs',\n                ibGibsToRel8: notAlreadySyncingTjps,\n                rel8nName: AUTOSYNC_ALWAYS_REL8N_NAME,\n            });\n\n            // add to cache and we're done\n            notAlreadySyncingTjpAddrs.forEach(tjpAddr => {\n                this._alwaysAutosyncTjpAddrsCache.add(tjpAddr);\n            });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    async disableAutosync({\n        tjpIbGibs,\n    }: {\n        tjpIbGibs: IbGib_V1[],\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.disableAutosync.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if ((tjpIbGibs ?? []).length === 0) { throw new Error(`tjps required. (E: 7b7e34e20b5848b882e14ff8b6c53622)`); }\n\n            if (tjpIbGibs.some(tjp => !tjp.data?.isTjp)) {\n                const wonkyTjpAddrs =\n                    tjpIbGibs\n                        .filter(tjp => !tjp.data?.isTjp)\n                        .map(x => getIbGibAddr({ ibGib: x }));\n                console.warn(`${lc} unrelating tjp whose data.isTjp is false. tjpAddrs: ${wonkyTjpAddrs.join('|')} (W: 7babdf67dda54a2a9905c6c45ef36522)`);\n            }\n            let tjpAddrs = tjpIbGibs.map(tjp => getIbGibAddr({ ibGib: tjp }));\n\n            // if we're already autosyncing this tjp, warn and return early\n            // check locally...\n            // ...and double check in autosyncs itself.\n            const autosyncsIbGib = await this.getSpecialIbGib({ type: \"autosyncs\" });\n            if (!autosyncsIbGib?.rel8ns) { throw new Error(`(UNEXPECTED) invalid autosyncIbGibs. rel8ns falsy. (E: 5f6211c8a41896003db8bfc40230af22)`); }\n            const alreadySyncing = autosyncsIbGib.rel8ns[AUTOSYNC_ALWAYS_REL8N_NAME] ?? [];\n            const tjpAddrsToRemove: TjpIbGibAddr[] = [];\n            tjpAddrs.forEach(tjpAddr => {\n                if (alreadySyncing.includes(tjpAddr)) {\n                    if (logalot) { console.log(`${lc} disabling autosync for ${tjpAddr} (I: 63087804e6c436143971e5039b5e5e22)`); }\n                    tjpAddrsToRemove.push(tjpAddr);\n                } else {\n                    if (logalot) { console.log(`${lc} already NOT auto syncing ${tjpAddr} (I: 88e00fea009964cd2bab4cc580aa2922)`); }\n                }\n            });\n            if (tjpAddrsToRemove.length === 0) {\n                console.warn(`${lc} tried to disable autosync for tjpAddrs but none were valid. returning early. (W: f9bdda90d906471aa56804d76b6e9522)`);\n                return; /* <<<< returns early */\n            }\n\n            const uniqueTjpAddrsToRemove = Array.from(new Set(tjpAddrsToRemove));\n            const tjpsToRemove = uniqueTjpAddrsToRemove.map(tjpAddr => {\n                return tjpIbGibs.filter(tjp => getIbGibAddr({ ibGib: tjp }) === tjpAddr)[0];\n            });\n\n\n            // execute rel8 transform and plumbing\n            await this.rel8ToSpecialIbGib({\n                type: 'autosyncs',\n                ibGibsToUnRel8: tjpsToRemove,\n                rel8nName: AUTOSYNC_ALWAYS_REL8N_NAME,\n            });\n\n            // remove from cache and we're done\n            uniqueTjpAddrsToRemove.forEach(tjpAddr => {\n                this._alwaysAutosyncTjpAddrsCache.delete(tjpAddr);\n            });\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async loadAutoSyncs(): Promise<void> {\n        const lc = `${this.lc}[${this.loadAutoSyncs.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            const autosyncsIbGib = await this.getSpecialIbGib({ type: \"autosyncs\" });\n            if (!autosyncsIbGib) {\n                console.warn(`${lc} autosyncsIbGib (\"autosyncs\") special ibgib not found not found. maybe fine, no idea. (W: 30ad2df15b38999106883358722fd425)`);\n                return; /* <<<< returns early */\n            }\n\n            // if (!autosyncsIbGib?.rel8ns) { throw new Error(`autosyncsIbGib?.rel8ns falsy (E: 3fdcdf40f33c41ed9b7a01a079a8fd71)`); }\n\n            if (autosyncsIbGib.rel8ns) {\n                this._alwaysAutosyncTjpAddrsCache =\n                    new Set(autosyncsIbGib.rel8ns[AUTOSYNC_ALWAYS_REL8N_NAME]);\n            }\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * checks to see if autosync is enabled for a given `tjp`.\n     *\n     * NOTE: this only checks cache atm.\n     *\n     * @returns true if autosync is enabled for the given tjp, else false\n     */\n    autosyncIsEnabled({\n        tjp,\n    }: {\n        tjp: IbGib_V1,\n    }): boolean {\n        const lc = `${this.lc}[${this.autosyncIsEnabled.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            return this._alwaysAutosyncTjpAddrsCache.has(getIbGibAddr({ ibGib: tjp }));\n        } catch (error) {\n            console.error(`${lc} ${error.message}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #endregion autosync\n\n}\n", "import { IBGIB_SPACE_NAME_DEFAULT } from \"../space-constants.mjs\";\nimport { Directory, Encoding } from \"./filesystem-types.mjs\";\n\n/**\n * atow this is '.' (cwd)\n *\n * In original ionic space, this would be \"DOCUMENTS\" or similar.\n */\nexport const IBGIB_BASE_DIR: Directory = '.';\n/**\n * atow this is 'utf8'\n *\n * this stems from original ionic space default encoding.\n */\nexport const IBGIB_ENCODING: Encoding = 'utf8';\n/**\n * Base directory for all data of the app.\n */\nexport const IBGIB_BASE_SUBPATH = 'ibgib';\n/**\n * Default space that is also used for bootstrapping.\n *\n * The user should provide his/her own space name that will contain their data.\n * If a custom user space name is not provided, one should be auto-generated.\n *\n * ## notes\n *\n * * the leading 000's help to put the space earlier in alphabetized listing if viewing through an OS file viewer\n */\nexport const IBGIB_SPACE_SUBPATH_DEFAULT = `000_${IBGIB_SPACE_NAME_DEFAULT}`;\n/**\n * Subpath for \"normal\" ibgibs (non-meta, non-dna, non-binary, etc.).\n */\nexport const IBGIB_IBGIBS_SUBPATH = 'ibgibs';\n/**\n * should contain special-use ibgibs to the application.\n *\n * Use case:\n *   Because some special ibgibs will be changed frequently,\n *   e.g. settings, a separate folder will be useful.\n */\nexport const IBGIB_META_SUBPATH = 'meta';\n/**\n * Path for storing the dna for ibgibs.\n *\n * bins will be stored without hyphens in the format:\n *   [hash].[ext]\n *\n * @example\n *   641575866a7c42bda89f58de5cd1c3aa.jpg\n */\nexport const IBGIB_BIN_SUBPATH = 'bin';\n/**\n * Path for storing the dna for ibgibs.\n *\n * ## notes\n *\n * eventually, these should most likely be stored in \"colder\"\n * storage, like compressed, low-priority.\n */\nexport const IBGIB_DNA_SUBPATH = 'dna';\n/**\n * store long paths here.\n *\n * WARNING: short name used here specifically because we're trying to mitigate\n * existing technical debt outside of the the ibgib codebase. otherwise, this\n * would be much more descriptive. please don't use non-descriptive short names\n * like this in ibgib code unless it's extremely justified.\n */\nexport const IBGIB_LONG_SUBPATH = 'l';\n\n/**\n * Yep, this one starts with default instead of ending with it.\n */\nexport const DEFAULT_FILESYSTEM_SPACE_DESCRIPTION = `This is a filesystem space. The ibgib data contains settings for the space itself, and the witness ibgib object interfaces with a back end that is hierarchical like a filesystem. Descend from this class if you're working with a similar space.`;\n\n/**\n * when deciding what a long path length is, this is the constant used.\n *\n * this is used in help mitigating some OSs path limits of 255.\n *\n * ## notes\n *\n * i have this well below the 255 limit on some OSs. probably too defensive.\n */\nexport const DEFAULT_LONG_PATH_LENGTH = 240;\n\n/**\n * used when building paths\n */\nexport const DEFAULT_PATH_SEPARATOR = '/';\n\n/**\n * want to get some more metadata past the initial atom(s) and 32 sounds like a\n * decent compromise of staying relatively short and doing this.\n */\nexport const ARBITRARY_IB_SUBSTRING_LENGTH_FOR_MITIGATE_LONG_PATH = 32;\n", "import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';\nimport { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';\n// import { SecretModalFormComponent } from '../modals/secret-modal-form/secret-modal-form.component';\n// import { EncryptionModalFormComponent } from '../modals/encryption-modal-form/encryption-modal-form.component';\n// import { OuterspaceModalFormComponent } from '../modals/outerspace-modal-form/outerspace-modal-form.component';\n// import { UpdatePicModalFormComponent, UpdatePicPromptResult } from '../modals/update-pic-modal-form/update-pic-modal-form.component';\n// import { UpdateCommentModalFormComponent, UpdateCommentPromptResult } from '../modals/update-comment-modal-form/update-comment-modal-form.component';\n// import { EncryptionData_V1 } from '@ibgib/core-gib/dist/common/encrypt/encrypt-types.mjs';\n// import { OuterSpaceIbGib } from '@ibgib/core-gib/dist/witness/space/outer-space/outer-space-types.mjs';\n// import { PicIbGib_V1 } from '@ibgib/core-gib/dist/common/pic/pic-types.mjs';\n// import { RobbotIbGib_V1 } from '@ibgib/core-gib/dist/witness/robbot/robbot-types.mjs';\n// import {\n//     RobbotModalFormComponent, RobbotPromptResult\n// } from '@ibgib/core-gib/dist/modals/robbot-modal-form/robbot-modal-form.component';\n// import { AppIbGib_V1 } from '@ibgib/core-gib/dist/witness/app/app-types.mjs';\n// import {\n//     AppModalFormComponent, AppPromptResult\n// } from '@ibgib/core-gib/dist../modals/app-modal-form/app-modal-form.component';\n// import { clearDoCancelModalOnBackButton, registerCancelModalOnBackButton } from '@ibgib/core-gib/dist./utils';\n// import { CommentIbGib_V1 } from '@ibgib/core-gib/dist/common/comment/comment-types.mjs';\n// import { SECRET_REL8N_NAME } from '@ibgib/core-gib/dist/common/encrypt/encrypt-constants.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../constants.mjs';\nimport { alertUser, promptForConfirm, promptForText } from '../helpers.web.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT || false;\n\n\n/**\n * Wrapper for alerting via atow capacitor modals.\n *\n * @returns FUNCTION that alerts (doesn't actually do the alert)\n */\nexport function getFnAlert(): ({ title, msg }: { title: string, msg: string }) => Promise<void> {\n    return async ({ title, msg }: { title: string, msg: string }) => {\n        // await Dialog.alert({ title, message: msg });\n        // const titlePlusMsg = `${title}: ${msg}`;\n        // console.log(titlePlusMsg);\n        // alert(titlePlusMsg)\n        await alertUser({ msg, title });\n    };\n}\n\n/**\n * Wrapper for prompting via custom dialog function.\n *\n * @returns FUNCTION that prompts (doesn't actually do the prompt, just creates\n * the function that will)\n */\nexport function getFnPrompt(): ({ title, msg }: { title: string, msg: string }) => Promise<string | null> {\n    return async ({ title, msg }: { title: string, msg: string }) => {\n        const lc = `[${getFnPrompt.name}]`;\n        let answer: string;\n        try {\n            if (!msg) { throw new Error(`msg required. (E: c39d1656b6b803e11bad46efe15b6823)`); }\n\n            answer = await promptForText({ title, msg });\n\n            // const titlePlusMsg = `${title}: ${msg}`;\n            // console.log(`${lc} ${titlePlusMsg}`);\n            // answer = window.prompt(titlePlusMsg) ?? '';\n            // if (logalot) { console.log(`${lc} answer: ${answer} (I: 89e4379f368c136a31e52107447b7b24)`); }\n\n            // const rl = readline.createInterface({ input: stdin, output: stdout });\n            // try {\n            //     const text = title ? `\\n# ${title}:\\n\\n${msg}\\n` : `${msg}\\n`;\n            //     answer = await rl.question(text);\n            //     if (logalot) { console.log(`${lc} text: ${text}. answer: ${answer} (I: 7f0375b3abd7eba9c75636d31bbca323)`); }\n            // } catch (error) {\n            //     throw error;\n            // } finally {\n            //     rl.close();\n            // }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        }\n        return answer || answer === '' ? answer : null;\n    };\n}\n\n/**\n * Wrapper for confirming via commandline/terminal prompt.\n *\n * @returns FUNCTION that prompts (doesn't actually do the prompt)\n */\nexport function getFnConfirm():\n    ({ title, msg, okButtonTitle, cancelButtonTitle }:\n        { title: string, msg: string, okButtonTitle?: string, cancelButtonTitle?: string }) => Promise<boolean> {\n    return async ({ title, msg, okButtonTitle, cancelButtonTitle }:\n        { title: string, msg: string, okButtonTitle?: string, cancelButtonTitle?: string }) => {\n        okButtonTitle ||= 'yes';\n        cancelButtonTitle ||= 'no';\n\n        if (okButtonTitle === cancelButtonTitle) { throw new Error(`okButtonTitle (${okButtonTitle}) must be different than cancelButtonTitle (${cancelButtonTitle}) (E: 254e92fed2e99edc362de337e8bf3123)`); }\n        // if (okButtonTitle[0] === cancelButtonTitle[0]) { throw new Error(`okButtonTitle (${okButtonTitle}) must start with a different character than cancelButtonTitle (${cancelButtonTitle}) (E: 8bdd34b0d90f479399d911af58df9190)`); }\n\n        let result = await promptForConfirm({\n            msg,\n            yesLabel: okButtonTitle,\n            noLabel: cancelButtonTitle,\n        });\n\n        return result;\n\n        // const promptFn = getFnPrompt();\n        // let result: string | null = null;\n        // do {\n        //     // result = await promptFn({ title, msg: `${msg} (${okButtonTitle}/${cancelButtonTitle})` });\n        //     result = await promptForConfirm({\n        //         title,\n        //         msg: `${msg} (${okButtonTitle}/${cancelButtonTitle})`\n        //     }) ?? null;\n        //     result = result ? result!.toLowerCase() : null;\n        // } while (!result);\n\n        // if (result === okButtonTitle![0].toLowerCase()) { result = okButtonTitle!; }\n        // return result === okButtonTitle;\n    };\n}\n\n/**\n * Prompts the user for a password using an ionic capacitor (atow) alert\n * controller with an input of type `'password'`.\n *\n *\n *\n * @returns either the password or null if cancelled\n */\nexport function getFnPromptPassword(): (title: string, msg: string) => Promise<string | null> {\n    const lc = `[${getFnPromptPassword.name}]`;\n    try {\n        throw new Error(`not implemented yet. i have added PromptPasswordFunction type in core-gib/core-types (E: 78c7dbb8958f8f353730d0dbb86b5423)`);\n        // if (!alertController) { throw new Error('alertController required.'); }\n        // let fnPromptPassword = async (title: string, msg: string) => {\n        //     const alert = await alertController.create({\n        //         header: title,\n        //         message: msg,\n        //         inputs: [\n        //             { name: 'password', type: 'password', label: 'Password: ', },\n        //         ],\n        //         buttons: ['OK', 'Cancel'],\n        //     });\n        //     await alert.present();\n        //     let result = await alert.onDidDismiss();\n        //     if (result?.data?.values?.password) {\n        //         return result!.data!.values!.password;\n        //     } else {\n        //         return null;\n        //     }\n        // };\n        // return fnPromptPassword;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\n/**\n * Creates a function with a single `space` arg. This fn when called shows a\n * modal to create an secret ibgib. If the user chooses to save, then the\n * modal will create the secret ibgib, save the transform result in the\n * given `space` (atow this is the local user space), and return the new\n * secret ibgib.\n */\nexport function getFn_promptCreateSecretIbGib(\n): (space: IbGibSpaceAny) => Promise<IbGib_V1 | undefined> {\n    const lc = `[${getFn_promptCreateSecretIbGib.name}]`;\n    return async (space: IbGibSpaceAny) => {\n        throw new Error(`not impl yet (E: 990b79f9b8c2302163cc656deceaf923)`);\n        // /** hacked untyped document reference to hack a solution to the back button leaving modals open. */\n        // try {\n        //     const modal = await common.modalController.create({\n        //         component: SecretModalFormComponent,\n        //     });\n        //     // have to register/clear modal for cancelling in case the user\n        //     // presses the back button while the modal is still visible\n        //     registerCancelModalOnBackButton(modal);\n        //     await modal.present();\n        //     let resModal = await modal.onWillDismiss();\n        //     // clear the cancel since it dismissed naturally\n        //     clearDoCancelModalOnBackButton();\n        //     if (resModal.data) {\n        //         const resNewSecret = <TransformResult<SecretIbGib_V1>>resModal.data;\n        //         await common.ibgibs.persistTransformResult({ resTransform: resNewSecret, space });\n        //         const addr = getIbGibAddr({ ibGib: resNewSecret.newIbGib });\n        //         if (logalot) { console.log(`${lc} created secret. addr: ${addr}`); }\n        //         await common.ibgibs.rel8ToSpecialIbGib({\n        //             type: \"secrets\",\n        //             rel8nName: SECRET_REL8N_NAME,\n        //             ibGibsToRel8: [resNewSecret.newIbGib],\n        //             space,\n        //         });\n        //         return resNewSecret.newIbGib;\n        //     } else {\n        //         // didn't create one\n        //         console.warn(`${lc} didn't create at this time.`);\n        //         return undefined;\n        //     }\n        // } catch (error) {\n        //     console.error(`${lc} error: ${extractErrorMsg(error)}`);\n        //     return undefined;\n        // }\n    }\n}\n\n/**\n * Creates a function with a single `space` arg. This fn when called shows a\n * modal to create an encryption ibgib. If the user chooses to save, then the\n * modal will create the encryption ibgib, save the transform result in the\n * given `space` (atow this is the local user space), and return the new\n * encryption ibgib.\n */\nexport function getFn_promptCreateEncryptionIbGib(\n    // common: CommonService,\n): (space: IbGibSpaceAny) => Promise<IbGib_V1 | undefined> {\n    throw new Error(`not impl yet (E: 69c7d552de7318a97457363adfd34f23)`);\n    // const lc = `[${getFn_promptCreateEncryptionIbGib.name}]`;\n    // return async (space: IbGibSpaceAny) => {\n    //     try {\n    //         const modal = await common.modalController.create({\n    //             component: EncryptionModalFormComponent,\n    //         });\n    //         // have to register/clear modal for cancelling in case the user\n    //         // presses the back button while the modal is still visible\n    //         registerCancelModalOnBackButton(modal);\n    //         await modal.present();\n    //         let resModal = await modal.onWillDismiss();\n    //         // clear the cancel since it dismissed naturally\n    //         clearDoCancelModalOnBackButton();\n    //         if (resModal.data) {\n    //             const resNewEncryption = <TransformResult<IbGib_V1<EncryptionData_V1>>>resModal.data;\n    //             await common.ibgibs.persistTransformResult({ resTransform: resNewEncryption, space });\n    //             const addr = getIbGibAddr({ ibGib: resNewEncryption.newIbGib });\n    //             if (logalot) { console.log(`${lc} created encryption. addr: ${addr}`); }\n    //             return resNewEncryption.newIbGib;\n    //         } else {\n    //             // didn't create one\n    //             console.warn(`${lc} didn't create at this time.`);\n    //             return undefined;\n    //         }\n    //     } catch (error) {\n    //         console.error(`${lc} error: ${extractErrorMsg(error)}`);\n    //         return undefined;\n    //     }\n    // }\n}\n\n/**\n * Creates a function with a single `space` arg. This fn when called shows a\n * modal to create an outerspace ibgib. If the user chooses to save, then the\n * modal will create the outerspace ibgib, save the transform result in the\n * given `space` (atow this is the local user space), and return the new\n * outerspace ibgib.\n */\nexport function getFn_promptCreateOuterSpaceIbGib(\n    // common: CommonService,\n): (space: IbGibSpaceAny) => Promise<IbGib_V1 | undefined> {\n    throw new Error(`not impl yet (E: e48ef8a7b4252cfe795dde791de99523)`);\n    // const lc = `[${getFn_promptCreateOuterSpaceIbGib.name}]`;\n    // return async (space: IbGibSpaceAny) => {\n    //     try {\n    //         const modal = await common.modalController.create({\n    //             component: OuterspaceModalFormComponent,\n    //         });\n    //         // have to register/clear modal for cancelling in case the user\n    //         // presses the back button while the modal is still visible\n    //         registerCancelModalOnBackButton(modal);\n    //         await modal.present();\n    //         let resModal = await modal.onWillDismiss();\n    //         // clear the cancel since it dismissed naturally\n    //         clearDoCancelModalOnBackButton();\n    //         if (resModal.data) {\n    //             const resOuterSpace = <TransformResult<OuterSpaceIbGib>>resModal.data;\n    //             await common.ibgibs.persistTransformResult({ resTransform: resOuterSpace, space });\n    //             const addr = getIbGibAddr({ ibGib: resOuterSpace.newIbGib });\n    //             if (logalot) { console.log(`${lc} created outerspace. addr: ${addr}`); }\n    //             return resOuterSpace.newIbGib;\n    //         } else {\n    //             // didn't create one\n    //             console.warn(`${lc} didn't create outerspace at this time.`);\n    //             return undefined;\n    //         }\n    //     } catch (error) {\n    //         console.error(`${lc} error: ${extractErrorMsg(error)}`);\n    //         return undefined;\n    //     }\n    // }\n}\n\n/**\n * Creates a function with a single `space` arg. This fn when called shows a\n * modal to mutate a pic ibgib. If the user chooses to save, then the modal will\n * perform the mutation, save the transform result in the given `space`, and\n * return the new pic ibgib.\n */\n// export function getFn_promptUpdatePicIbGib(\n//     common: CommonService,\n// ): (space: IbGibSpaceAny, picIbGib: PicIbGib_V1) => Promise<UpdatePicPromptResult | undefined> {\n//     const lc = `[${getFn_promptUpdatePicIbGib.name}]`;\n//     return async (space: IbGibSpaceAny, picIbGib: PicIbGib_V1) => {\n//         try {\n//             const modal = await common.modalController.create({\n//                 component: UpdatePicModalFormComponent,\n//                 componentProps: { picIbGib, space },\n//             });\n//             // have to register/clear modal for cancelling in case the user\n//             // presses the back button while the modal is still visible\n//             registerCancelModalOnBackButton(modal);\n//             await modal.present();\n//             let resModal = await modal.onWillDismiss();\n//             // clear the cancel since it dismissed naturally\n//             clearDoCancelModalOnBackButton();\n//             if (resModal.data) {\n//                 const result = <UpdatePicPromptResult>resModal.data;\n//                 const [resCreatePic, _resCreateBin] = result;\n//                 const addr = getIbGibAddr({ ibGib: resCreatePic.newIbGib });\n//                 if (logalot) { console.log(`${lc} updated pic. addr: ${addr}`); }\n//                 return result;\n//             } else {\n//                 // didn't create one\n//                 console.warn(`${lc} didn't create at this time.`);\n//                 return undefined;\n//             }\n//         } catch (error) {\n//             console.error(`${lc} error: ${extractErrorMsg(error)}`);\n//             return undefined;\n//         }\n//     }\n// }\n\n/**\n * Creates a function with a single `space` arg. This fn when called shows a\n * modal to mutate a comment ibgib. If the user chooses to save, then the modal will\n * perform the mutation, save the transform result in the given `space`, and\n * return the new comment ibgib.\n */\n// export function getFn_promptUpdateCommentIbGib(\n//     common: CommonService,\n// ): (space: IbGibSpaceAny, commentIbGib: CommentIbGib_V1) => Promise<UpdateCommentPromptResult | undefined> {\n//     const lc = `[${getFn_promptUpdateCommentIbGib.name}]`;\n//     return async (space: IbGibSpaceAny, commentIbGib: CommentIbGib_V1) => {\n//         try {\n//             const modal = await common.modalController.create({\n//                 component: UpdateCommentModalFormComponent,\n//                 componentProps: { commentIbGib, space },\n//             });\n//             // have to register/clear modal for cancelling in case the user\n//             // presses the back button while the modal is still visible\n//             registerCancelModalOnBackButton(modal);\n//             await modal.present();\n//             let resModal = await modal.onWillDismiss();\n//             // clear the cancel since it dismissed naturally\n//             clearDoCancelModalOnBackButton();\n//             if (resModal.data) {\n//                 const resCreateComment = <UpdateCommentPromptResult>resModal.data;\n//                 const addr = getIbGibAddr({ ibGib: resCreateComment.newIbGib });\n//                 if (logalot) { console.log(`${lc} updated comment. addr: ${addr}`); }\n//                 return resCreateComment;\n//             } else {\n//                 // didn't create one\n//                 console.warn(`${lc} didn't create at this time.`);\n//                 return undefined;\n//             }\n//         } catch (error) {\n//             console.error(`${lc} error: ${extractErrorMsg(error)}`);\n//             return undefined;\n//         }\n//     }\n// }\n\n/**\n * Creates a function with a single `space` arg. This fn when called shows a\n * modal to create a robbot ibgib. If the user chooses to save, then the modal will\n * perform the mutation, save the transform result in the given `space`, and\n * return the new pic ibgib.\n */\n// export function getFn_promptRobbotIbGib(\n//     common: CommonService,\n// ): (space: IbGibSpaceAny, ibGib: RobbotIbGib_V1) => Promise<RobbotPromptResult | undefined> {\n//     const lc = `[${getFn_promptRobbotIbGib.name}]`;\n//     return async (space: IbGibSpaceAny, ibGib: RobbotIbGib_V1) => {\n//         try {\n//             const modal = await common.modalController.create({\n//                 component: RobbotModalFormComponent,\n//                 componentProps: { ibGib, space },\n//             });\n//             // have to register/clear modal for cancelling in case the user\n//             // presses the back button while the modal is still visible\n//             registerCancelModalOnBackButton(modal);\n//             await modal.present();\n//             let resModal = await modal.onWillDismiss();\n//             // clear the cancel since it dismissed naturally\n//             clearDoCancelModalOnBackButton();\n//             if (resModal.data) {\n//                 const result = <RobbotPromptResult>resModal.data;\n//                 return result;\n//             } else {\n//                 // didn't create one\n//                 console.warn(`${lc} didn't create at this time.`);\n//                 return undefined;\n//             }\n//         } catch (error) {\n//             console.error(`${lc} error: ${extractErrorMsg(error)}`);\n//             return undefined;\n//         }\n//     }\n// }\n\n/**\n * Creates a function with a single `space` arg. This fn when called shows a\n * modal to create a app ibgib. If the user chooses to save, then the modal will\n * perform the mutation, save the transform result in the given `space`, and\n * return the new pic ibgib.\n */\n// export function getFn_promptAppIbGib(\n//     common: CommonService,\n// ): (space: IbGibSpaceAny, ibGib: AppIbGib_V1) => Promise<AppPromptResult | undefined> {\n//     const lc = `[${getFn_promptAppIbGib.name}]`;\n//     return async (space: IbGibSpaceAny, ibGib: AppIbGib_V1) => {\n//         try {\n//             const modal = await common.modalController.create({\n//                 component: AppModalFormComponent,\n//                 componentProps: { ibGib, space },\n//             });\n//             // have to register/clear modal for cancelling in case the user\n//             // presses the back button while the modal is still visible\n//             registerCancelModalOnBackButton(modal);\n//             await modal.present();\n//             let resModal = await modal.onWillDismiss();\n//             // clear the cancel since it dismissed naturally\n//             clearDoCancelModalOnBackButton();\n//             if (resModal.data) {\n//                 const result = <AppPromptResult>resModal.data;\n//                 return result;\n//             } else {\n//                 // didn't create one\n//                 console.warn(`${lc} didn't create at this time.`);\n//                 return undefined;\n//             }\n//         } catch (error) {\n//             console.error(`${lc} error: ${extractErrorMsg(error)}`);\n//             return undefined;\n//         }\n//     }\n// }\n", "import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';\nimport { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/index.mjs';\nimport { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';\nimport { WitnessBase_V1, } from '../witness-base-v1.mjs';\nimport {\n    GetDependencyGraphResultData, IbGibSpace, IbGibSpaceData,\n    IbGibSpaceOptionsCmd, IbGibSpaceOptionsCmdModifier, IbGibSpaceOptionsData,\n    IbGibSpaceOptionsIbGib, IbGibSpaceOptionsRel8ns, IbGibSpaceRel8ns,\n    IbGibSpaceResultData, IbGibSpaceResultIbGib, IbGibSpaceResultRel8ns\n} from './space-types.mjs';\nimport { getSpaceResultMetadata } from './space-helper.mjs';\nimport { getDependencyGraph, GetGraphOptions } from '../../common/other/graph-helper.mjs';\nimport { argy_, resulty_ } from '../../witness/witness-helper.mjs';\nimport { IbGibCacheService } from '../../common/cache/cache-types.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT;\n\nexport interface IbGibSpaceAny\n    extends SpaceBase_V1<any, any, any, any, any, any, any> {\n}\n\nexport abstract class SpaceBase_V1<\n    TIbGib extends IbGib_V1 = IbGib_V1,\n    TOptionsData extends IbGibSpaceOptionsData = IbGibSpaceOptionsData,\n    TOptionsRel8ns extends IbGibSpaceOptionsRel8ns = IbGibSpaceOptionsRel8ns,\n    TOptionsIbGib extends IbGibSpaceOptionsIbGib<TIbGib, TOptionsData, TOptionsRel8ns>\n    = IbGibSpaceOptionsIbGib<TIbGib, TOptionsData, TOptionsRel8ns>,\n    TResultData extends IbGibSpaceResultData = IbGibSpaceResultData,\n    TResultRel8ns extends IbGibSpaceResultRel8ns = IbGibSpaceResultRel8ns,\n    TResultIbGib extends IbGibSpaceResultIbGib<TIbGib, TResultData, TResultRel8ns>\n    = IbGibSpaceResultIbGib<TIbGib, TResultData, TResultRel8ns>,\n    TData extends IbGibSpaceData = IbGibSpaceData,\n    TRel8ns extends IbGibSpaceRel8ns = IbGibSpaceRel8ns,\n>\n    extends WitnessBase_V1<\n        TOptionsData, TOptionsRel8ns, TOptionsIbGib,\n        TResultData, TResultRel8ns, TResultIbGib,\n        TData, TRel8ns>\n    implements IbGibSpace<TIbGib, TOptionsData, TOptionsRel8ns, TOptionsIbGib, TResultData, TResultRel8ns, TResultIbGib, TData, TRel8ns> {\n\n    /**\n     * Log context for convenience with logging. (Ignore if you don't want to use this.)\n     */\n    protected lc: string = `[${SpaceBase_V1.name}]`;\n\n    /**\n     * Optional cache service. hmm...\n     */\n    cacheSvc: IbGibCacheService | undefined;\n\n    // getSpaceIb(classname: string): string {\n    //     const lc = `${this.lc}[${this.getSpaceIb.name}]`;\n    //     if (!classname) {\n    //         classname = this.lc?.replace('[','').replace(']','') || SpaceBase_V1.name+'_descendant';\n    //         console.warn(`${lc} classname is falsy. Using ${classname}.`);\n    //     }\n    //     const name = this.data?.name || IBGIB_SPACE_NAME_DEFAULT;\n    //     const id = this.data?.uuid || undefined;\n    //     return `witness space ${classname} ${name} ${id}`;\n    // }\n\n    constructor(initialData?: TData, initialRel8ns?: TRel8ns) {\n        super(initialData, initialRel8ns);\n        this.initialized = this.initialize();\n    }\n\n    /**\n     * In a Space, we are concerned with getting ibGibs out of and putting ibGibs into a \"space\".\n     *\n     * So in this base, we take the incoming arg and divert it multiple ways, depending on our settings.\n     */\n    protected async witnessImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.witnessImpl.name}]`;\n        if (logalot) { console.log(`${lc}`); }\n\n        // do the thing\n        let result = await this.routeAndDoCommand({\n            cmd: arg.data!.cmd,\n            cmdModifiers: arg.data!.cmdModifiers ?? [],\n            arg,\n        });\n\n        // persist the arg and result if we're configured to do so\n        // if (result && this.data.persistOptsAndResultIbGibs) {\n        //     try {\n        //         await this.persistOptsAndResultIbGibs({arg, result});\n        //     } catch (error) {\n        //         const emsg = `${lc} ${error.message}`;\n        //         console.error(emsg);\n        //     }\n        // }\n\n        return result;\n    }\n\n    protected abstract persistOptsAndResultIbGibs({ arg, result }:\n        { arg: TOptionsIbGib, result: TResultIbGib }): Promise<void>;\n\n    /**\n     * Routes the given `cmd` to the correct handling function in the space,\n     * and executes that function.\n     *\n     * Override this if you have custom commands to handle.\n     * Check for those first, and if not among them, call this\n     * via `super.doCommand(...)`. If cmd is still not found,\n     * this will throw.\n     */\n    protected routeAndDoCommand<TCmdModifier extends IbGibSpaceOptionsCmdModifier = IbGibSpaceOptionsCmdModifier>({\n        cmd,\n        cmdModifiers,\n        arg,\n    }: {\n        cmd: IbGibSpaceOptionsCmd | string,\n        cmdModifiers: (TCmdModifier | string)[],\n        arg: TOptionsIbGib,\n    }): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.routeAndDoCommand.name}]`;\n        switch (cmd) {\n            case IbGibSpaceOptionsCmd.get:\n                if ((cmdModifiers ?? []).length === 0) {\n                    return this.get(arg);\n                } else if (cmdModifiers.includes('can')) {\n                    return this.canGet(arg);\n                } else if (cmdModifiers.includes('latest')) {\n                    if (cmdModifiers.includes('addrs')) {\n                        return this.getLatestAddrs(arg);\n                    } else {\n                        return this.getLatestIbGibs(arg);\n                    }\n                } else if (cmdModifiers.includes('tjps')) {\n                    if (cmdModifiers.includes('addrs')) {\n                        return this.getTjpAddrs(arg);\n                    } else {\n                        return this.getTjpIbGibs(arg);\n                    }\n                } else if (cmdModifiers.includes('addrs')) {\n                    return this.getAddrs(arg);\n                } else if (cmdModifiers.includes('dependency-graph')) {\n                    return this.getDependencyGraph(arg);\n                } else {\n                    return this.get(arg);\n                }\n\n            case IbGibSpaceOptionsCmd.put:\n                if ((cmdModifiers ?? []).length === 0) {\n                    return this.put(arg);\n                } else if (cmdModifiers.includes('can')) {\n                    return this.canPut(arg);\n                } else {\n                    return this.put(arg);\n                }\n\n            case IbGibSpaceOptionsCmd.delete:\n                if ((cmdModifiers ?? []).length === 0) {\n                    return this.delete(arg);\n                } else if (cmdModifiers.includes('can')) {\n                    return this.canDelete(arg);\n                } else {\n                    return this.delete(arg);\n                }\n\n            default:\n                throw new Error(`${lc} unknown cmd: ${cmd}. cmdModifiers: ${cmdModifiers}`);\n        }\n    }\n\n    protected get(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.getImpl(arg); }\n    protected abstract getImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined>;\n\n    protected put(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.putImpl(arg); }\n    protected abstract putImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined>;\n\n    protected delete(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.deleteImpl(arg); }\n    protected deleteImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.deleteImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * Get all (public?) addrs in space.\n     *\n     * @optional method for space.\n     *\n     * @returns all addresses in space (that it wants to reveal).\n     */\n    protected getAddrs(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.getAddrsImpl(arg); }\n    protected getAddrsImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.getAddrsImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * Get latest ibGibs for given ibGib addresses.\n     *\n     * Usually I pass in the tjp address(es) if I have them.\n     *\n     * @optional method for space.\n     *\n     * @returns latest ibGibs in timelines for each given ibgib address.\n     */\n    protected getLatestIbGibs(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.getLatestIbGibsImpl(arg); }\n    protected getLatestIbGibsImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.getLatestIbGibsImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * Get latest addrs for given ibGib(s)/address(es).\n     *\n     * Usually I pass in the tjp address(es) if I have them.\n     *\n     * @optional method for space.\n     *\n     * @returns latest addrs in timelines for each given ibgib address.\n     */\n    protected getLatestAddrs(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.getLatestAddrsImpl(arg); }\n    protected getLatestAddrsImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.getLatestAddrsImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * Get temporal junction point ibgibs for given ibgib(s) or address(es).\n     *\n     * @optional method for space.\n     *\n     * @returns tjp ibgib for each given ibgib/address.\n     */\n    protected getTjpIbGibs(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.getTjpIbGibsImpl(arg); }\n    protected getTjpIbGibsImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.getTjpIbGibsImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * Get temporal junction point addr(s) for given ibgib(s) or address(es).\n     *\n     * @optional method for space.\n     *\n     * @returns tjp addrs in timelines for each given ibgib/address.\n     */\n    protected getTjpAddrs(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.getTjpAddrsImpl(arg); }\n    protected getTjpAddrsImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.getTjpAddrsImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * Supposed to be a check on either authorization, accessibility, existence...\n     *\n     * @notimplementedyet\n     */\n    protected canGet(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.canGetImpl(arg); }\n    protected canGetImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.canGetImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * Supposed to be a check on either authorization, accessibility, existence...\n     *\n     * @notimplementedyet\n     */\n    protected canPut(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.canPutImpl(arg); }\n    protected canPutImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.canPutImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * Supposed to be a check on either authorization, accessibility, existence...\n     *\n     * @notimplementedyet\n     */\n    protected canDelete(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.canPutImpl(arg); }\n    protected canDeleteImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.canDeleteImpl.name}]`;\n        throw new Error(`${lc} not implemented in base class`);\n    }\n\n    /**\n     * gets the entire dependency graph(s) of incoming addr(s).\n     * \n     * NOTE: Caller will have to manually convert the result.ibGibs to a flag\n     * ibgib graph to match the existing {@link getDependencyGraph} return if\n     * desired. This should be a trivial conversion though, as the keys to the\n     * flat graph are just the {@link getIbGibAddr} on the ibGib itself.\n     * \n     * @returns resulty ibgib with {@link GetDependencyGraphResultData}\n     */\n    protected getDependencyGraph(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> { return this.getDependencyGraphImpl(arg); }\n    /**\n     * Default implementation of getDependencyGraph uses the helper function\n     * {@link getDependencyGraph} in space-helpers.mts.\n     * \n     * Override this in subclasses for optimized behavior (e.g. Postgres).\n     */\n    protected async getDependencyGraphImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.getDependencyGraphImpl.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 0e5fe807a0169224781f6c2833f34826)`); }\n            if (!arg.data) { throw new Error(`(UNEXPECTED) arg.data falsy? (E: 45eba816295a97a0e55f981861a03f26)`); }\n            if ((arg.data.ibGibAddrs ?? []).length === 0) {\n                throw new Error(`arg.data.ibGibAddrs is falsy/empty (E: 70adc939c7b80c9938d8fa18fd7c5826)`);\n            }\n            const opts: GetGraphOptions = {\n                space: this,\n                ibGibAddrs: arg.data.ibGibAddrs!,\n                live: (arg.data as any).live || true,\n            };\n            const graph = await getDependencyGraph(opts);\n            const ibGibs = Object.values(graph) as TIbGib[];\n            const resultData: GetDependencyGraphResultData = {\n                optsAddr: getIbGibAddr({ ibGib: arg }),\n                count: ibGibs.length,\n                addrs: Object.keys(graph),\n            };\n            return this.resulty({\n                resultData: resultData as any as TResultData,\n                ibGibs,\n            });\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Centralized location for general argument validation for a given witness.\n     *\n     * In the case of spaces, this is where I usually put my common validation\n     * for various cases on cmd+modifier combinations.\n     *\n     * @returns validation error string, empty if no errors.\n     */\n    protected async validateWitnessArg(arg: TOptionsIbGib): Promise<string[]> {\n        const lc = `${this.lc}[${this.validateWitnessArg.name}]`;\n        let errors: string[] = [];\n        try {\n            errors = await super.validateWitnessArg(arg);\n            if (!arg.data) {\n                errors.push(`arg.data required (E: 8ee544d7d88a45c6adcbc15838a283a7)`);\n                return errors; // <<<< returns immediately\n            }\n            if (!this.data) {\n                errors.push(`this.data required (E: 64f80642d7de44329355d6f907e272c8)`);\n                return errors; /* <<<< returns early */\n            }\n\n            const { cmd, ibGibAddrs, } = arg.data!;\n            let cmdModifiers = arg.data!.cmdModifiers ?? [];\n            const ibGibs = arg.ibGibs;\n            if (!cmd) { errors.push(`arg.data.cmd required (E: 72a11ee87a0d4896bcacd65a9c0284d9)`); }\n            if (!Object.values(IbGibSpaceOptionsCmd).includes((cmd as any))) { errors.push(`unknown arg.data.cmd: ${cmd}. (E: 95282ce61e97429f8049e61ec9f14f0b)`); }\n            const ibGibAddrsLength = ibGibAddrs?.length ?? 0;\n            if (\n                cmd === IbGibSpaceOptionsCmd.get &&\n                !cmdModifiers?.includes('addrs') && // we allow get addrs to be get ALL addrs\n                !cmdModifiers?.includes('latest') &&\n                ibGibAddrsLength === 0\n            ) {\n                errors.push(`ibGibAddrs required when cmd is ${cmd}. (E: ee55a3f60b90423cbe054f27c34ab7d5)`);\n            }\n            if (cmd === IbGibSpaceOptionsCmd.put) {\n                if (logalot) { console.log(`${lc} validate put cmd`); }\n                const ibGibsLength = ibGibs?.length ?? 0;\n                if (ibGibsLength === 0) {\n                    errors.push(`ibGibs required when cmd is ${cmd}. (E: b3a422169f7344a48a1d44e7ad1ba44e)`);\n                } else if (this.data.validateIbGibAddrsMatchIbGibs) {\n                    // #region validate ibGib map to ibGibAddrs\n                    if (logalot) { console.log(`${lc} validateIbGibAddrsMatchIbGibs true, so doing so.`); }\n\n                    // confirm the incoming ibGibs match up with the addresses\n                    // we have in `ibGibAddrs`.\n                    if (ibGibsLength !== ibGibAddrsLength) {\n                        errors.push(`ibGibsLength !== ibGibAddrsLength and this.data.validateIbGibAddrsMatchIbGibs is true. (E: 6c6bf824ab32443aa4d6b8bf4f8113dd)`);\n                    } else {\n                        // lengths match, so validate ibgibs\n                        if (logalot) { console.log(`${lc} validateIbGibAddrsMatchIbGibs, lengths match. validating intrinsically`); }\n                        const ibGibAddrsCopy = ibGibAddrs!.concat();\n                        for (let i = 0; i < ibGibs!.length; i++) {\n                            const ibGib = ibGibs![i];\n                            const intrinsicErrors = await validateIbGibIntrinsically({ ibGib });\n                            if (intrinsicErrors?.length ?? 0 > 0) {\n                                const addr = getIbGibAddr({ ibGib });\n                                // for privacy it might be nice to not have the\n                                // addr in the error msg, but it's too blind to\n                                // only have the gib right now.\n                                intrinsicErrors!.forEach(x => errors.push(`(${addr}) ERROR: ${x}`));\n                            } else {\n                                // intrinsically valid, but ensure the ibGib\n                                // addr maps 1-to-1 in ibGibAddrs\n                                const xAddr = getIbGibAddr({ ibGib });\n                                const xIndex = ibGibAddrsCopy.indexOf(xAddr);\n                                if (xIndex === -1) {\n                                    errors.push(`ibGibAddrs don't map to calculated ibGib addrs. calculated Addr: (${xAddr}) (E: b21b3a7a74db43e5a8722acc97274646)`);\n                                    break;\n                                } else {\n                                    ibGibAddrsCopy.splice(xIndex, 1);\n                                }\n                            }\n                        }\n                    }\n\n                    // #endregion validate ibGib map to ibGibAddrs\n                }\n            }\n            return errors;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (errors?.length > 0) { console.error(`${lc} errors: ${errors}`); }\n        }\n    }\n\n    /**\n     * builds an arg ibGib.\n     *\n     * wrapper convenience to avoid long generic calls.\n     */\n    async argy({\n        argData,\n        ibMetadata,\n        noTimestamp,\n        ibGibs,\n    }: {\n        argData: TOptionsData,\n        ibMetadata?: string,\n        noTimestamp?: boolean,\n        ibGibs?: TIbGib[],\n    }): Promise<TOptionsIbGib> {\n        const arg = await argy_<TOptionsData, TOptionsRel8ns, TOptionsIbGib>({\n            argData,\n            ibMetadata,\n            noTimestamp\n        });\n\n        if (ibGibs) { arg.ibGibs = ibGibs; }\n\n        return arg;\n    }\n\n    /**\n     * builds a result ibGib.\n     *\n     * wrapper convenience to avoid long generic calls.\n     */\n    async resulty({\n        resultData,\n        ibGibs,\n    }: {\n        resultData: TResultData,\n        ibGibs?: TIbGib[],\n    }): Promise<TResultIbGib> {\n        const result = await resulty_<TResultData, TResultIbGib>({\n            ibMetadata: getSpaceResultMetadata({ space: this }),\n            resultData,\n        });\n        if (ibGibs) { result.ibGibs = ibGibs; }\n        return result;\n    }\n\n}\n", "import { clone, extractErrorMsg, getTimestampInTicks, hash, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { Gib, Ib, IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';\nimport { getIbAndGib, getIbGibAddr, } from '@ibgib/ts-gib/dist/helper.mjs';\nimport { IbGib_V1, IbGibRel8ns_V1, GIB, ROOT, isPrimitive, getGib, getGibInfo, GIB_DELIMITER, } from '@ibgib/ts-gib/dist/V1/index.mjs';\nimport { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../../../core-constants.mjs';\nimport { SpaceBase_V1 } from '../space-base-v1.mjs';\nimport {\n    IbGibSpaceData, IbGibSpaceOptionsData, IbGibSpaceOptionsRel8ns,\n    IbGibSpaceOptionsIbGib, IbGibSpaceResultData, IbGibSpaceResultRel8ns,\n    IbGibSpaceResultIbGib,\n    IbGibSpaceData_Subpathed\n} from '../space-types.mjs';\nimport { argy_ } from '../../witness-helper.mjs';\nimport { isBinary, getBinHashAndExt, hasTjp, isTjp_Naive, getTimestampInfo, } from '../../../common/other/ibgib-helper.mjs';\nimport { parseSpaceIb, getSpaceIb, getSpecialIbGib, getTjpIbGib, } from '../space-helper.mjs';\nimport { DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS, IBGIB_SPACE_NAME_DEFAULT, ZERO_SPACE_ID } from '../space-constants.mjs';\nimport {\n    Directory, Encoding,\n    GetIbGibFileOpts, GetIbGibFileResult,\n    PutIbGibFileOpts, PutIbGibFileResult,\n    DeleteIbGibFileOpts, DeleteIbGibFilesResult,\n} from './filesystem-types.mjs';\nimport {\n    IBGIB_BASE_SUBPATH, IBGIB_SPACE_SUBPATH_DEFAULT, IBGIB_BASE_DIR,\n    IBGIB_ENCODING, IBGIB_IBGIBS_SUBPATH, IBGIB_META_SUBPATH,\n    DEFAULT_FILESYSTEM_SPACE_DESCRIPTION,\n    IBGIB_BIN_SUBPATH,\n    IBGIB_DNA_SUBPATH,\n    DEFAULT_LONG_PATH_LENGTH,\n    IBGIB_LONG_SUBPATH,\n    DEFAULT_PATH_SEPARATOR,\n    ARBITRARY_IB_SUBSTRING_LENGTH_FOR_MITIGATE_LONG_PATH,\n} from './filesystem-constants.mjs';\nimport { isMetaStone, parseMetaStoneIb, validateCommonMetaStoneIbGib } from '../../../common/meta-stone/meta-stone-helper.mjs';\nimport { MetaStoneIbGib_V1, MetaStoneIbInfo } from '../../../common/meta-stone/meta-stone-types.mjs';\nimport { META_STONE_TARGET_REL8N_NAME } from '../../../common/meta-stone/meta-stone-constants.mjs';\nimport { BinIbGib_V1 } from '../../../common/bin/bin-types.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT;\n\n// #region tmp\n\n// export async function tryRead({\n//     path,\n//     directory,\n//     encoding,\n// }: {\n//     path: string,\n//     directory: string,\n//     encoding: string,\n//     // directory: Directory,\n//     // encoding: Encoding,\n// }): Promise<string | null> {\n//     const lc = `[${tryRead.name}]`;\n//     try {\n//         if (logalot) {\n//             console.log(`${lc} starting...`);\n//             if (path.includes('bootstrap^gib')) { console.log(`${lc} trying bootstrap^gib... (I: dacfdbe5a2d640ab947a7c17e3c56f78)`); }\n//         }\n//         throw new Error(`not implemented over from ionic-space yet (E: 3f60f152a449467a3ed53ac3c28f8523)`);\n//         // const resRead = await Filesystem.readFile({\n//         //     path: path,\n//         //     directory,\n//         //     encoding,\n//         // });\n//         // if (logalot) { console.log(`${lc} path found: ${path} (I: 82e3ad9821bd4bf8a54c8facc61dbad0)`); }\n//         // return resRead;\n//     } catch (error) {\n//         if (logalot) { console.log(`${lc} path not found: ${path} (I: 1fde689d29aa47fcb589b3e7dac8929b)`); }\n//         return null;\n//     } finally {\n//         if (logalot) { console.log(`${lc} complete. (I: e2615c944a464cd48a5635fe401562d9)`); }\n//     }\n// }\n\n// #endregion tmp\n\n// #region Space related interfaces/constants\n\n/**\n * This is the shape of data about this space itself (not the contained ibgibs' spaces).\n */\nexport interface FilesystemSpaceData_V1 extends IbGibSpaceData_Subpathed {\n    /**\n     * Redeclared here to make this required (not optional)\n     */\n    uuid: string;\n    baseDir: Directory;\n    encoding: Encoding;\n}\n\n/**\n * Used in bootstrapping.\n *\n * If you change this, please bump the version\n *\n * (but of course won't be the end of the world when this doesn't happen).\n */\nconst DEFAULT_FILESYSTEM_SPACE_DATA_V1: FilesystemSpaceData_V1 = {\n    version: '3',\n    uuid: ZERO_SPACE_ID,\n    name: IBGIB_SPACE_NAME_DEFAULT,\n    classname: 'FilesystemSpace_V1',\n    baseDir: IBGIB_BASE_DIR,\n    encoding: IBGIB_ENCODING,\n    baseSubPath: IBGIB_BASE_SUBPATH,\n    spaceSubPath: IBGIB_SPACE_SUBPATH_DEFAULT,\n    ibgibsSubPath: IBGIB_IBGIBS_SUBPATH,\n    metaSubPath: IBGIB_META_SUBPATH,\n    binSubPath: IBGIB_BIN_SUBPATH,\n    dnaSubPath: IBGIB_DNA_SUBPATH,\n    longSubPath: IBGIB_LONG_SUBPATH,\n    longPathLength: DEFAULT_LONG_PATH_LENGTH,\n    mitigateLongPaths: true,\n    persistOptsAndResultIbGibs: false,\n    validateIbGibAddrsMatchIbGibs: false,\n    longPollingIntervalMs: DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS,\n    allowPrimitiveArgs: false,\n    catchAllErrors: true,\n    description: DEFAULT_FILESYSTEM_SPACE_DESCRIPTION,\n    trace: false,\n}\n\n/** Marker interface atm */\nexport interface FilesystemSpaceRel8ns_V1 extends IbGibRel8ns_V1 { }\n\n/**\n * Space options involve whether we're getting/putting ibgibs categorized as\n * meta, bin, dna.\n *\n * We'll leverage the fact that we don't need to get dna very often, and that\n * meta ibgibs act differently and are recorded differently.\n *\n * For example, we don't necessarily want to keep the past of certain meta\n * objects, because it may change (and thus grow) too quickly.\n */\nexport interface FilesystemSpaceOptionsData extends IbGibSpaceOptionsData {\n    /**\n     * Are we looking for a DNA ibgib?\n     */\n    isDna?: boolean;\n}\n\nexport interface FilesystemSpaceOptionsRel8ns extends IbGibSpaceOptionsRel8ns {\n}\n\n/** Marker interface atm */\nexport interface FilesystemSpaceOptionsIbGib<TData extends FilesystemSpaceOptionsData, TRel8ns extends FilesystemSpaceOptionsRel8ns>\n    extends IbGibSpaceOptionsIbGib<IbGib_V1, TData, TRel8ns> {\n}\n\n/** Marker interface atm */\nexport interface FilesystemSpaceResultData extends IbGibSpaceResultData {\n}\n\nexport interface FilesystemSpaceResultRel8ns extends IbGibSpaceResultRel8ns {\n}\n\nexport interface FilesystemSpaceResultIbGib<TData extends FilesystemSpaceResultData, TRel8ns extends FilesystemSpaceResultRel8ns>\n    extends IbGibSpaceResultIbGib<IbGib_V1, FilesystemSpaceResultData, FilesystemSpaceResultRel8ns> {\n}\n\n// #endregion\n\n/**\n * basic validation for filesystem space\n */\nexport async function validateFilesystemSpace_V1Intrinsically({ space }:\n    { space: FilesystemSpace_V1<any, any, any, any> }): Promise<string[] | null> {\n    const lc = `[${validateFilesystemSpace_V1Intrinsically.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: fcfe57145426ab4a5a0e961e87001922)`); }\n        const errors: string[] = (await validateIbGibIntrinsically({ ibGib: space })) ?? [];\n\n        const { ib, gib, data, rel8ns } = space;\n\n        if (!ib) { errors.push('ib required. (E: a67fbb88841048f0a5bbf5ea266d7789)'); }\n        if (!gib) { errors.push('gib required. (E: c811ce87f1e042769d0a43ff56091e22)'); }\n        if (gib === GIB) { errors.push('gib cannot be primitive. (E: 5933bb715efc4e7cb74383d69d55ca64)'); }\n\n        if (!data) {\n            errors.push('data required. (E: 0b358c37f244422a96c7edb638b5ec00)');\n            return errors;\n        }\n\n        if (!data.name) { errors.push('space name required. (E: f66412cd4d4e43ebb3cef55f91914f7c)') }\n\n        if (!data.baseDir) { errors.push(`data.baseDir required. (E: 9df11d82a4bc4da38765c8e21ed9bace)`) }\n        if (!data.baseSubPath) { errors.push(`data.baseSubPath required. (E: a44d3afec8b345d49480a640b33edfcd)`) }\n        if (!data.binSubPath) { errors.push(`data.binSubPath required. (E: 52896e2405e842ebb7b5b11419556873)`) }\n        if (!data.dnaSubPath) { errors.push(`data.dnaSubPath required. (E: 698a7853722b4e99927570231c350434)`) }\n        if (!data.ibgibsSubPath) { errors.push(`data.ibgibsSubPath required. (E: f254076e67324969b5b2361d1fc514fb)`) }\n        if (!data.metaSubPath) { errors.push(`data.metaSubPath required. (E: b675033dd2584fafbfe7a96d0c33b444)`) }\n        if (data.n && typeof data.n !== 'number') { errors.push(`data.n must be a number. (E: a86fc07807594c90a4e67f9a7605b1b1)`) }\n        if (data.n === undefined) {\n            // the very first space record (tjp) has an undefined n and no rel8ns\n            if (rel8ns) { errors.push(`rel8ns not expected when data.n is falsy (custom temporal junction point indicator I suppose...) (E: ef4317e9db9147abba66d75ffe63740b)`); }\n        }\n        if (!data.spaceSubPath) { errors.push(`data.spaceSubPath required. (E: 477d02f719bc45f08d133681c6e3f492)`) }\n        if (!data.uuid) { errors.push(`data.uuid required. (E: 7ac3e7ae16ef47b78414b07b18d1a740)`) }\n        if (!data.encoding) { errors.push(`data.encoding required. (E: 4f4baf9c9adf4a11a3357b7cfe450b92)`) }\n        /** should probably get this from Capacitor... */\n        const validEncodings = [\"utf8\", \"ascii\", \"utf16\"];\n        if (!validEncodings.includes(data.encoding)) {\n            errors.push(`invalid encoding: ${data.encoding}. validEncodings: ${validEncodings.join(', ')} (E: 0c910168b12f4f22935c3d23b23bbfd8)`);\n        }\n\n        // ensure ib matches up with internal data\n        const { spaceClassname, spaceId, spaceName } = parseSpaceIb({ spaceIb: ib });\n        if (data.classname && (spaceClassname !== data.classname)) {\n            errors.push(`ib's spaceClassname (${spaceClassname}) must match data.classname (${data.classname}) (E: 57977f50d9bb4c64a0d06544023742a1)`);\n        }\n        if (spaceId !== data.uuid) {\n            errors.push(`ib's spaceId (${spaceId}) must match data.uuid (${data.uuid}) (E: 03dd4d0d119b48a8a2d97c1444e2239e)`);\n        }\n        if (spaceName !== data.name) {\n            errors.push(`ib's spaceName (${spaceName}) must match data.name (${data.name}) (E: 2cfa219c948f4fc8869d47b7217aed6f)`);\n        }\n\n        // ensure rel8ns make sense\n        if (data.n === undefined && (rel8ns?.past ?? []).length > 0) {\n            errors.push(`\"past\" rel8n not expected when data.n is falsy (E: 189bdfe41a7a46db947590d50c11ef88)`);\n        }\n        if (data.n && (rel8ns?.past ?? []).length === 0) {\n            errors.push(`\"past\" rel8n required when data.n is truthy (E: abab9f88c898406497181c872b619276)`);\n        }\n        if (data.n === 0 && (rel8ns?.past ?? []).length !== 1) {\n            errors.push(`\"past\" rel8n expected to have a single record when data.n === 0 (E: d5c9721b475d45ce9b94ba989bbc231b)`);\n        }\n        if (rel8ns && (rel8ns.past?.length ?? -1) > 0) {\n            const pastAddrs = rel8ns.past as IbGibAddr[];\n            pastAddrs.forEach(x => {\n                const { ib: pastIb } = getIbAndGib({ ibGibAddr: x });\n                const pastIbInfo = parseSpaceIb({ spaceIb: pastIb });\n                if (pastIbInfo.spaceClassname && (pastIbInfo.spaceClassname !== spaceClassname)) {\n                    errors.push(`rel8ns.past address classname (${pastIbInfo.spaceClassname}) must match current spaceClassname (${spaceClassname}) (E: 51d859ab2e9f46279b9492c1a3ad1037)`);\n                }\n                if (pastIbInfo.spaceId !== spaceId) {\n                    errors.push(`rel8ns.past address spaceId (${pastIbInfo.spaceId}) must match current spaceId (${spaceId}) (E: 738a23cf54c947528e085cba24ab547a)`);\n                }\n                // i want to allow this, but for now we're going to require not changing the name...\n                if (pastIbInfo.spaceName !== spaceName) {\n                    errors.push(`rel8ns.past address spaceName (${pastIbInfo.spaceName}) must match current spaceName (${spaceName}) (E: c0512b208885489eaf0d073613205fa7)`);\n                }\n            });\n        }\n\n        return errors;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * Base class convenience for a local space with V1 ibgibs.\n *\n * This naively caches ibGibs in memory. When not found there,\n * will looks in files using Ionic `FileSystem`.\n */\nexport abstract class FilesystemSpace_V1<\n    TOptionsData extends FilesystemSpaceOptionsData,\n    TOptionsRel8ns extends FilesystemSpaceOptionsRel8ns,\n    TResultData extends FilesystemSpaceResultData,\n    TResultRel8ns extends FilesystemSpaceResultRel8ns,\n    TData extends FilesystemSpaceData_V1 = FilesystemSpaceData_V1,\n    TRel8ns extends FilesystemSpaceRel8ns_V1 = FilesystemSpaceRel8ns_V1\n> extends SpaceBase_V1<\n    IbGib_V1,\n    TOptionsData,\n    TOptionsRel8ns,\n    FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>,\n    FilesystemSpaceResultData,\n    FilesystemSpaceResultRel8ns,\n    FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>,\n    TData,\n    TRel8ns\n> {\n\n    /**\n     * Log context for convenience with logging.\n     */\n    protected lc: string = `[${FilesystemSpace_V1.name}]`;\n\n    /**\n     * Naive caching in-memory. Memory leak as it stands right now!\n     */\n    protected ibGibs: { [key: string]: IbGib_V1 } = {};\n\n    /**\n     * Check every time app starts if paths exist.\n     * But don't check every time do anything whatsoever.\n     *\n     * @see {@link ensureAllDirsExist}\n     * @see {@link ensureDirsImpl}\n     */\n    protected pathExistsMap: { [key: string]: any } = {};\n\n    constructor(\n        // /**\n        //  * Default predicate value when putting an unknown ibGib.\n        //  *\n        //  * ## notes\n        //  *\n        //  * So when a repo witnesses another ibGib, it either defaults to\n        //  * storing that ibGib or not storing that ibGib. This is what that\n        //  * is referring to. If it's optimistic, then it stores any ibGib by\n        //  * default and it passes its put predicate.\n        //  */\n        // public optimisticPut: boolean = true,\n        initialData?: TData,\n        initialRel8ns?: TRel8ns,\n    ) {\n        super(initialData ?? clone(DEFAULT_FILESYSTEM_SPACE_DATA_V1), initialRel8ns);\n    }\n\n\n    protected async validateWitnessArg(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>): Promise<string[]> {\n        const lc = `${this.lc}[${this.validateWitnessArg.name}]`;\n        let errors: string[] = [];\n        try {\n            errors = (await super.validateWitnessArg(arg)) || [];\n            if (arg.data?.cmd === 'put' && (arg.ibGibs || []).length === 0) {\n                errors.push(`when \"put\" cmd is called, ibGibs required.`);\n            }\n            if (arg.data?.cmd === 'get' && (arg.data?.ibGibAddrs || []).length === 0) {\n                errors.push(`when \"get\" cmd is called, ibGibAddrs required.`);\n            }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (errors?.length > 0) { console.error(`${lc} errors: ${errors}`); }\n        }\n\n        return errors;\n    }\n\n    /**\n     * Initializes to default space values.\n     */\n    protected async initialize(): Promise<void> {\n        const lc = `${this.lc}[${this.initialize.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (!this.data) {\n                this.data = clone(DEFAULT_FILESYSTEM_SPACE_DATA_V1);\n                this.data = this.data!; // why does ts compiler need this?\n            }\n            if (!this.data?.classname) { this.data!.classname = FilesystemSpace_V1.name }\n            if (!this.data.baseDir) { this.data.baseDir = IBGIB_BASE_DIR; }\n            if (!this.data.encoding) { this.data.encoding = IBGIB_ENCODING; }\n            if (!this.data.baseSubPath) { this.data.baseSubPath = IBGIB_BASE_SUBPATH; }\n            if (!this.data.spaceSubPath) { this.data.spaceSubPath = IBGIB_SPACE_SUBPATH_DEFAULT; }\n            if (!this.data.ibgibsSubPath) { this.data.ibgibsSubPath = IBGIB_IBGIBS_SUBPATH; }\n            if (!this.data.metaSubPath) { this.data.metaSubPath = IBGIB_META_SUBPATH; }\n            if (!this.data.binSubPath) { this.data.binSubPath = IBGIB_BIN_SUBPATH; }\n            if (!this.data.dnaSubPath) { this.data.dnaSubPath = IBGIB_DNA_SUBPATH; }\n\n            // do nothing, allow falsy\n            // if (!this.data.longSubPath) { this.data.longSubPath = IBGIB_LONG_SUBPATH; }\n\n            this.ib = getSpaceIb({ space: this, classname: FilesystemSpace_V1.name });\n\n            this.gib = await getGib({ ibGib: this });\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected hasInCache({ addr }: { addr: IbGibAddr }): Promise<boolean> {\n        if (isPrimitive({ gib: getIbAndGib({ ibGibAddr: addr }).gib })) {\n            // primitives never cached\n            return Promise.resolve(false);\n        } else if (Object.keys(this.ibGibs).includes(addr)) {\n            // has in local instance cache\n            return Promise.resolve(true);\n        } else if (this.cacheSvc) {\n            // not local so delegate to cache svc\n            return this.cacheSvc.has({ addr });\n        } else {\n            // no external cache svc and not in local instance cache\n            return Promise.resolve(false);\n        }\n    }\n    protected async putInCache({ addr, ibGib }: { addr: IbGibAddr, ibGib: IbGib_V1 }): Promise<void> {\n        const lc = `${this.lc}[${this.putInCache.name}][${addr}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (!ibGib) { throw new Error(`ibGib required (E: 993e26fe40894bab9feccac3938f37df)`); }\n\n            if (isPrimitive({ ibGib })) {\n                if (logalot) { console.log(`${lc} skipping caching primitive (I: a04dfb691582a4db8a0bfecfefe5e622)`); }\n                return;\n            } else {\n                if (logalot) { console.log(`${lc} caching addr (I: b996a306f256ee5f39db1e2f5d515c22)`); }\n            }\n\n            // instance cache\n            this.ibGibs[addr] = ibGib;\n\n            // cache svc\n            if (this.cacheSvc) { await this.cacheSvc.put({ addr, ibGib }); }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n    protected async getFromCache({ addr }: { addr: IbGibAddr }): Promise<IbGib_V1 | undefined> {\n        const lc = `${this.lc}[${this.getFromCache.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            let cached: IbGib_V1 | undefined = this.ibGibs[addr];\n            if (!cached && this.cacheSvc) {\n                const info = await this.cacheSvc.get({ addr });\n                cached = info?.ibGib;\n            }\n            return cached;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected deleteFromCache({ addr }: { addr: IbGibAddr }): Promise<void> {\n        const lc = `${this.lc}[${this.getFromCache.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            delete this.ibGibs[addr];\n            return Promise.resolve();\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async getImpl(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>):\n        Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.getImpl.name}]`;\n        const resultIbGibs: IbGib_V1[] = [];\n        const resultData: FilesystemSpaceResultData = { optsAddr: getIbGibAddr({ ibGib: arg }), }\n        let notFoundIbGibAddrs: IbGibAddr[] | undefined = undefined;\n        try {\n            if (!arg.data) { throw new Error('arg.data is falsy'); }\n            let { ibGibAddrs, isDna, } = arg.data!;\n\n            ibGibAddrs ||= [];\n\n            const binAddrs = ibGibAddrs.filter(addr => isBinary({ addr }));\n\n            let ibGibAddrsNonBin = ibGibAddrs.filter(addr => !binAddrs.includes(addr));\n\n            if (logalot) { console.log(`${lc} getting non-bin ibgibs. ibGibAddrsNonBin: ${ibGibAddrsNonBin}`); }\n            for (let i = 0; i < ibGibAddrsNonBin.length; i++) {\n                const addr = ibGibAddrsNonBin[i];\n                if (!arg.data.force && await this.hasInCache({ addr })) {\n                    if (logalot) { console.log(`${lc} YES found in naive cache. (I: 0b23f394fd944c2a96df3543dd0a59c5)`); }\n                    const cached = await this.getFromCache({ addr });\n                    if (!cached) { throw new Error(`(UNEXPECTED) we had in cache but failed to retrieve? (E: 4af334f7a90cb22ffa3b549d0db19a22)`); }\n                    resultIbGibs.push(cached);\n                } else {\n                    // not found in memory, so look in files\n                    // if (!isPrimitive({ gib: getIbAndGib({ ibGibAddr: addr }).gib }) && this.cacheSvc) {\n                    // }\n                    const getResult = await this.getFile({ addr, isDna, });\n                    if (getResult?.success && getResult.ibGib) {\n                        await this.putInCache({ addr, ibGib: getResult.ibGib })\n                        resultIbGibs.push(getResult.ibGib!);\n                    } else {\n                        // not found in memory or in files\n                        if (!notFoundIbGibAddrs) { notFoundIbGibAddrs = []; }\n                        notFoundIbGibAddrs.push(addr);\n                    }\n                }\n            }\n\n            for (let i = 0; i < binAddrs.length; i++) {\n                // debugger;\n                const addr = binAddrs[i];\n                const { binHash, binExt } = getBinHashAndExt({ addr });\n\n                // getting binary, not a regular ibGib via addr\n                if (logalot) { console.log(`${lc} getting binHash.binExt: ${binHash}.${binExt}`); }\n                const getResult = await this.getFile({ addr });\n                if (getResult?.success && getResult.ibGib) {\n                    if (logalot) { console.log(`${lc} getResult.success. ibGib.data?.length: ${getResult.ibGib!.data?.length}`); }\n                    resultIbGibs.push(getResult.ibGib);\n                } else {\n                    if (logalot) { console.log(`${lc} not found in files. (binData is not cached atm)`) }\n                    // not found in files. (binData is not cached atm)\n                    if (!notFoundIbGibAddrs) { notFoundIbGibAddrs = []; }\n                    notFoundIbGibAddrs.push(addr);\n                }\n            }\n\n            if (notFoundIbGibAddrs && notFoundIbGibAddrs.length > 0) {\n                if (logalot) { console.log(`${lc}[${this.data!.uuid.substring(0, 8)}] notFoundIbGibAddrs: ${notFoundIbGibAddrs} (I: 10f7e35e75445a1d64b353851d00b923)`); }\n                resultData.addrsNotFound = notFoundIbGibAddrs;\n                resultData.errors ??= [];\n                resultData.errors.push(`notFoundIbGibAddrs.length > 0 (E: e7eadcfa2f4643238590469bc917a35c)`);\n                resultData.success = false;\n            } else {\n                resultData.success = true;\n            }\n        } catch (error) {\n            const emsg = extractErrorMsg(error);\n            console.error(`${lc} error: ${emsg}`);\n            resultData.errors = [emsg];\n        }\n        try {\n            const result = await this.resulty({ resultData });\n            if (resultIbGibs.length > 0) {\n                result.ibGibs = resultIbGibs;\n            }\n            return result;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        }\n    }\n\n    protected async putImpl(\n        arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>\n    ): Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.putImpl.name}]`;\n        const resultData: FilesystemSpaceResultData = { optsAddr: getIbGibAddr({ ibGib: arg }), }\n        const errors: string[] = [];\n        try {\n            if (logalot) { console.log(`validating arg and internal state...`); }\n            if (!arg.data) { throw new Error('arg.data required. (E: d64a46e5efab4b09b57850ecf0854386)'); }\n            if (arg.ibGibs?.length === 0) { throw new Error(`arg.ibGibs required. (E: b4930d564b284fb9b26b542f14143a28)`); }\n\n            if (logalot) { console.log(`arg and internal state validated...calling impl func`); }\n            return await this.putIbGibsImpl(arg); // <<<< returns early\n        } catch (error) {\n            const emsg = extractErrorMsg(error);\n            console.error(`${lc} error: ${emsg}`);\n            resultData.errors = errors.concat([emsg]);\n            resultData.success = false;\n        }\n        // only executes if there is an error.\n        const result = await this.resulty({ resultData });\n        return result;\n    }\n\n    protected async putIbGibsImpl(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>\n    ): Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.putIbGibsImpl.name}]`;\n        const resultData: FilesystemSpaceResultData = { optsAddr: getIbGibAddr({ ibGib: arg }), }\n        const errors: string[] = [];\n        const warnings: string[] = [];\n        const addrsErrored: IbGibAddr[] = [];\n        try {\n            if (!arg.data) { throw new Error('arg.data is falsy (E: aae5757c158d4a799deb7fca9d6245f0)'); }\n            const { isDna, force } = arg.data!;\n            const ibGibs = arg.ibGibs || [];\n            const addrsAlreadyHave: IbGibAddr[] = [];\n\n            for (let i = 0; i < ibGibs.length; i++) {\n                const ibGib = ibGibs[i];\n                const addr = getIbGibAddr({ ibGib });\n                if (logalot) { console.log(`${lc} checking to see if already exists...`); }\n                const getResult = await this.getFile({ addr, isDna });\n                // const getResult: any = null; // testing performance\n                if (getResult?.success && getResult.ibGib) {\n                    // already exists...\n                    if (logalot) { console.log(`${lc} already exists...`); }\n                    if (force) {\n                        // ...but save anyway.\n                        if (logalot) { console.log(`${lc} Forcing save of already put addr: ${addr} (I: 325f363e5d438b43c24b810c150e4e22)`); }\n                        const putResult = await this.putFile({ ibGib, isDna });\n                        if (putResult.success) {\n                            if (!isDna) {\n                                // naive cache will cause \"memory leak\" eventually\n                                await this.putInCache({ addr, ibGib });\n                            }\n                        } else {\n                            errors.push(putResult.errorMsg || `${lc} error putting ${addr}`);\n                            addrsErrored.push(addr);\n                        }\n                    } else {\n                        // ...so annotate\n                        // deb ugger;\n                        if (logalot) {\n                            warnings.push(`${lc} skipping (non-force) of already exists addr: ${addr} (W: b7fbe22473014dd090db88aee631fecb)`);\n                        }\n                        addrsAlreadyHave.push(addr);\n                    }\n                } else {\n                    // does not already exist.\n                    if (logalot) { console.log(`${lc} does NOT already exist...`); }\n                    const putResult = await this.putFile({ ibGib, isDna, });\n                    if (putResult.success) {\n                        if (!isDna) { await this.putInCache({ addr, ibGib }); }\n                    } else {\n                        errors.push(putResult.errorMsg || `${lc} error putting ${addr}`);\n                        addrsErrored.push(addr);\n                    }\n                }\n            }\n\n            if (addrsAlreadyHave.length > 0) { resultData.addrsAlreadyHave = addrsAlreadyHave; }\n            if (warnings.length > 0) { resultData.warnings = warnings; }\n            if (errors.length === 0) {\n                resultData.success = true;\n            } else {\n                resultData.errors = errors;\n                resultData.addrsErrored = addrsErrored;\n            }\n        } catch (error) {\n            const emsg = extractErrorMsg(error);\n            console.error(`${lc} error: ${emsg}`);\n            resultData.errors = errors.concat([emsg]);\n            resultData.addrsErrored = addrsErrored;\n            resultData.success = false;\n        }\n        const result = await this.resulty({ resultData });\n        return result;\n    }\n\n    protected async deleteImpl(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>):\n        Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.deleteImpl.name}]`;\n        const resultData: FilesystemSpaceResultData = { optsAddr: getIbGibAddr({ ibGib: arg }), }\n        const errors: string[] = [];\n        const warnings: string[] = [];\n        const addrsDeleted: IbGibAddr[] = [];\n        const addrsErrored: IbGibAddr[] = [];\n        try {\n            if (!arg.data) { throw new Error('arg.data is falsy'); }\n            const { isDna, } = arg.data!;\n            const ibGibAddrs = arg.data!.ibGibAddrs || [];\n\n            // delete cached entries first\n            // const cachedAddrs = Object.entries(this.ibGibs)\n            //     .filter(([x,y]) => ibGibAddrs.includes(x))\n            //     .map(([x,y]) => x);\n            // cachedAddrs.forEach(addr => { delete this.ibGibs[addr]; });\n\n            // iterate through ibGibs, but this may be an empty array if we're doing binData.\n            for (let i = 0; i < ibGibAddrs.length; i++) {\n                const addr = ibGibAddrs[i];\n                await this.deleteFromCache({ addr });\n                const deleteResult = await this.deleteFile({ addr, isDna, });\n                if (deleteResult?.success) {\n                    addrsDeleted.push(addr);\n                } else {\n                    errors.push(deleteResult.errorMsg || `delete failed: addr (${addr})`);\n                    addrsErrored.push(addr);\n                }\n            }\n            if (warnings.length > 0) { resultData.warnings = warnings; }\n            if (errors.length === 0) {\n                resultData.success = true;\n                resultData.addrs = addrsDeleted;\n            } else {\n                resultData.errors = errors;\n                resultData.addrsErrored = addrsErrored;\n                if (addrsDeleted.length > 0) {\n                    const warningMsg =\n                        `some addrs (${addrsDeleted.length}) were indeed deleted, but not all. See result addrs and addrsErrored.`;\n                    resultData.warnings = (resultData.warnings || []).concat([warningMsg]);\n                }\n            }\n        } catch (error) {\n            const emsg = extractErrorMsg(error);\n            console.error(`${lc} error: ${emsg}`);\n            resultData.errors = errors.concat([emsg]);\n            resultData.addrsErrored = addrsErrored;\n            resultData.success = false;\n        }\n        const result = await this.resulty({ resultData });\n        return result;\n    }\n\n    protected async getAddrsImpl(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>):\n        Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.getAddrsImpl.name}]`;\n        throw new Error(`${lc} not implemented. (E: 74dd50ce4b564559bc44d6c08d446cb3)`);\n    }\n\n    /**\n     * Performs a naive `exists: boolean` or `includes: boolean` analog.\n     *\n     * If all of the addresses are found, will result in `success` and `can` being `true`.\n     *\n     * Else, `can` will be falsy, and `addrsNotFound` will be populated with all/some of\n     * the queried addresses.\n     *\n     * ## notes\n     *\n     * This does not take authorization into account in any way. it's a simple, naive in-memory\n     * storage ibGib witness.\n     *\n     * @returns result ibGib whose primary value is `can`\n     */\n    protected async canGetImpl(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>):\n        Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.canGetImpl.name}]`;\n        const resultData: FilesystemSpaceResultData = { optsAddr: getIbGibAddr({ ibGib: arg }), }\n        try {\n            throw new Error(`not implemented (E: 2a45977c584c6bbbc4f164c16106bd22)`);\n        } catch (error) {\n            const emsg = extractErrorMsg(error);\n            console.error(`${lc} error: ${emsg}`);\n            resultData.errors = [emsg];\n        }\n        const result = await this.resulty({ resultData });\n        return result;\n    }\n    protected async canPutImpl(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>):\n        Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.canPutImpl.name}]`;\n        const resultData: FilesystemSpaceResultData = { optsAddr: getIbGibAddr({ ibGib: arg }), }\n        try {\n            throw new Error(`not implemented (E: 25a005d496efc69faefdec155ffb4a22)`);\n        } catch (error) {\n            const emsg = extractErrorMsg(error);\n            console.error(`${lc} error: ${emsg}`);\n            resultData.errors = [emsg];\n        }\n        const result = await this.resulty({ resultData });\n        return result;\n    }\n\n    protected async canDeleteImpl(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>):\n        Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.canDeleteImpl.name}]`;\n        throw new Error(`${lc} not implemented (E: a3306138b4ac429ba5f8f293ad7dd07b)`);\n    }\n\n    protected async getLatestAddrsImpl(arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>):\n        Promise<FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>> {\n        const lc = `${this.lc}[${this.getLatestAddrsImpl.name}]`;\n        const resultData: FilesystemSpaceResultData = { optsAddr: getIbGibAddr({ ibGib: arg }), }\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (!arg.data) { throw new Error(`arg.data required (E: cd92cb965d711c8014455c69e898ac23)`); }\n            if (!arg.data.ibGibAddrs) { throw new Error(`arg.data.ibGibAddrs required (E: 2d0824f9b8aec916a751ef17e2d4a823)`); }\n            if (arg.data.ibGibAddrs.length === 0) { throw new Error(`arg.data.ibGibAddrs required to be non-zero (E: 2d0824f9b8aec916a751ef17e2d4a823)`); }\n\n            const latestAddrs = new Set<IbGibAddr>();\n            const addrsNotFound = new Set<IbGibAddr>();\n            const addrsErrored = new Set<IbGibAddr>();\n            resultData.latestAddrsMap = {};\n\n            // iterate through incoming ibGibAddrs, get their corresponding\n            // ibgib from file storage, and use our existing\n            // `getLatestAddrImpl` function\n            for (let i = 0; i < arg.data.ibGibAddrs.length; i++) {\n                const addr = arg.data.ibGibAddrs[i];\n                const getResult = await this.getFile({ addr });\n                if (getResult?.success && getResult.ibGib) {\n                    const ibGib = getResult.ibGib!;\n                    const latestAddr = await this.getLatestAddrImpl({ ibGib });\n                    if (latestAddr) {\n                        latestAddrs.add(latestAddr);\n                        resultData.latestAddrsMap[addr] = latestAddr;\n                    } else {\n                        console.warn(`expecting latestAddr to either be assigned or throw. Adding addr (${addr}) to addrsErrored. (W: 35c3712b1a1e579ccf28c389eb2ecc22)`);\n                        addrsErrored.add(addr);\n                    }\n                } else if (getResult?.success) {\n                    addrsNotFound.add(addr);\n                    resultData.latestAddrsMap[addr] = null;\n                } else if (getResult.errorMsg) {\n                    addrsErrored.add(addr);\n                } else {\n                    throw new Error(`unknown (invalid) getResult: ${pretty(getResult)} (E: 2674ad5d30294be29a3d3fdcf54ef6d9)`);\n                }\n            }\n\n            resultData.addrs = latestAddrs.size > 0 ? [...latestAddrs] : undefined;\n            resultData.addrsErrored = addrsErrored.size > 0 ? [...addrsErrored] : undefined;\n            resultData.addrsNotFound = addrsNotFound.size > 0 ? [...addrsNotFound] : undefined;\n\n            // we didn't throw, so that's a success\n            resultData.success = true;\n        } catch (error) {\n            const emsg = extractErrorMsg(error);\n            console.error(`${lc} error: ${emsg}`);\n            resultData.errors = [emsg];\n        }\n        try {\n            let result = await this.resulty({ resultData });\n            return result;\n        } catch (error) {\n            console.error(`${lc}[resulty] ${extractErrorMsg(error)}`);\n            throw error;\n        }\n    }\n\n    /**\n     * @internal\n     *\n     * This is the actual implementation function to get a single latest address\n     * for a single ibgib.\n     *\n     * @returns latest addr in this space according to the \"latest\" special ibgib index\n     *\n     * ## implementation notes\n     *\n     * ### pre-11/2023 Single SpecialIbGibType.latest \"special ibgib\" indexing\n     *\n     * an early implementation, this used a single meta \"special ibgib\" () that\n     * is a central point in the space that maps from tjpAddr => latestAddr.\n     * this makes it a bottleneck (not scalable) and a single point-of-failure\n     * (not robust).\n     *\n     * ### 11/2023 (current atow 11/2023)\n     *\n     * default latest address mapping from tjpAddr => latestAddr implementation\n     * candidates are considered here.\n     *\n     * #### individual constant-named files\n     *\n     * individual files inside /basePath/spaceSubpath/metaSubpath/latest. These\n     * will have tjpAddr filename (no extension?) but the contents should simply\n     * be the latestAddr.\n     *\n     * ##### advantages\n     *\n     * * this would require additional/specialized file getting/putting\n     *   implementations.\n     * * this might be a proximally faster implementation as no additional\n     *   hashing would be required.\n     *\n     * ##### disadvantages\n     *\n     * mainly it is about possible security concerns on this implementation and\n     * less ibgib dogfooding.\n     *\n     * I am unsure if this would be any \"less safe\" than the previous\n     * implementation that relied on the special ibgib indexing, as even though\n     * the latest special ibgib index was itself hashed, it was still ephemeral\n     * and the space did not track changes to it. Either way, it is always a\n     * security consideration to change the tjpAddr => latestAddr mapping as you\n     * can hijack timelines. But this is mitigated as long as you have a\n     * monotonically increasing space, you can correct any malfeasance and\n     * \"stitch\" together the \"correct\" space state.\n     *\n     * Still, it would be good to have some timeline whose job is to snapshot\n     * these periodically. Perhaps that is simply a functionality that would be\n     * good to have regardless of \"security\" concerns. Reified checkpointing.\n     *\n     * #### meta latest ibgib stones (constants/no tjp themselves)\n     *\n     * instead of bare files, we reuse ibgib plumbing via ibgib stones with\n     * special ib schemas that allow us to mimic a timeline with the following\n     * information:\n     *\n     * * meta_latest [tjpGib] [n] [index timestamp ticks]\n     *\n     * _I mention this as mimicking a timeline because if we were to have them as\n     * colocated ibgibs in space (not separated specially to ignore when sending\n     * graphs), we would then have a recursive problem of keeping track of the\n     * latest addrs of the latest addr tracking ibgibs (turtles all the way\n     * down)._\n     *\n     * this would be put in a separate subpath underneath the meta subpath, or\n     * possibly as a sibling beside it. definitely need a separate path though\n     * for the same reason we have a separate path for dna. there will be many,\n     * **many** of these constants. so much so that we may want to prune them on\n     * some basis. Possibly will do sibling beside it to reduce overall path\n     * length.\n     *\n     * the index timestamp ticks is the timestamp when the indexing occurs in\n     * the local space (not the ibgib's internal timestamp, if it exists). I\n     * wanted to add this also, but could be yagni and there is a cost with path\n     * length implementations.\n     *\n     * ##### advantages\n     *\n     * * reuses existing get/put implementation\n     * * allows consistent coding of helper functions/types/etc.\n     * * allows for (future implementation) of on-chain schema information\n     * * more robust against soft hacks\n     *   * soft = non-total access hacks\n     * * allows for future consensus/witness backups/gossip\n     *\n     * overall would be less distal overhead (more simplification) and dogfoods\n     * the ibgib protocol to a greater degree.\n     *\n     * ##### disadvantages\n     *\n     * * more proximal overhead\n     *   * already \"practical\" performance issues in prototype, though afaict\n     *     this is largely because i'm working solo on the darn project and i suck\n     *     at ux (i.e. angular)\n     *     * not just me, angular/react/others dispatching are necessarily overhead as\n     *       they duplicate some of the awesomeness that comes for free when starting with\n     *       ibgib timelines from the beginning.\n     */\n    protected async getLatestAddrImpl({\n        ibGib,\n        ibGibAddr,\n    }: {\n        ibGib?: IbGib_V1,\n        ibGibAddr?: IbGibAddr,\n    }): Promise<IbGibAddr> {\n        let lc = `${this.lc}[${this.getLatestAddrImpl.name}]`;\n        if (logalot) { console.log(`${lc} starting...`); }\n        try {\n            if (!ibGib && !ibGibAddr) { throw new Error(`either ibGib or ibGibAddr required (E: 1f8f0cb61d1b4c708b06762048735c22)`); }\n\n            if (ibGib && ibGibAddr && (getIbGibAddr({ ibGib }) !== ibGibAddr)) { throw new Error(`(UNEXPECTED) both ibGib and ibGibAddr provided but they don't match? (E: 01d1938252ef49b53d41d58abfaac523)`); }\n\n            ibGibAddr ||= getIbGibAddr({ ibGib });\n            const { ib, gib } = getIbAndGib({ ibGibAddr });\n            if (!gib) { throw new Error(`(UNEXPECTED) gib falsy? (E: d2506b99162e27348310f8e7e68e4523)`); }\n\n            // first do some initial checking to rule out quick special cases...\n\n            // if it's primitive, warn and return incoming addr\n            if (isPrimitive({ gib })) {\n                console.warn(`${lc} incoming ibGibAddr is primitive. Why are we calling getLatest on a primitive? returning incoming addr. (W: 57fcf479d5cc48d393841ec3d53587fa)`);\n                return ibGibAddr; /* <<<< returns early */\n            }\n            const probablyIsDna = ['fork', 'mut8', 'rel8'].includes(ib);\n            if (probablyIsDna) {\n                if (logalot) { console.log(`${lc} probably is dna (ib === fork/mut8/rel8). returning incoming ibGibAddr early. (I: 2081628936de6a36bbb51224f0223523)`); }\n                return ibGibAddr; /* <<<< returns early */\n            }\n\n            // at this point it might be...\n            // 1) a stone (constant/no timeline)\n            // 2) a tjp (data.isTjp is true)\n            // 3) a timeline member (tjpGib in gib)\n            // in any case, we can pull the tjpGib out of the addr. if it's falsy, we use the gib as\n            // if it were the tjpGib.\n            //\n\n            const gibInfo = getGibInfo({ ibGibAddr });\n            let { tjpGib } = gibInfo;\n            tjpGib ||= gib;\n            // if (!tjpGib) {\n            //     // may still itself be the tjp\n            //     if (!!ibGib.data?.isTjp) {\n            //         // the ibgib is itself the tjp, so it's gib is the tjpGib\n            //         tjpGib = gib;\n            //     } else {\n            //         // no tjp, just return the incoming ibGib\n            //         if (logalot) { console.log(`${lc} incoming ibGib has no tjp and is not itself the tjp. so it's a stone, not a timeline. returning incoming ibGibAddr. (I: 30bace867ea274cdc3263ab901c9dd23)`); }\n            //         return ibGibAddr; /* <<<< returns early */\n            //     }\n            // }\n\n            // guaranteed to have a tjp at this point & tjpGib is truthy\n\n            // get the tjp for the rel8nName mapping, and also for\n            // some checking logic\n            // let tjp = await getTjpIbGib({ ibGib, space: this });\n            // if (!tjp) {\n            //     throw new Error(`(UNEXPECTED) tjp not found for ${ibGibAddr}? Should at least just be the ibGib's address itself. (E: 860bdcaaf80548feb6b61b4cde21a722)`);\n            //     // console.warn();\n            //     // tjp = ibGib;\n            // }\n            // const tjpAddr = getIbGibAddr({ ibGib: tjp });\n            // if (logalot) { console.log(`${lc} tjp (${tjpAddr}) (I: 5245a2ec85a943f98479e93a32d67f22)`); }\n\n            // here is where the implementation change starts. instead of using\n            // the special ibgib, we will look for the subfolder that corresponds to the tjpGib.\n\n            // if we get a list of the metastone addrs in the folder, we can\n            // filter for the highest n and latest timestampInTicks.\n            // * do we need to load any actual files to do more searching?\n            // * ensure that tjpGib matches in ib?\n            // * is this an implementation detail that should only be in descendant class\n            // * pass in lambda to do filtering in the function?\n            const metaStoneAddrs = await this.getMetaStoneAddrs({ tjpGib, ibGibAddr });\n            if (metaStoneAddrs.length === 0) {\n                if (logalot) { console.warn(`${lc} no metastones found for given ibGibAddr (${ibGibAddr}). returning incoming ibGibAddr (W: a6a35cbbf40745e8a3e202226bb457ff)`); }\n                return ibGibAddr; /* <<<< returns early */\n            }\n\n            // security-wise, a stronger implementation would verify each meta\n            // stone intrinsically at the very least, as well as additional\n            // checking once authorization/authentication/keystones are in use.\n            // for now, we'll just take it for granted, as this provides the\n            // same (lack of) security guarantees as previous implementation that\n            // used the SpecialIbGibType.latest.\n\n            const metaStoneAddrsAndIbInfos: [IbGibAddr, MetaStoneIbInfo][] = metaStoneAddrs\n                .map(xAddr => [xAddr, getIbAndGib({ ibGibAddr: xAddr }).ib])\n                .map(([xAddr, metaStoneIb]) => [xAddr, parseMetaStoneIb({ ib: metaStoneIb })]);\n\n\n            /**\n             * sort mutates the actual array (shuffle sort I think), but\n             * we're storing it in a different variable name to be more\n             * explicit.\n             */\n            const metaStoneAddrsAndIbInfos_descending = metaStoneAddrsAndIbInfos.sort((a, b) => {\n                const [_aAddr, aInfo] = a;\n                const [_bAddr, bInfo] = b;\n                // we want the highest n, with tiebreaker going to\n                // timestampInTicks. if that's the same also, then what are we\n                // quibbling about?\n                if (aInfo.n > bInfo.n) {\n                    return -1;\n                } else if (aInfo.n < bInfo.n) {\n                    return 1;\n                } else if (aInfo.timestampInTicks > bInfo.timestampInTicks) {\n                    return -1;\n                } else if (aInfo.timestampInTicks < bInfo.timestampInTicks) {\n                    return 1;\n                } else {\n                    // neither discriminator is different.\n                    return 0;\n                }\n            });\n            if (logalot) {\n                console.log(`${lc} console.dir(metaStoneAddrsAndIbInfos_descending)... (I: 1bb5e7d994248e8b6559ca2863c72123)`);\n                console.dir(metaStoneAddrsAndIbInfos_descending);\n            }\n\n            // since we sorted into a descending order, the latest is the very\n            // first item.  and we have already guaranteed that there is at\n            // least 1 in the array.\n            if (metaStoneAddrsAndIbInfos_descending.length === 0) { throw new Error(`(UNEXPECTED) metaStoneAddrsAndIbInfos_descending is empty? earlier in the function there should have been a check. did getMetaStoneAddrs return a populated list but no stones were found? (E: 63c035ebed77741f2330c7a625823f23)`); }\n\n            const [latestMetaStoneAddr, latestMetaStoneInfo] = metaStoneAddrsAndIbInfos_descending[0];\n            if (logalot) { console.log(`${lc} [latestMetaStoneAddr, latestMetaStoneInfo]: ${[latestMetaStoneAddr, latestMetaStoneInfo]}  (I: 1307ca46b4abd62c7a30fe87c08fa923)`); }\n\n            let latestMetaStoneIbGib: MetaStoneIbGib_V1;\n            const getResult = await this.getFile({ addr: latestMetaStoneAddr, isDna: false, });\n            if (getResult?.success && getResult.ibGib) {\n                latestMetaStoneIbGib = getResult.ibGib as MetaStoneIbGib_V1;\n                const errors = await validateCommonMetaStoneIbGib({ ibGib: latestMetaStoneIbGib }) ?? [];\n                if (errors.length > 0) { throw new Error(`invalid metastone (${latestMetaStoneAddr}) for tjpGib (${tjpGib}). errors: ${errors.join('|')} (E: 7fa7c6fa696d860cc7a9148861f96123)`); }\n            } else {\n                throw new Error(`(UNEXPECTED) we just found a metastone addr (${latestMetaStoneAddr}) that was read from the directory's contents, but we can't get the file? (E: 3b934b4adcd9d0efee7820f8d4012e23)`);\n            }\n\n            // latestMetaStoneIbGib.rel8ns ensured via validation at this point\n            const latestMetaStoneRel8ns = latestMetaStoneIbGib.rel8ns!;\n            /**\n             * this is accurate as the punctiliar address that corresponds to\n             * the metastone.\n             *\n             * atow (11/2023) interface of rel8ns\n             * [META_STONE_TARGET_REL8N_NAME]: IbGibAddr[];\n             * [META_STONE_TARGET_TJP_REL8N_NAME]?: IbGibAddr[];\n             */\n            const latestAddr = latestMetaStoneRel8ns[META_STONE_TARGET_REL8N_NAME].at(0);\n            if (!latestAddr) { throw new Error(`metastone passed validation but latestMetaStoneRel8ns[META_STONE_TARGET_REL8N_NAME].at(0) is empty? (E: c188ec0089ad86efe4d925c118599d23)`); }\n            return latestAddr;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n\n\n    /**\n     * Extremely crude implementation that just\n     * saves the ibgibs alongside existing data.\n     *\n     * ## future\n     *\n     * * At the very least, this could be changed similar to dna to have\n     *   its own folder.\n     */\n    protected async persistOptsAndResultIbGibs({\n        arg,\n        result,\n    }: {\n        arg: FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>,\n        result: FilesystemSpaceResultIbGib<TResultData, TResultRel8ns>,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.persistOptsAndResultIbGibs.name}]`;\n        if (logalot || this.data?.trace) {\n            console.log(`${lc} doing arg?.data?.cmd: ${arg?.data?.cmd}, result?.data?.success: ${result?.data?.success}`);\n        }\n        const ibGibs = [arg, result ?? ROOT];\n        let argPersist = await argy_<FilesystemSpaceOptionsData, FilesystemSpaceOptionsRel8ns, FilesystemSpaceOptionsIbGib<TOptionsData, TOptionsRel8ns>>({\n            argData: {\n                cmd: 'put',\n                catchAllErrors: true,\n                ibGibAddrs: ibGibs.map(x => getIbGibAddr({ ibGib: x })),\n            },\n        });\n        argPersist.ibGibs = ibGibs;\n        // this is a best effort storage, so we aren't using the result\n        // in the future, we should incorporate what to do if this persistence\n        // fails into the larger success requirements of spaces.\n        const resPut = await this.putIbGibsImpl(argPersist);\n        if (!resPut?.data) { throw new Error(`resPut.data falsy (E: f3115254240b8eff6cd82878a4a35a23)`); }\n        if (!resPut.data.success || resPut.data.errors) {\n            console.error(`${lc} Errors persisting arg & result: ${(resPut.data?.errors ?? ['unknown errs']).join('\\n')}. (E: 65ef314a4f8e445d851dab5b290e9a03)`);\n        }\n    }\n\n    // #region files related\n\n    protected abstract putFile({\n        ibGib,\n        isDna,\n    }: PutIbGibFileOpts): Promise<PutIbGibFileResult>;\n\n    protected abstract deleteFile({\n        addr,\n        isDna,\n    }: DeleteIbGibFileOpts): Promise<DeleteIbGibFilesResult>;\n\n    protected abstract getFile({\n        addr,\n        isDna,\n    }: GetIbGibFileOpts): Promise<GetIbGibFileResult>;\n\n    // #endregion files related\n\n    // #region ensure related\n\n    protected async ensurePermissions(): Promise<boolean> {\n        const lc = `${this.lc}[${this.ensurePermissions.name}]`;\n        const keyPermissionRequested: string = 'ibgib_permissionRequested_ensurePermissions';\n        try {\n            return true;\n        } catch (error) {\n            console.error(`${lc} Dont have permissions... error: ${extractErrorMsg(error)}`);\n            // localStorage.removeItem(keyPermissionRequested);\n            return false;\n        }\n    }\n\n    /**\n     * Ensure directories are created on filesystem before trying to read/write\n     * paths.\n     */\n    protected async ensureAllDirsExist(): Promise<void> {\n        // does nothing in base impl\n        // throw? i don't remember why i didn't have this throw...\n        const lc = `${this.lc}[${this.ensureAllDirsExist.name}]`;\n        console.warn(`${lc} not implemented in base class (W: c1b63ec036134db5960e0d3ea169d15b)`);\n    }\n    protected abstract ensureDirsImpl(paths: string[]): Promise<void>;\n\n    // #endregion ensure related\n\n    // #region metastone related\n\n    /**\n     * retrieves all metastone addrs whose targets have tjpGib\n     */\n    protected abstract getMetaStoneAddrs({\n        ibGibAddr,\n        tjpGib,\n        fnFilterIb,\n    }: {\n        /**\n         * addr of ibGib for which we're getting the metastones.\n         */\n        ibGibAddr: IbGibAddr,\n        /**\n         * tjpGib of the metastone's target ibgib\n         */\n        tjpGib: Gib,\n        fnFilterIb?: (ib: Ib) => boolean,\n    }): Promise<IbGibAddr[]>;\n\n    /**\n     * we are storing tjp-related things under the tjp subpath. so it will be\n     * atow (11/2023) something like .ibgib/ibgib/ibgibs/[tjpGib]/[ibGibAddr].json.\n     * i'm thinking that i should put the metastones inside a sub folder, so,\n     * .ibgib/ibgib/ibgibs/[tjpGib]/meta/[metaStoneAddr].json\n     *\n     * NOTE: does NOT ensure that the subpath exists.\n     *\n     * ## driving use case\n     *\n     * in here is where i will be putting the metastones. but I'm thinking I\n     * should store all ibgibs in this way, if they have a tjpGib. in fact, i\n     * may want to store the metastones underneath this tjpGib subpath.\n     *\n     * @returns full path of the (possibly non-existent) directory.\n     */\n    protected getTjpSubpath({\n        viaTargetAddr,\n        viaTargetTjpGib,\n        viaMetaStoneAddr,\n        pathSeparator = DEFAULT_PATH_SEPARATOR,\n    }: {\n        /**\n         * This param pulls the tjpGib from the target ibGib's address. (target\n         * as opposed to a metastone that points to a target).\n         *\n         * If this target addr is a stone, then this will use the addr's gib.\n         *\n         * ## notes\n         *\n         * Ultimately the tjp subpath is built on an ibGib's tjpGib. We can get\n         * this via multiple sources.\n         *\n         * _We only need to pass in one source, whichever is most convenient to\n         * caller._\n         */\n        viaTargetAddr?: IbGibAddr,\n        /**\n         * This param provides the target's tjpGib directly. (target as opposed\n         * to a metastone that points to a target).\n         *\n         * ## notes\n         *\n         * Ultimately the tjp subpath is built on an ibGib's tjpGib. We can get\n         * this via multiple sources.\n         *\n         * _We only need to pass in one source, whichever is most convenient to\n         * caller._\n         */\n        viaTargetTjpGib?: Gib,\n        /**\n         * This param provides the target's tjpGib based on the metaStone's ib,\n         * whose schema includes the target tjpGib (target as opposed\n         * to a metastone that points to a target).\n         *\n         * ## notes\n         *\n         * Ultimately the tjp subpath is built on an ibGib's tjpGib. We can get\n         * this via multiple sources.\n         *\n         * _We only need to pass in one source, whichever is most convenient to\n         * caller._\n         */\n        viaMetaStoneAddr?: IbGibAddr,\n        /**\n         * path separator to use when building the path.\n         */\n        pathSeparator?: string,\n    }): string {\n        const lc = `${this.lc}[${this.getTjpSubpath.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: c65dabcf47acf6d6881087b404861e23)`); }\n\n            // validate\n            if (!viaTargetAddr && !viaTargetTjpGib && !viaMetaStoneAddr) {\n                throw new Error(`either viaTargetAddr/TargetTjpGib/metaStoneAddr required (E: a784c4f0369e6e38eafcdf3289c38523)`);\n            }\n            if (!this.data) { throw new Error(`(UNEXPECTED) this.data falsy? (E: 441ff1b038366a1c07a94cf128454923)`); }\n            if (!pathSeparator) {\n                console.warn(`${lc} pathSeparator falsy? using default: \"${DEFAULT_PATH_SEPARATOR}\" (W: 295d21ab226743dd83a721f78870ab6e)`);\n                pathSeparator = DEFAULT_PATH_SEPARATOR;\n            }\n\n            // get the tjpGib depending on what is passed in\n            if (!viaTargetTjpGib) {\n                if (viaMetaStoneAddr) {\n                    // get the tjpGib via the metastone\n                    viaTargetTjpGib = parseMetaStoneIb({ ib: getIbAndGib({ ibGibAddr: viaMetaStoneAddr }).ib }).tjpGib;\n                } else {\n                    // get the tjpGib via the targetIbGibAddr\n                    viaTargetTjpGib = getGibInfo({ ibGibAddr: viaTargetAddr }).tjpGib;\n                }\n            }\n            if (!viaTargetTjpGib) { throw new Error(`targetTjpGib could not be gotten. are you sure this has a tjp? or is the ibGib a stone? (E: e507f1996aaa68a229a3158b3dbc5723)`); }\n\n            // build the path\n            const { baseSubPath, spaceSubPath, ibgibsSubPath } = this.data!\n            const tjpFullSubpath =\n                `${baseSubPath}${pathSeparator}${spaceSubPath}${pathSeparator}${ibgibsSubPath}${pathSeparator}${viaTargetTjpGib}`;\n\n            // return it\n            return tjpFullSubpath;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #endregion metastone related\n\n    // #region other helpers\n\n    /**\n     * builds the path of a given file, based on params.\n     *\n     * ## implementation change (11/2023)\n     *\n     * i'm changing the implementation from a naive `subpath/ib^gib.json` approach\n     * to a slightly more sophisticated one. we will change the path depending on\n     * the address:\n     *\n     * 1. if the addr has no tjp delimiter, path will be:\n     *    * `(bin|dna)/[gib]/ib.json` for \"binaries\" and dna\n     *    * `[gib]/ib.json` for all others\n     * 2. if the addr has a tjp delimiter, path will be:\n     *    * `[tjpGib]/[punctiliarHash]/ib.json` for all others\n     *    * it would be nicer to have a \"timelines\" folder but\n     *\n     * _NOTE: all dna and bins are stones (and have no tjpGib)._\n     * _NOTE: bins may have a different extension than \"json\"._\n     * _REFRESHER: punctiliarHash is the hash of a specific ibGib in time (punctiliar === point in time)._\n     *\n     * some benefits:\n     *\n     * 1. With this new structure, we can now conceivably create metastones\n     *    targeted at multiple levels:\n     *    * metastones that apply to entire timeline (tjpGib)\n     *    * metastones that apply to punctiliar ibGibs (punctiliarHash)\n     *    * metastones that apply to non-timeline stones (gib)\n     *    * NOTE: we atow (11/2023) are only creating metastones for\n     *      tracking latest punctiliar ibGibs in timelines.\n     * 2. separation between meta and regular ibgibs was slightly annoying &\n     *    useless, as the distinction is not as clear cut as the metastone one,\n     *    so condensing.\n     *\n     * @returns the path of a given file, based on params\n     */\n    protected async buildPath({\n        addr,\n        isDna,\n        isBin,\n        ensureMetaStonePaths,\n        pathSeparator = '/',\n        pretendItsALongPath = false,\n        addrIsForAMetaStone,\n    }: {\n        addr?: IbGibAddr,\n        isDna: boolean,\n        isBin?: boolean\n        ensureMetaStonePaths: boolean,\n        pathSeparator?: string,\n        /**\n         * I'm putting this in just in case the path length on the filesystem\n         * changes. it will be slower, but hey, this is a rough and tough\n         * implementation and they shouldn't be moving the damn folder. (*1)\n         *\n         * *1) just kidding. ideally we shouldn't have to worry about this kind\n         *     of thing but it's just an artifact of legacy os, \"time crunch\",\n         *     and hey I'm not a great programmer.\n         */\n        pretendItsALongPath?: boolean,\n        /**\n         * if true, the path built will be related to metastones.\n         *\n         * if false, the return path may still be for a metastone if the\n         * incoming `addr` is itself a metastone addr.\n         *\n         * ## intent\n         *\n         * this can be because we are get/set a metastone addr or if we are\n         * looking to get the directory for an address that will contain\n         * metastones.\n         *\n         * so if either of these use cases, this should be true.\n         *\n         * ## notes\n         *\n         * * the reason for the distinction is that metastones cannot have their ibs\n         *   shortened because all ib information is required.\n         * * perhaps in the future, i should change metastones impl to be in\n         *   their own folder.\n         */\n        addrIsForAMetaStone?: boolean,\n    }): Promise<string> {\n        const lc = `${this.lc}[${this.buildPath.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: d630823bbe0e1a1aa3592103768e8423)`); }\n\n            const data = this.data as FilesystemSpaceData_V1;\n            if (!data) { throw new Error(`this.data required (E: d2553d11b637577aa7b074387b613f23)`); }\n            if (!addr) { throw new Error(`addr required (E: 68149eccdbe2e6ef95eb50d588d68423)`); }\n\n            let resPath: string;\n\n            pathSeparator ||= '/';\n\n            let { ib, gib } = getIbAndGib({ ibGibAddr: addr });\n            if (!gib) { throw new Error(`gib required in building paths. if it's a primitive ibgib, then it shouldn't be put into/gotten from a space (E: 8a34bc925496c35d1892638623ec0a23)`); }\n\n            // we always start from the root dir of the space subpath\n            resPath = `${data.baseSubPath}${pathSeparator}${data.spaceSubPath}${pathSeparator}`;\n            if (logalot) { console.log(`${lc} resPath as of space subpath: ${resPath} (I: 5feccfadec1d8ac856243e78377c1e23)`); }\n\n            /**\n             * store the result of isMetaStone just to keep from having to\n             * call it more than once.\n             */\n            const addrIsAMetaStone = isMetaStone({ addr });\n            // if the caller did not specify that the addr is for a metastone,\n            // we still set this variable if the addr itself is a metastone.\n            if (addrIsAMetaStone) { addrIsForAMetaStone = true; }\n\n            // by looking at gib, determine if...\n            // 1. stone (no tjp)\n            // 2. tjp (gib is tjpGib b/c start of timeline)\n            // 3. ibgib belongs to timeline (has tjpGib and punctiliarHash)\n\n            const gibPieces = gib.split(GIB_DELIMITER);\n            if (gibPieces.length === 1) {\n                // either tjp, metastone, or other stone (e.g. dna).\n\n                // first prefix subpath is point if dna and bin files\n                if (isDna) {\n                    resPath += `${data.dnaSubPath}${pathSeparator}`;\n                    if (logalot) { console.log(`${lc} resPath dna appended subpath: ${resPath} (I: eecd26dfc1699110ae5b91dd68438f23)`); }\n                } else if (isBin) {\n                    resPath += `${data.binSubPath}${pathSeparator}`;\n                    if (logalot) { console.log(`${lc} resPath bin appended subpath: ${resPath} (I: b53248d5b8d142108cf5a363f148980b)`); }\n                }\n\n                if (addrIsForAMetaStone || addrIsAMetaStone) {\n                    // we want to store the metastone in the same dir as the\n                    // timeline, not in the metastone's own gib dir\n                    let targetTjpGib: Gib;\n                    if (addrIsAMetaStone) {\n                        targetTjpGib = parseMetaStoneIb({ ib }).tjpGib;\n                    } else {\n                        const gibInfo = getGibInfo({ ibGibAddr: addr });\n                        targetTjpGib = gibInfo.tjpGib ?? getIbAndGib({ ibGibAddr: addr }).gib;\n                    }\n                    resPath += `${targetTjpGib}${pathSeparator}`;\n                } else {\n                    // at this point, stones and tjps are treated the same. for\n                    // tjp's, their gib _is_ the tjpGib\n                    resPath += `${gib}${pathSeparator}`;\n                }\n\n            } else if (gibPieces.length === 2) {\n                // belongs to a timeline\n                let { tjpGib, punctiliarHash } = getGibInfo({ gib, gibDelimiter: GIB_DELIMITER });\n                resPath += `${tjpGib}${pathSeparator}${punctiliarHash}${pathSeparator}`;\n            } else {\n                throw new Error(`invalid gib atow (11/2023). expected only one gib delimiter (${GIB_DELIMITER}) that splits two pieces of the gib, but we have ${gibPieces.length} many pieces. gib: ${gib} (E: 7d5f8608d79854e6d1d2878975258423)`);\n            }\n\n            // at this point, we have a full path to a directory. if this space\n            // is configured to mitigate long paths and if the path is already\n            // too long, then i'm not sure what to do. if it's not too long, we\n            // need to check to see if it will be when we add the filename.\n\n            const mitigateLongPaths = !!data.mitigateLongPaths;\n            const longPathLength = data.longPathLength;\n\n            /**\n             * we tweak the extension for binaries (i.e. pictures like .jpg, .png,\n             * etc.) in order to maintain the extension in the os's filesystem. (in\n             * a future full-ibgib-os, this will be a non-issue).\n             */\n            let ext: string;\n\n            if (isBinary({ addr })) {\n                const { binExt } = getBinHashAndExt({ addr });\n                ext = binExt.concat();\n            } else {\n                ext = 'json';\n            }\n\n            /**\n             * filename+ext using the `ib`.\n             * NOTE: if we're mitigating long paths, then we may not use this.\n             */\n            let filenameAsIbPlusExt: string = `${ib}.${ext}`;\n            /**\n             * filename+ext using the entire `addr`.\n             *\n             * this is used when doing meta stones (and I may change dna to use\n             * this also, but if so then i need to change the path in previous\n             * code).\n             *\n             * NOTE: if we're mitigating long paths, then we may not use this.\n             */\n            let filenameAsAddrPlusExt: string = `${addr}.${ext}`;\n\n            if (mitigateLongPaths && longPathLength) {\n                // have to take long path lengths into account\n                const ameliorateLongPathMsg = ` you have to place the root folder higher up in the OS's filesystem. (and you should put in a change request to the OS to fix their weak sauce/move to/fund a better OS.) Will try what we have and hope+pray.`;\n\n                if (resPath.length >= longPathLength) {\n                    throw new Error(`path is already too long without even having a filename. ${ameliorateLongPathMsg} (E: c126522a5cda4c2acb6de3a92fc2c423)`);\n                } else if ((resPath.length + ib.length) >= longPathLength || pretendItsALongPath) {\n                    if (logalot) { console.warn(`${lc} the path is too long when adding the full ib as the filename (even without the ext). (W: 3011a1e58641c53274d4776f58bb5323)`); }\n                    if (addrIsForAMetaStone) {\n                        if (addrIsAMetaStone) { console.error(`can't even get a metastone ib in the path. ${ameliorateLongPathMsg} (E: 962c52deb7a5b57842c97676a1192623)`); }\n                        resPath += filenameAsAddrPlusExt;\n                    } else {\n                        if (logalot) { console.log(`${lc} non metastone ib found (not logging ib here for privacy). will try to shorten... (I: 73dcb3f019c9b48b92fe67a9c4f2f123)`); }\n                        const shorterFilenamePlusExt =\n                            await this.buildPath_getShorterFilenameExtSubpath_ibTooLong_nonMetaStone({\n                                ib, ext, pathSeparator,\n                            });\n                        resPath += shorterFilenamePlusExt;\n                        if (resPath.length >= longPathLength) {\n                            console.error(`${lc} shortened filenamePlusExt and the path is still too long. i give up. ${ameliorateLongPathMsg} (E: df9e52098b94a99212c15c167e4d9f23)`);\n                        }\n                    }\n                } else {\n                    // the path + full ib/addr+ext is ok\n                    if (addrIsForAMetaStone) {\n                        resPath += filenameAsAddrPlusExt;\n                    } else {\n                        resPath += filenameAsIbPlusExt;\n                    }\n                }\n            } else {\n                // don't need to worry about mitigating path lengths\n                // the path + full ib/addr+ext is ok\n                if (addrIsForAMetaStone) {\n                    resPath += filenameAsAddrPlusExt;\n                } else {\n                    resPath += filenameAsIbPlusExt;\n                }\n            }\n\n            if (logalot) { console.log(`${lc} returning resPath: ${resPath} (I: 62a76a630335a872a4fc5f25dec4b623)`); }\n\n            return resPath;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * if we're here, then the path is too long with the ib.\n     * we need to do a couple things:\n     *\n     * 1. make this deterministic\n     * 2. indicate to others that may be traversing raw file system ibgib files\n     *    (like this one) that it has been adjusted to a long path.\n     * 3. not make it too convoluted so that those same traversers can do so in\n     *    a reasonably straight-forward manner.\n     *\n     * With this given, my first implementation (atow 11/2023) will...\n     *\n     * 1. subpath to a \"long\" subpath (which should be a single character plus a\n     *    path delimiter e.g. slash).\n     *   * adds 1 characters + 1 slash = 2\n     * 2. hash the ib and shard subpath to the first 4 chars.\n     *   * adds 4 characters + 1 slash = 5\n     * 3. substring the ib to the first N characters\n     *   * atow is N = 32\n     *   * adds N characters + 1 dot + ext.length ~=~ N+5-ish chars. (37ish)\n     *\n     * This will add a total of 44-ish chars, which is less than what a\n     * metastone path would be. I say this, because atow (11/2023) the code\n     * execution has already checked that a metastone would be valid. So we're\n     * just trying to exclude very long ib's that have e.g. 100+ characters.\n     */\n    protected async buildPath_getShorterFilenameExtSubpath_ibTooLong_nonMetaStone({\n        ib,\n        ext,\n        pathSeparator,\n    }: {\n        ib: Ib,\n        ext: string,\n        pathSeparator: string,\n    }): Promise<string> {\n        const lc = `${this.lc}[${this.buildPath_getShorterFilenameExtSubpath_ibTooLong_nonMetaStone.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 1f14c5de4174d726182c5dc97bd62a23)`); }\n\n            let resAdjustedFilenameExtSubpath = '';\n\n            //  * 1. subpath to a \"long\" subpath (which should be a single character plus a\n            //  *    path delimiter e.g. slash).\n            //  *   * adds 1 characters + 1 slash = 2\n            let longSubPath = this.data!.longSubPath || IBGIB_LONG_SUBPATH;\n            if (longSubPath.length !== 1) {\n                console.warn(`${lc} longSubPath (this.data.longSubPath || IBGIB_LONG_SUBPATH) longer than one char. should be 1 char. substringing to the first char. (W: 8c19a983730f4b62ac4208f7d21c90fc)`);\n                longSubPath = longSubPath.substring(0, 1) || 'l'; // l for long, get it\n            }\n            resAdjustedFilenameExtSubpath += `${longSubPath}${pathSeparator}`;\n\n            //  * 2. hash the ib and shard subpath to the first 4 chars.\n            //  *   * adds 4 characters + 1 slash = 5\n            const ibHash = await hash({ s: ib })\n            const firstFourOfIbHash = ibHash.substring(0, 4);\n            resAdjustedFilenameExtSubpath += `${firstFourOfIbHash}${pathSeparator}`;\n\n            //  * 3. substring the ib to the first N characters and add ext\n            //  *   * atow is N = 32\n            //  *   * adds N characters + 1 dot + ext.length ~=~ N+5-ish chars. (37ish)\n            const ibSubstring = ib.substring(0, ARBITRARY_IB_SUBSTRING_LENGTH_FOR_MITIGATE_LONG_PATH);\n            resAdjustedFilenameExtSubpath += `${ibSubstring}.${ext}`;\n\n            return resAdjustedFilenameExtSubpath;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #endregion other helpers\n}\n", "/**\n * @module node-filesystem-space-types\n *\n * mostly interfaces, some constants\n */\n\nimport { IbGibRel8ns_V1, } from '@ibgib/ts-gib/dist/V1/index.mjs';\n\n// import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';\nimport { INDEXED_DB_LONG_PATH_LENGTH } from './web-filesystem-space-constants.mjs';\nimport { FilesystemSpaceData_V1, FilesystemSpaceOptionsData, FilesystemSpaceOptionsIbGib, FilesystemSpaceOptionsRel8ns, FilesystemSpaceResultData, FilesystemSpaceResultIbGib, FilesystemSpaceResultRel8ns } from '@ibgib/core-gib/dist/witness/space/filesystem-space/filesystem-space-v1.mjs';\nimport { DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS, IBGIB_SPACE_NAME_DEFAULT, ZERO_SPACE_ID } from '@ibgib/core-gib/dist/witness/space/space-constants.mjs';\nimport { DEFAULT_FILESYSTEM_SPACE_DESCRIPTION, IBGIB_BASE_DIR, IBGIB_BASE_SUBPATH, IBGIB_BIN_SUBPATH, IBGIB_DNA_SUBPATH, IBGIB_ENCODING, IBGIB_IBGIBS_SUBPATH, IBGIB_LONG_SUBPATH, IBGIB_META_SUBPATH, IBGIB_SPACE_SUBPATH_DEFAULT } from '@ibgib/core-gib/dist/witness/space/filesystem-space/filesystem-constants.mjs';\nimport { getGlobalDbName } from '../../../helpers.web.mjs';\n\n\n/**\n * This is the shape of data about this space itself (not the contained ibgibs' spaces).\n */\nexport interface WebFilesystemSpaceData_V1 extends FilesystemSpaceData_V1 {\n}\n\n/**\n * Used in bootstrapping.\n *\n * If you change this, please bump the version\n *\n * (but of course won't be the end of the world when this doesn't happen).\n *\n * ## notes\n *\n * This is a terrible kluge port from NodeFilesystemSpaceData_V1. I am just\n * moving \"as fast as I can\" (I can't move fast these days). Little of the\n * filesystem internal details reallly matter I think, as this is just meant to\n * be a local space living on indexeddb. The main thing is segregation of local\n * spaces from each other, but I think this is covered to begin with via the\n * space name used in the path somewhere.\n */\nexport const DEFAULT_WEB_FILESYSTEM_SPACE_DATA_V1: WebFilesystemSpaceData_V1 = {\n    version: '1',\n    uuid: ZERO_SPACE_ID,\n    name: IBGIB_SPACE_NAME_DEFAULT,\n    classname: 'WebFilesystemSpace_V1',\n    // baseDir: IBGIB_BASE_DIR,\n    /**\n     * atow (12/2025), i am pulling out from blank-gib to web-gib, a more\n     * generic framework in the making. This baseDir is a question mark, but it\n     * seems that tying this to the consuming app's global db name is a good\n     * idea. But only time will tell.\n     *\n     * I'm considering atow (12/6/2024) using this baseDir as the db name, and\n     * the spaceId as the store. To effect this, the writeFile will use the two\n     * lowest directories as the db & store names, e.g.,\n     *\n     *   blank^gib/[spaceId]/[other unnecessary paths from node port]/ib^gibaddr\n     *\n     * (This path will be spliced when \"writing the file path\".)\n     *\n     * So the db name is blank^gib, the store name is the spaceId. The other\n     * parts of the path are vestigial from node implementation, just as long as\n     * it resolves down to the right ibgib addr consistently. If something\n     * requires listing other spaces, then the indexed db.stores I think allows\n     * for this.\n     */\n    baseDir: getGlobalDbName(),\n    encoding: IBGIB_ENCODING,\n    baseSubPath: IBGIB_BASE_SUBPATH,\n    spaceSubPath: IBGIB_SPACE_SUBPATH_DEFAULT,\n    ibgibsSubPath: IBGIB_IBGIBS_SUBPATH,\n    metaSubPath: IBGIB_META_SUBPATH,\n    binSubPath: IBGIB_BIN_SUBPATH,\n    dnaSubPath: IBGIB_DNA_SUBPATH,\n    longSubPath: IBGIB_LONG_SUBPATH,\n    mitigateLongPaths: false,\n    longPathLength: INDEXED_DB_LONG_PATH_LENGTH,\n    persistOptsAndResultIbGibs: false,\n    validateIbGibAddrsMatchIbGibs: false,\n    longPollingIntervalMs: DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS,\n    allowPrimitiveArgs: false,\n    catchAllErrors: true,\n    description: DEFAULT_FILESYSTEM_SPACE_DESCRIPTION,\n    trace: false,\n}\n\n/** Marker interface atm */\nexport interface WebFilesystemSpaceRel8ns_V1 extends IbGibRel8ns_V1 { }\n\n/**\n * Space options involve whether we're getting/putting ibgibs categorized as\n * meta, bin, dna.\n *\n * We'll leverage the fact that we don't need to get dna very often, and that\n * meta ibgibs act differently and are recorded differently.\n *\n * For example, we don't necessarily want to keep the past of certain meta\n * objects, because it may change (and thus grow) too quickly.\n */\nexport interface WebFilesystemSpaceOptionsData extends FilesystemSpaceOptionsData {\n}\n\nexport interface WebFilesystemSpaceOptionsRel8ns extends FilesystemSpaceOptionsRel8ns {\n}\n\n/** Marker interface atm */\nexport interface WebFilesystemSpaceOptionsIbGib\n    extends FilesystemSpaceOptionsIbGib<WebFilesystemSpaceOptionsData, WebFilesystemSpaceOptionsRel8ns> {\n}\n\n/** Marker interface atm */\nexport interface WebFilesystemSpaceResultData extends FilesystemSpaceResultData {\n}\n\nexport interface WebFilesystemSpaceResultRel8ns extends FilesystemSpaceResultRel8ns {\n}\n\nexport interface WebFilesystemSpaceResultIbGib\n    extends FilesystemSpaceResultIbGib<WebFilesystemSpaceResultData, WebFilesystemSpaceResultRel8ns> {\n}\n/**\n * currently i'm just taking this from the definition of node's `Buffer` type.\n *\n * ## notes\n *\n * * using this with handle-reify-file.mts when reading the file.\n * * 'binary' may resolve to 'latin1' per SO\n *   * https://stackoverflow.com/questions/46441667/reading-binary-data-in-node-js\n */\nexport type FileEncoding =\n    | 'ascii'\n    | 'utf8'\n    | 'utf-8'\n    | 'utf16le'\n    | 'ucs2'\n    | 'ucs-2'\n    | 'base64'\n    | 'base64url'\n    | 'latin1'\n    | 'binary'\n    | 'hex';\nexport const FileEncoding = {\n    ascii: 'ascii' as FileEncoding,\n    utf8: 'utf8' as FileEncoding,\n    utf_8: 'utf-8' as FileEncoding,\n    ['utf-8']: 'utf-8' as FileEncoding,\n    utf16le: 'utf16le' as FileEncoding,\n    ucs2: 'ucs2' as FileEncoding,\n    ucs_2: 'ucs-2' as FileEncoding,\n    ['ucs-2']: 'ucs-2' as FileEncoding,\n    base64: 'base64' as FileEncoding,\n    base64url: 'base64url' as FileEncoding,\n    latin1: 'latin1' as FileEncoding,\n    binary: 'binary' as FileEncoding,\n    hex: 'hex' as FileEncoding,\n};\n/**\n * valid file encoding values per {@link FileEncoding}\n */\nexport const FILE_ENCODINGS = Object.values(FileEncoding);\n\nexport interface FileDataInfo {\n    inputPath: string;\n    detectedEncoding?: FileEncoding | undefined;\n    dataString?: string | undefined;\n    dataBuffer?: Uint8Array | undefined;\n}\nexport const B2TFS_DEFAULT_ENCODINGS_TO_TRY: (FileEncoding | undefined)[] = [\n    FileEncoding.utf8,\n    FileEncoding.utf16le,\n    FileEncoding.base64,\n    FileEncoding.binary,\n    undefined,\n];\n", "/**\n * @module web-filesystem-space-helper\n */\n\nimport { extractErrorMsg, pretty, unique, } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';\nimport { getIbAndGib, } from '@ibgib/ts-gib/dist/helper.mjs';\nimport { GIB, } from '@ibgib/ts-gib/dist/V1/index.mjs';\nimport { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';\nimport { parseSpaceIb } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';\nimport { SPACE_NAME_REGEXP } from '@ibgib/core-gib/dist/witness/space/space-constants.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';\nimport { WebFilesystemSpace_V1 } from './web-filesystem-space-v1.mjs';\nimport { B2TFS_DEFAULT_ENCODINGS_TO_TRY, FILE_ENCODINGS, FileDataInfo, FileEncoding } from './web-filesystem-space-types.mjs';\nimport { getGlobalDbName, PathUtilsHelper, uint8ArrayToString } from '../../../helpers.web.mjs';\nimport { storageGet, storagePut, storageReaddir, storageRmRF, } from '../../../storage/storage-helpers.web.mjs';\nimport { Dirent } from '../../../storage/storage-types.web.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT;\nconst pathUtils = new PathUtilsHelper();\n\n/**\n * tries to read the given path. if fails **FOR ANY REASON**, @returns `null`.\n *\n * does not throw\n *\n * @returns file contents as string or `null`\n */\nexport async function tryRead({\n    path,\n    directory,\n    encoding,\n}: {\n    path: string,\n    directory: string,\n    encoding: string,\n}): Promise<string | Uint8Array | null> {\n    const lc = `[${tryRead.name}]`;\n    try {\n        if (logalot) {\n            console.log(`${lc} starting...`);\n            // console.log(`${lc} cwd: ${cwd()}`);\n            if (path.includes('bootstrap^gib') || path.includes('gib/bootstrap.json')) { console.log(`${lc} trying bootstrap^gib... (I: cde10726c55737e5c5a2e0a66a188e24)`); }\n        }\n        const fullPath = pathUtils.join(directory, path);\n        if (logalot) { console.log(`${lc} fullPath: ${fullPath} (I: e5cfdd62247c6ba05dffb64d8f25d424)`); }\n        encoding ||= 'utf8';\n        let resRead: string | undefined = undefined;\n\n        let resRead_uncasted = await readFile(fullPath, { encoding });\n        if (resRead_uncasted instanceof Uint8Array) {\n            resRead = uint8ArrayToString(resRead_uncasted);\n        } else if (typeof resRead_uncasted === 'string') {\n            resRead = resRead_uncasted;\n        }\n\n        if (logalot) {\n            console.log(`${lc} record found. data length: ${resRead?.length ?? 0}. fullPath: ${fullPath}. console.dir(resRead)... (I: be5cfbf04874b4e8e4787ad966cb8424)`);\n            console.dir(resRead)\n        }\n        return resRead ?? null;\n    } catch (error) {\n        if (logalot) { console.log(`${lc} fullPath not found from directory (${directory}) and path (${path})\\nerror:\\n${extractErrorMsg(error)} (I: 8f93e583c048fac0682f55ca74df0324)`); }\n        return null;\n    } finally {\n        if (logalot) { console.log(`${lc} complete. (I: 22a6958aee350e4d99b76057ec8b9224)`); }\n    }\n}\n\nexport async function tryRead_bin({\n    path,\n    directory,\n    encoding,\n}: {\n    path: string,\n    directory: string,\n    encoding: string,\n}): Promise<FileDataInfo | null> {\n    const lc = `[${tryRead_bin.name}]`;\n    try {\n        if (logalot) {\n            console.log(`${lc} starting...`);\n            // console.log(`${lc} cwd: ${cwd()}`);\n            if (path.includes('bootstrap^gib')) { console.log(`${lc} trying bootstrap^gib... (I: acdb59d399ca16c45456392d935c0524)`); }\n        }\n        const fullPath = pathUtils.join(directory, path);\n        if (logalot) { console.log(`${lc} fullPath: ${fullPath} (I: abef0200a4b823b446713349ca102924)`); }\n        encoding ||= 'utf8';\n        let resRead: string | Uint8Array | undefined = undefined;\n        let encodingsToTry: FileEncoding[] = unique<FileEncoding>([\n            encoding as FileEncoding,\n            ...FILE_ENCODINGS,\n        ]);\n        let { dataBuffer, dataString, inputPath, detectedEncoding } = await getFileDataAndEncoding({\n            inputPath: path,\n            encodingsToTry,\n        });\n        if (!dataBuffer) { throw new Error(`getFileDataAndEncoding yielded falsy dataBuffer (E: f748ffc8c71c92be06a3566102ba8e24)`); }\n        resRead = dataBuffer;\n\n        if (logalot) {\n            console.log(`${lc} record found. data length: ${resRead?.length ?? 0}. fullPath: ${fullPath}. console.dir(resRead)... (I: b0c1da7e3849edd3edef899d74b21a24)`);\n            console.dir(resRead)\n        }\n\n        return {\n            dataBuffer, dataString, inputPath, detectedEncoding\n        };\n    } catch (error) {\n        if (logalot) { console.log(`${lc} fullPath not found from directory (${directory}) and path (${path})\\nerror:\\n${extractErrorMsg(error)} (I: 04b11599387ab37adf2b18a5f767cd24)`); }\n        return null;\n    } finally {\n        if (logalot) { console.log(`${lc} complete. (I: baa1e9d18134bc451b56bb5a56150824)`); }\n    }\n}\n\n/**\n * basic validation for a web fs space ibgib\n */\nexport async function validateWebFilesystemSpace_V1Intrinsically({ space }: { space: WebFilesystemSpace_V1<any, any> }): Promise<string[] | null> {\n    const lc = `[${validateWebFilesystemSpace_V1Intrinsically.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 7dab564254813390c30b082da3c18224)`); }\n        const errors: string[] = (await validateIbGibIntrinsically({ ibGib: space })) ?? [];\n\n        const { ib, gib, data, rel8ns } = space;\n\n        if (!ib) { errors.push('ib required. (E: f86c9e618fb11b4ac6036e5ff494ba24)'); }\n        if (!gib) { errors.push('gib required. (E: 18481a93f7fa0b8e44617b8ef49b6a24)'); }\n        if (gib === GIB) { errors.push('gib cannot be primitive. (E: fe6a5111f6d1647458c5a60ed337ee24)'); }\n\n        if (!data) {\n            errors.push('data required. (E: 50d2f1aaa72f61f09efed2361e88d124)');\n            return errors;\n        }\n\n        if (data.name) {\n            if (!SPACE_NAME_REGEXP.test(data.name)) {\n                errors.push(`space name (${data.name}) does not match space name regexp (${SPACE_NAME_REGEXP.source}). (E: 2eb2399e14f11f66a5f06ff9855bf225)`);\n            }\n        } else {\n            errors.push('space name required. (E: 3f3f85315602ee06d1d371a4729f0624)')\n        }\n        // if (!data.classname) { errors.push('classname required. (E: 5078a2ce307cce02b11c9c393db7c224)') }\n        if (data.classname && data.classname !== WebFilesystemSpace_V1.name) {\n            errors.push(`unknown classname (${data.classname}). data.classname !== FilesystemSpace_V1.name (E: 251aee62590dd6894144d8b4f9b7ab24)`);\n        }\n        if (!data.baseDir) { errors.push(`data.baseDir required (E: 66d5467064c4b794bf91218b14d53e24).`) }\n        if (!data.baseSubPath) { errors.push(`data.baseSubPath required. (E: 8545b7e9ea9a9b6265f447d9da2bac24)`) }\n        if (!data.binSubPath) { errors.push(`data.binSubPath required. (E: c9ca181a8b7979470669e2f7a081d624)`) }\n        if (!data.dnaSubPath) { errors.push(`data.dnaSubPath required. (E: 25a3b7a4c4820efa2e092fb122d3fe24)`) }\n        if (!data.ibgibsSubPath) { errors.push(`data.ibgibsSubPath required. (E: 8c2552c720bc1470d3566e1b87fe3824)`) }\n        if (!data.metaSubPath) { errors.push(`data.metaSubPath required. (E: 5f4d2c846717d21908569dab4b09a224)`) }\n        if (data.n && typeof data.n !== 'number') { errors.push(`data.n must be a number. (E: 0e4a25fd447dc835c68ee8657e455724)`) }\n        if (data.n === undefined) {\n            // the very first space record (tjp) has an undefined n and no rel8ns\n            if (rel8ns) { errors.push(`rel8ns not expected when data.n is falsy (custom temporal junction point indicator I suppose...) (E: 43714a88a1f248cdc827a97644d1c124)`); }\n        }\n        if (!data.spaceSubPath) { errors.push(`data.spaceSubPath required. (E: a49c78b367c5d8b9ddba92d50db8a624)`) }\n        if (!data.uuid) { errors.push(`data.uuid required. (E: bf6997ccf542adc15bc31e84012e9524)`) }\n        if (!data.encoding) { errors.push(`data.encoding required. (E: 4c61e1a5acc41b5f15f53535177b9124)`) }\n        /** should probably get this from Capacitor... */\n        const validEncodings = [\"utf8\", \"ascii\", \"utf16\"];\n        if (!validEncodings.includes(data.encoding)) {\n            errors.push(`invalid encoding: ${data.encoding}. validEncodings: ${validEncodings.join(', ')} (E: 8d2ae9fed4f59ab72c0e7e17bdbda124)`);\n        }\n\n        // ensure ib matches up with internal data\n        const { spaceClassname, spaceId, spaceName } = parseSpaceIb({ spaceIb: ib });\n        if (data.classname && (spaceClassname !== data.classname)) {\n            errors.push(`ib's spaceClassname (${spaceClassname}) must match data.classname (${data.classname}) (E: 9d1fce5cf2d42de2d96b487ab3570a24)`);\n        }\n        if (spaceId !== data.uuid) {\n            errors.push(`ib's spaceId (${spaceId}) must match data.uuid (${data.uuid}) (E: 45f5b88a62ac830302e74b33270b0224)`);\n        }\n        if (spaceName !== data.name) {\n            errors.push(`ib's spaceName (${spaceName}) must match data.name (${data.name}) (E: a752c7bc00e251458dc72af76edcb924)`);\n        }\n\n        // ensure rel8ns make sense\n        if (data.n === undefined && (rel8ns?.past ?? []).length > 0) {\n            errors.push(`\"past\" rel8n not expected when data.n is falsy (E: f578bf87da6ab80144f8d879fa0d9724)`);\n        }\n        if (data.n && (rel8ns?.past ?? []).length === 0) {\n            errors.push(`\"past\" rel8n required when data.n is truthy (E: 7b1e06b911c6f4a1e313ea6cfcdc3a24)`);\n        }\n        if (data.n === 0 && (rel8ns?.past ?? []).length !== 1) {\n            errors.push(`\"past\" rel8n expected to have a single record when data.n === 0 (E: 47998507925497bb8b25dbf70e542a24)`);\n        }\n        if (rel8ns && (rel8ns.past?.length ?? -1) > 0) {\n            const pastAddrs = rel8ns.past as IbGibAddr[];\n            pastAddrs.forEach(x => {\n                const { ib: pastIb } = getIbAndGib({ ibGibAddr: x });\n                const pastIbInfo = parseSpaceIb({ spaceIb: pastIb });\n                if (pastIbInfo.spaceClassname && (pastIbInfo.spaceClassname !== spaceClassname)) {\n                    errors.push(`rel8ns.past address classname (${pastIbInfo.spaceClassname}) must match current spaceClassname (${spaceClassname}) (E: 71bdfd2c7235c6854963a451ddcd9f24)`);\n                }\n                if (pastIbInfo.spaceId !== spaceId) {\n                    errors.push(`rel8ns.past address spaceId (${pastIbInfo.spaceId}) must match current spaceId (${spaceId}) (E: 8b01f47268c34b8a638e397230331824)`);\n                }\n                // i want to allow this, but for now we're going to require not changing the name...\n                if (pastIbInfo.spaceName !== spaceName) {\n                    errors.push(`rel8ns.past address spaceName (${pastIbInfo.spaceName}) must match current spaceName (${spaceName}) (E: 323ce598506b19ae791377a449aa8e24)`);\n                }\n            });\n        }\n\n        return errors;\n    } catch (error) {\n        console.error(`${lc} ${error.message}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * gets the data and encoding of a given {@link inputPath} if that file exists.\n * if it doesn't exist, this will throw an ENOENT error, but this is not logged\n * as an error.\n *\n * this is because atow (03/2024) this is only used in a tryRead_bin function\n * where the file often does not exist.\n */\nexport async function getFileDataAndEncoding({\n    inputPath,\n    encodingsToTry = B2TFS_DEFAULT_ENCODINGS_TO_TRY,\n}: {\n    inputPath: string,\n    /**\n     * ignored in web version\n     */\n    encodingsToTry?: (FileEncoding | undefined)[],\n}): Promise<FileDataInfo> {\n    const lc = `[${getFileDataAndEncoding.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: be8a697780bd9f2dcc4e55ed557d3b24)`); }\n\n        if (encodingsToTry) {\n            console.warn(`${lc} encodingsToTry (${pretty(encodingsToTry)}) is ignored in this web version of this function. (W: 1dda04d8e0b7fb046cff5d89d3903924)`);\n        }\n\n        const resRead = await readFile(inputPath);\n        if (resRead instanceof Uint8Array) {\n            // uint8array\n            if (resRead.length === 0) {\n                console.warn(`${lc} file at inputPath (${inputPath}) has dataBuffer.length === 0, i.e., no data content. we are treating this as utf8. (W: 8159ac120ec276df17484c1d32870424)`)\n                return {\n                    inputPath,\n                    dataBuffer: resRead,\n                    detectedEncoding: FileEncoding.utf8,\n                    dataString: '',\n                };\n            } else {\n                const resRead_str = uint8ArrayToString(resRead);\n                return {\n                    inputPath,\n                    dataString: resRead_str,\n                    detectedEncoding: FileEncoding.utf8,\n                    dataBuffer: resRead,\n                };\n            }\n\n            // encodingsToTry ??= ['utf-8', 'utf8'];\n\n            // const tryEncoding = async (encoding: FileEncoding | undefined) => {\n            //     let res: [boolean, string | undefined];\n            //     try {\n\n            //         // const str = resRead.toString(encoding ?? undefined);\n            //        const str = uint8ArrayToString(resRead);\n            //         /**\n            //          * doesn't include the node.js replacement unicode char\n            //          */\n            //         const isProbablyCorrect = !str.includes('\\ufffd');\n            //         res = [isProbablyCorrect, str];\n            //         return res;\n            //     } catch (error) {\n            //         res = [false, undefined];\n            //     }\n            //     return res;\n            // }\n\n            // for (let i = 0; i < encodingsToTry.length; i++) {\n            // const maybeEncoding = encodingsToTry[i];\n            // const [isProbablyCorrectEncoding, dataString] = await tryEncoding(maybeEncoding);\n            // if (isProbablyCorrectEncoding) {\n            //     resDataAndEncoding = {\n            //         inputPath,\n            //         dataString,\n            //         detectedEncoding: maybeEncoding,\n            //         dataBuffer,\n            //     };\n            //     break;\n            // }\n            // }\n\n        } else if (typeof resRead === 'string') {\n            // utf8 on web\n            return {\n                inputPath,\n                dataString: resRead,\n                detectedEncoding: FileEncoding.utf8,\n                dataBuffer: undefined,\n            };\n        } else if (!resRead) {\n            // not found\n            return {\n                inputPath,\n                dataString: undefined,\n                detectedEncoding: undefined,\n                dataBuffer: undefined,\n            };\n        } else {\n            throw new Error(`(UNEXPECTED) resRead not Uint8Array, not string, not falsy? (E: bdeceb4c354da36708e31406adb30124)`);\n        }\n    } catch (error) {\n        // i'm just suppressing ENOENT at this time because in context, this is\n        // often the case. we do, however, rethrow the error for proper flow.\n        const emsg = extractErrorMsg(error);\n        if (!emsg.startsWith('ENOENT:')) { console.error(`${lc} ${emsg}`); }\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\ninterface FullPathInfo {\n    dbName: string,\n    storeName: string,\n    key: string,\n}\n\nfunction parseFullPath(fullPath: string): FullPathInfo {\n    const lc = `[${parseFullPath.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: c911bff0cb7333dfd45bde6925cce524)`); }\n\n        const pieces = fullPath.split('/');\n\n        // must be at least 3 pieces in path\n        if (pieces.length < 3) { throw new Error(`fullPath (${fullPath}) must have at least 3 pieces (E: d99c38d035551af3e85b7f767d911324)`); }\n\n        // dbName is the first piece\n        let dbName = pieces.shift()!;\n        if (dbName === '.') { dbName = getGlobalDbName(); }\n        // storeName is the second piece of the path\n        const storeName = pieces.shift()!;\n        // key is the rest of the path\n        const key = pieces.join('/');\n        return { dbName, storeName, key };\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * Writes a \"file\" to the \"filesystem\" using IndexedDB.\n *\n * This overload in the node version is used for writing string files (i.e.\n * non-binary utf-8 files).\n *\n * @param fullPath path to write to\n * @param data data to write\n * @param encoding ignored atow (11/2024) in this web version of this function.\n */\nexport function writeFile(fullPath: string, data: any, encoding: any): Promise<void>;\n/**\n * Writes a \"file\" to the \"filesystem\" using IndexedDB.\n *\n * ATOW (12/2024) this assumes the fullPath is in the form of\n *\n *   [dbName]/\n *\n * This overload in the node version is used for writing binary files.\n *\n * @param fullPath path to write to\n * @param data data to write\n */\nexport function writeFile(fullPath: string, data: any): Promise<void>;\nexport async function writeFile(fullPath: string, data: any, encoding?: any): Promise<void> {\n    const lc = `[${writeFile.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 18c4f3558ab1f150382948556ab5f924)`); }\n\n        const { dbName, storeName, key } = parseFullPath(fullPath);\n\n        if (typeof data === 'string' || data instanceof Uint8Array) {\n            // utf8/string/binary on web\n            // maybe separate this later if we want to log type?\n            await storagePut({ dbName, storeName, key, value: data, });\n        } else {\n            throw new Error(`(UNEXPECTED) data not string or Uint8Array? (E: ac3e1c15484dbc7188c75e62ab78b124)`);\n        }\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n\n// export function readFile(fullPath: any, opts: { encoding: string; }): string | Promise<string | undefined> | undefined;\n// export function readFile(fullPath: any): string | Promise<string | undefined> | Uint8Array | Promise<Uint8Array | undefined> | undefined;\nexport async function readFile(\n    fullPath: any,\n    opts?: { encoding: string; },\n): Promise<string | Uint8Array | undefined> {\n    const lc = `[${readFile.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 37fd6ea3d79fc1ab797049ef00f6e224)`); }\n        // implement the read complement to writeFile\n        const { dbName, storeName, key } = parseFullPath(fullPath);\n        const resGet = await storageGet({ dbName, storeName, key });\n        return resGet;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport async function rm(fullPath: string, opts: {\n    /**\n     * ignored in web version atow (11/2024)\n     */\n    force: boolean\n}): Promise<void> {\n    const lc = `[${rm.name}]`;\n    if (logalot) {\n        console.log(fullPath);\n        console.log(JSON.stringify(opts));\n    }\n    const { dbName, storeName, key: pathToRm } = parseFullPath(fullPath);\n    await storageRmRF({ dbName, storeName, pathToRm: pathToRm });\n}\n\n/**\n * is this necessary in web version?\n * @param fullPath\n * @param opts\n */\nexport function mkdirSync(fullPath: string, opts: { recursive: boolean }): void {\n    const lc = `[${mkdirSync.name}]`;\n    throw new Error(`${lc} not implemented (E: da4684557038657662e5d0d17a0c9224)`);\n}\n\n/**\n * mimic node's readdir when `withFileTypes` is true.\n *\n * in this overload, returns mimicked `Dirent[]`\n */\nexport async function readdir(\n    containingDir: string,\n    opts: { withFileTypes: true; recursive?: boolean }\n): Promise<Dirent[]>;\n/**\n * mimic node's readdir when `withFileTypes` is falsy.\n *\n * in this overload, returns `string[]`\n */\nexport async function readdir(\n    containingDir: string,\n    opts?: { withFileTypes?: false; recursive?: boolean }\n): Promise<string[]>;\nexport async function readdir(\n    containingDir: string,\n    opts?: {\n        withFileTypes?: boolean;\n        recursive?: boolean;\n    }\n): Promise<string[] | Dirent[]> {\n    const lc = `[${readdir.name}]`;\n    const { dbName, storeName, key: dirPath } = parseFullPath(containingDir);\n\n    return await storageReaddir({\n        dbName, storeName, dirPath,\n        withFileTypes: opts?.withFileTypes ?? false,\n    });\n}\n\n// export function existsSync(fullPath: string): boolean {\n//     const lc = `[${existsSync.name}]`;\n//     throw new Error(`${lc} not implemented (E: 2e2577807b69b6f2e475783d59cd1c24)`);\n// }\n", "/**\n * @module web-filesystem-space-v1\n *\n * uuids unique\n */\nimport { clone, extractErrorMsg, } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { getIbAndGib, getIbGibAddr, } from '@ibgib/ts-gib/dist/helper.mjs';\nimport { getGib, getGibInfo, } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';\nimport {\n    IbGib_V1, IbGibRel8ns_V1,\n} from '@ibgib/ts-gib/dist/V1/types.mjs';\nimport { Gib, Ib, IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';\nimport { validateIbGibAddr } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';\nimport { IBGIB_DELIMITER } from '@ibgib/ts-gib/dist/V1/constants.mjs';\nimport { isBinary, parseBinIb, toDto, } from '@ibgib/core-gib/dist/common/other/ibgib-helper.mjs';\nimport { FilesystemSpace_V1 } from '@ibgib/core-gib/dist/witness/space/filesystem-space/filesystem-space-v1.mjs';\nimport { getSpaceIb } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';\nimport {\n    DeleteIbGibFileOpts, DeleteIbGibFilesResult,\n    GetIbGibFileOpts,\n    GetIbGibFileResult,\n    PutIbGibFileOpts,\n    PutIbGibFileResult\n} from '@ibgib/core-gib/dist/witness/space/filesystem-space/filesystem-types.mjs';\nimport {\n    IBGIB_BASE_SUBPATH, IBGIB_SPACE_SUBPATH_DEFAULT, IBGIB_BASE_DIR,\n    IBGIB_ENCODING, IBGIB_IBGIBS_SUBPATH, IBGIB_META_SUBPATH,\n    IBGIB_BIN_SUBPATH,\n    IBGIB_DNA_SUBPATH,\n    DEFAULT_LONG_PATH_LENGTH,\n    IBGIB_LONG_SUBPATH,\n} from '@ibgib/core-gib/dist/witness/space/filesystem-space/filesystem-constants.mjs';\nimport {\n    WebFilesystemSpaceData_V1, WebFilesystemSpaceRel8ns_V1,\n    WebFilesystemSpaceOptionsData, WebFilesystemSpaceOptionsRel8ns, WebFilesystemSpaceOptionsIbGib,\n    WebFilesystemSpaceResultData, WebFilesystemSpaceResultRel8ns,\n    DEFAULT_WEB_FILESYSTEM_SPACE_DATA_V1,\n    FileDataInfo,\n} from './web-filesystem-space-types.mjs';\nimport { META_STONE_ATOM } from '@ibgib/core-gib/dist/common/meta-stone/meta-stone-constants.mjs';\nimport { isMetaStone, validateCommonMetaStoneIb } from '@ibgib/core-gib/dist/common/meta-stone/meta-stone-helper.mjs';\nimport { BinIbGib_V1 } from '@ibgib/core-gib/dist/common/bin/bin-types.mjs';\nimport { readdir, rm, tryRead, tryRead_bin, writeFile } from './web-filesystem-space-helper.mjs';\nimport { PathUtilsHelper } from '../../../helpers.web.mjs';\nimport { INDEXED_DB_LONG_PATH_LENGTH } from './web-filesystem-space-constants.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT;\nconst pathUtils = new PathUtilsHelper();\n\n/**\n * Base class convenience for a local space with V1 ibgibs working with the node\n * filesystem.\n *\n * Unfortunately, file systems have short file name requirements, where 255 is\n * often the max length of a filename. So this cannot store ibgibs directly by\n * their address.\n *\n * This naively caches ibGibs in memory. When not found there, will looks in\n * files using Ionic `FileSystem`.\n */\nexport class WebFilesystemSpace_V1<\n    TData extends WebFilesystemSpaceData_V1 = WebFilesystemSpaceData_V1,\n    TRel8ns extends WebFilesystemSpaceRel8ns_V1 = WebFilesystemSpaceRel8ns_V1\n> extends FilesystemSpace_V1<\n    WebFilesystemSpaceOptionsData,\n    WebFilesystemSpaceOptionsRel8ns,\n    WebFilesystemSpaceResultData,\n    WebFilesystemSpaceResultRel8ns,\n    TData,\n    TRel8ns\n> {\n\n    /**\n     * Log context for convenience with logging. (Ignore if you don't want to use this.)\n     */\n    protected lc: string = `[${WebFilesystemSpace_V1.name}]`;\n\n    constructor(\n        // /**\n        //  * Default predicate value when putting an unknown ibGib.\n        //  *\n        //  * ## notes\n        //  *\n        //  * So when a repo witnesses another ibGib, it either defaults to\n        //  * storing that ibGib or not storing that ibGib. This is what that\n        //  * is referring to. If it's optimistic, then it stores any ibGib by\n        //  * default and it passes its put predicate.\n        //  */\n        // public optimisticPut: boolean = true,\n        initialData?: TData,\n        initialRel8ns?: TRel8ns,\n    ) {\n        super(initialData ?? clone(DEFAULT_WEB_FILESYSTEM_SPACE_DATA_V1), initialRel8ns);\n        const lc = `${this.lc}[ctor]`;\n\n        // try {\n        //     if (logalot) { console.log(`${lc} starting...`); }\n        //     this.initialize();\n        // } catch (error) {\n        //     console.error(`${lc} ${extractErrorMsg(error)}`);\n        //     throw error;\n        // } finally {\n        //     if (logalot) { console.log(`${lc} complete.`); }\n        // }\n    }\n\n    /**\n     * Factory static method to create the space with the given\n     * `dto` param's ibGib properties.\n     *\n     * We do this because when we persist this space (and its settings\n     * located in `data`), we do not save the actual class instantiation\n     * but just the ibgib properties. Use this factory method to\n     * create a new space instance and rehydrate from that saved dto.\n     *\n     * ## notes\n     *\n     * * DTO stands for data transfer object.\n     *\n     * @param dto space ibGib dto that we're going to load from\n     * @returns newly created space built upon `dto`\n     */\n    static async createFromDto<\n        TData extends WebFilesystemSpaceData_V1 = WebFilesystemSpaceData_V1,\n        TRel8ns extends IbGibRel8ns_V1 = IbGibRel8ns_V1\n    >(dto: IbGib_V1<TData, TRel8ns>): Promise<WebFilesystemSpace_V1<TData, TRel8ns>> {\n        const lc = `[${FilesystemSpace_V1.name}][${this.createFromDto.name}]`;\n        if (logalot) { console.log(`${lc}`); }\n        const space = new WebFilesystemSpace_V1<TData, TRel8ns>();\n        await space.initialized;\n        await space.loadIbGibDto(dto);\n        return space;\n    }\n\n    protected async validateWitnessArg(arg: WebFilesystemSpaceOptionsIbGib): Promise<string[]> {\n        const lc = `${this.lc}[${this.validateWitnessArg.name}]`;\n        let errors: string[] = [];\n        try {\n            errors = (await super.validateWitnessArg(arg)) || [];\n            if (arg.data?.cmd === 'put' && (arg.ibGibs || []).length === 0) {\n                errors.push(`when \"put\" cmd is called, ibGibs required.`);\n            }\n            if (arg.data?.cmd === 'get' && (arg.data?.ibGibAddrs || []).length === 0) {\n                errors.push(`when \"get\" cmd is called, ibGibAddrs required.`);\n            }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (errors?.length > 0) { console.error(`${lc} errors: ${errors}`); }\n        }\n\n        return errors;\n    }\n\n    // _pathUtils: PathUtilsHelper | undefined;\n    // get pathUtils(): PathUtilsHelper {\n    //     if (!this._pathUtils) { this._pathUtils = new PathUtilsHelper(); }\n    //     return this._pathUtils;\n    // }\n\n    /**\n     * Initializes to default space values.\n     */\n    protected async initialize(): Promise<void> {\n        const lc = `${this.lc}[${this.initialize.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (!this.data) {\n                this.data = clone(DEFAULT_WEB_FILESYSTEM_SPACE_DATA_V1);\n                this.data = this.data!; // why does ts compiler need this?\n            }\n            // if (!this.data?.classname) { this.data!.classname = WebFilesystemSpace_V1.name }\n            if (this.data!.classname !== WebFilesystemSpace_V1.name) {\n                if (this.data.classname) {\n                    // only warn if the consumer has explicitly set a different classname\n                    console.warn(`${lc} this.data.classname (${this.data.classname}) !== ${WebFilesystemSpace_V1.name}. overriding this. (W: 400ef8f8626132bf763b5c68bc1d3424)`);\n                }\n                this.data!.classname = WebFilesystemSpace_V1.name; // always set?\n            }\n            if (!this.data.encoding) { this.data.encoding = IBGIB_ENCODING; }\n            if (!this.data.baseDir) { this.data.baseDir = IBGIB_BASE_DIR; }\n            // if (!this.data.baseSubPath) { this.data.baseSubPath = IBGIB_BASE_SUBPATH; }\n            if (!this.data.uuid) { throw new Error(`this.data.uuid is falsy. right now i'm assuming data.uuid is truthy. this is what i'm using atow (12/2024) as the indexeddb db.store to be the uuid via the baseSubPath (E: cd3475cc43d1384dccf0b20dd322b124)`); }\n            this.data.baseSubPath = this.data.uuid;\n            if (!this.data.spaceSubPath) { this.data.spaceSubPath = IBGIB_SPACE_SUBPATH_DEFAULT; }\n            if (!this.data.ibgibsSubPath) { this.data.ibgibsSubPath = IBGIB_IBGIBS_SUBPATH; }\n            if (!this.data.metaSubPath) { this.data.metaSubPath = IBGIB_META_SUBPATH; }\n            if (!this.data.binSubPath) { this.data.binSubPath = IBGIB_BIN_SUBPATH; }\n            if (!this.data.dnaSubPath) { this.data.dnaSubPath = IBGIB_DNA_SUBPATH; }\n\n            // do nothing, allow falsy\n            if (this.data.longSubPath === undefined) { this.data.longSubPath = IBGIB_LONG_SUBPATH; }\n            if (this.data.longPathLength === undefined) { this.data.longPathLength = INDEXED_DB_LONG_PATH_LENGTH; }\n            if (this.data.mitigateLongPaths === undefined) { this.data.mitigateLongPaths = false; }\n\n            this.ib = getSpaceIb({ space: this, classname: this.data!.classname });\n            this.gib = await getGib({ ibGib: this });\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async putFile({\n        ibGib,\n        isDna,\n    }: PutIbGibFileOpts): Promise<PutIbGibFileResult> {\n        const lc = `${this.lc}[${this.putFile.name}]`;\n\n        let result: PutIbGibFileResult = {};\n\n        try {\n            if (!ibGib) { throw new Error(`ibGib required. (E: bb41678a0e46f60782db4641e7355a24)`) };\n\n            const thisData = this.data!;\n            // await this.ensureAllDirsExist();\n            let path: string = \"\";\n            let data: any = \"\";\n\n            const addr = getIbGibAddr({ ibGib });\n            const isBin = isBinary({ addr });\n            path = await this.buildPath({\n                addr, isDna: isDna ?? false, isBin, ensureMetaStonePaths: true,\n            });\n            // await this.ensureDirsImpl([pathUtils.dirname(path)]); // needed in web fs space?\n\n            let fullPath = pathUtils.join(thisData.baseDir, path);\n\n            if (logalot) { console.log(`${lc} fullPath: ${fullPath} (I: accfac2f2ee924da0184e241c2408624)`); }\n            if (logalot) { console.log(`${lc} path: ${path}, directory: ${thisData.baseDir}, thisData.encoding: ${thisData.encoding} (I: 498dd4e293f7da0eef4b3dea2ee32524)`); }\n\n\n            let encoding: string | undefined;\n\n            if (!isBin) {\n                // not binary - most ibgibs will not be bins.\n\n                // we only want to persist the ibGib protocol properties (not\n                // any functions or other properties that might exist on the\n                // incoming ibGib arg)\n                const bareIbGib = toDto({ ibGib })\n                data = JSON.stringify(bareIbGib);\n\n                encoding = thisData.encoding || 'utf8';\n                await writeFile(fullPath, data, encoding as BufferEncoding);\n            } else {\n                // binary\n                const binIbGib = ibGib as BinIbGib_V1;\n                data = binIbGib.data;\n                if (!data) { throw new Error(`(UNEXPECTED) binIbGib.data falsy? I'm trying to have data always populated for bin ibgibs even if it is an empty Uint8Array. (E: 861489baffc294baf7b463333f389824)`); }\n                await writeFile(fullPath, data);\n            }\n\n            result.success = true;\n        } catch (error) {\n            const errorMsg = `${lc} ${extractErrorMsg(error)}`;\n            console.error(errorMsg);\n            result.errorMsg = errorMsg;\n        }\n\n        return result;\n    }\n\n    protected async deleteFile({\n        addr,\n        isDna,\n    }: DeleteIbGibFileOpts): Promise<DeleteIbGibFilesResult> {\n        const lc = `${this.lc}[${this.deleteFile.name}]`;\n\n        const result: DeleteIbGibFilesResult = {};\n\n        try {\n            if (!addr) { throw new Error(`addr required. (E: a2ca4b3ae9bb79891fd86c98af3de624)`) };\n\n            if (!this.data) { throw new Error(`this.data required (E: 6b6163a397c42adf5b03ca5117c0d624)`); }\n            const data = this.data;\n            let path: string = \"\";\n\n            if (!isBinary({ addr })) {\n                // regular ibGib\n                path = await this.buildPath({\n                    addr, isDna: isDna ?? false, ensureMetaStonePaths: true,\n                });\n            } else {\n                path = await this.buildPath({\n                    addr, isDna: false, isBin: true, ensureMetaStonePaths: false,\n                });\n            }\n            if (logalot) { console.log(`${lc} path: ${path}, directory: ${data.baseDir}`); }\n            const fullPath = pathUtils.join(this.data.baseDir, path);\n            await rm(fullPath, { force: true });\n            if (logalot) { console.log(`${lc} deleted. path: ${path}`); }\n            result.success = true;\n        } catch (error) {\n            const errorMsg = `${lc} ${extractErrorMsg(error)}`;\n            if (!errorMsg.includes('File does not exist')) {\n                console.error(errorMsg);\n            } else {\n                if (logalot) { console.log(`${lc} attempted to delete non-existent file. ${errorMsg} (I: 839257fb70d62a3273335d8536b15724)`); }\n            }\n            result.errorMsg = errorMsg;\n        }\n\n        return result;\n    }\n\n    protected async getFile({\n        addr,\n        isDna,\n    }: GetIbGibFileOpts): Promise<GetIbGibFileResult> {\n        let lc = `${this.lc}[${this.getFile.name}(${addr})]`;\n\n        const result: GetIbGibFileResult = {};\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 07e34fff2d9c7108dd79e5d6f93ed724)`); }\n            if (!addr) { throw new Error(`addr required`) };\n\n            const data = this.data!;\n            const { ib } = getIbAndGib({ ibGibAddr: addr });\n\n            const addrIsBin = isBinary({ addr });\n            const knownTransformIbs = ['fork', 'mut8', 'rel8', 'plan']; // hack/kluge here\n            const addrMightBeDna =\n                knownTransformIbs.some(x => x === ib || x.startsWith(ib + ' '));\n\n            const pathsToLook: string[] = [];\n\n            if (isDna || addrMightBeDna) {\n                pathsToLook.push(await this.buildPath({\n                    addr, isDna: true, ensureMetaStonePaths: false\n                }));\n            } else if (addrIsBin) {\n                pathsToLook.push(await this.buildPath({\n                    addr, isDna: false, isBin: true, ensureMetaStonePaths: false\n                }));\n            }\n\n            // always look in the main location as a last resort\n            pathsToLook.push(await this.buildPath({\n                addr, isDna: false, ensureMetaStonePaths: false\n            }));\n\n            // ...(pretend shortened as well as an absolute last last resort)\n            if (!isMetaStone({ addr })) {\n                pathsToLook.push(await this.buildPath({\n                    addr, isDna: false, ensureMetaStonePaths: false,\n                    pretendItsALongPath: true,\n                }));\n            }\n\n            // this is ugly atow (02/2024) because i'm struggling a bit of\n            // changing bin ibgibs to actually support binaries. i apologize.\n\n            if (!addrIsBin) {\n                // non-bin ibGib(s) retrieved (most ibgibs are non-bin)\n                let resRead: any = null;\n                for (const tryPath of pathsToLook) {\n                    const x = await tryRead({ path: tryPath, directory: data.baseDir, encoding: data.encoding });\n                    if (x) { resRead = x; break; }\n                }\n                if (resRead) {\n                    result.ibGib = JSON.parse(resRead) as IbGib_V1;\n                } else {\n                    if (logalot) { console.log(`${lc} paths not found: ${JSON.stringify(pathsToLook)} (I: 52287b4a0fb3e3fa5f893fa92bc15324)`); }\n                    // will return success since it's not really an error, but ibgib\n                    // will not be populated, indicating the addr was not found.\n                }\n            } else {\n                // bin\n                let resRead: FileDataInfo | null = null;\n                let { binEncoding, binHash } = parseBinIb({ addr });\n                if (binHash === '0') {\n                    // special case: if the binHash is 0, then it is an empty file.\n                    const { ib, gib } = getIbAndGib({ ibGibAddr: addr });\n                    result.ibGib = {\n                        ib,\n                        gib,\n                        data: new Uint8Array(0),\n                        // data: '',\n                        // rawData: Buffer.from([]),\n                    } as BinIbGib_V1;\n                } else {\n                    for (const tryPath of pathsToLook) {\n                        const x = await tryRead_bin({\n                            path: tryPath, directory: data.baseDir, encoding: binEncoding ?? data.encoding,\n                        });\n                        if (x) { resRead = x; break; }\n                    }\n\n                    if (resRead) {\n                        // all bins are buffers\n                        const { ib, gib } = getIbAndGib({ ibGibAddr: addr });\n                        const binIbGib: BinIbGib_V1 = {\n                            ib, gib, data: resRead.dataBuffer,\n                            // rawData: resRead.dataBuffer,\n                        }\n                        result.ibGib = binIbGib;\n                    } else {\n                        if (logalot) { console.log(`${lc} paths not found: ${JSON.stringify(pathsToLook)} (I: 9116435fa6198d1e2e40ed4467e72924)`); }\n                        // will return success since it's not really an error, but ibgib\n                        // will not be populated, indicating the addr was not found.\n                    }\n                }\n            }\n\n            result.success = true;\n        } catch (error) {\n            const errorMsg = `${lc} ${extractErrorMsg(error)}`;\n            console.error(errorMsg);\n            result.errorMsg = errorMsg;\n        } finally {\n            if (logalot) { console.log(`${lc} complete. (I: d648c9b72261e509dac1e36279f8eb24)`); }\n        }\n\n        return result;\n    }\n\n    protected async ensurePermissions(): Promise<boolean> {\n        const lc = `${this.lc}[${this.ensurePermissions.name}]`;\n        if (logalot) { console.log(`${lc} always returns true in base class (I: eaa254b35aadb047b2c4af58f9ec6f24)`); }\n        return true;\n    }\n\n    protected async ensureAllDirsExist(): Promise<void> {\n        const lc = `${this.lc}[${this.ensureAllDirsExist.name}]`;\n        try {\n            console.warn(`${lc} does nothing in web filesystem space. do I need to do anything in this concrete class? (W: 6f71512c4b32df68e483cf54e17e3124)`);\n            // if (logalot) { console.log(`${lc} starting... (I: d8ed5f71c09fc6124c36cd688edd8b24)`); }\n\n            // if (!this.data) { throw new Error(`this.data required (E: 48d1c9d922377d6c8693fd1b0a13e224)`); }\n            // if (!this.data.uuid) { throw new Error(`this.data.uuid required (E: 0257b3a432121db943f5e13e3c6b2d24)`); }\n\n            // const data = this.data!;\n\n            // /** these are the paths we're ensuring exist. all ibgibs are stored here. */\n            // const paths = [\n            //     data.baseSubPath, // = 'ibgib';\n            //     data.baseSubPath + '/' + data.spaceSubPath,\n            //     data.baseSubPath + '/' + data.spaceSubPath + '/' + data.ibgibsSubPath,\n            //     data.baseSubPath + '/' + data.spaceSubPath + '/' + data.metaSubPath,\n            //     data.baseSubPath + '/' + data.spaceSubPath + '/' + data.binSubPath,\n            //     data.baseSubPath + '/' + data.spaceSubPath + '/' + data.dnaSubPath,\n            // ];\n\n            // if (data.mitigateLongPaths) {\n            //     paths.push(data.baseSubPath + '/' + data.spaceSubPath + '/' + data.longSubPath);\n            // }\n\n            // await this.ensureDirsImpl(paths);\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * actually executes the ensure functionality for given `paths`. If they\n     * don't exist, then this tries to make the dirs.\n     * @param paths to ensure exist.\n     */\n    protected async ensureDirsImpl(paths: string[]): Promise<void> {\n        const lc = `${this.lc}[${this.ensureDirsImpl.name}]`;\n        try {\n            console.warn(`${lc} not implemented in this web-based class. do i need this? (W: 0c50f3eb750f11108e7cd2a1263d8124)`);\n\n            // if (logalot) { console.log(`${lc} starting... (I: 1edfc39f91edea3e92db02e95c740c24)`); }\n            // if (paths.length === 0) {\n            //     console.warn(`${lc} paths empty? returning early. (W: 0722ea869cad228463151cde8ee07f24)`)\n            //     return; /* <<<< returns early */\n            // }\n\n            // const directory = this.data!.baseDir;\n\n            // const getPathKey = (p: string) => { return directory.toString() + '/' + p; }\n\n            // let allExist = paths.every(p => this.pathExistsMap[getPathKey(p)]);\n            // if (allExist) {\n            //     if (logalot) { console.log(`${lc} allExist (I: 00a417b53878e2fd77bce374da2aae24)`); }\n            //     return; /* <<<< returns early */\n            // }\n\n            // const permitted = await this.ensurePermissions();\n            // if (!permitted) {\n            //     console.error(`${lc} permission not granted.`);\n            //     return; /* <<<< returns early */\n            // }\n\n            // for (let i = 0; i < paths.length; i++) {\n            //     const path = paths[i];\n            //     const lc2 = `${lc}[(path: ${path}, directory: ${directory})]`;\n            //     const fullPath = pathUtils.join(directory, path);\n\n            //     // check if we've already ensured for this path\n            //     const pathExistsKey = getPathKey(path);\n            //     let exists = this.pathExistsMap[pathExistsKey] || false;\n\n            //     if (!exists) {\n            //         // we've not checked this path (or it didn't exist)\n            //         try {\n            //             exists = existsSync(fullPath);\n            //             this.pathExistsMap[pathExistsKey] = exists;\n            //         } catch (error) {\n            //             if (logalot) { console.log(`${lc2} Did not exist`); }\n            //         }\n            //     }\n\n            //     if (!exists) {\n            //         // try full path\n            //         if (logalot) { console.log(`${lc2} creating...`); }\n            //         try {\n            //             mkdirSync(fullPath, { recursive: true });\n            //             exists = existsSync(fullPath);\n            //             if (logalot) { console.log(`${lc} exists: ${exists}`); }\n            //             this.pathExistsMap[pathExistsKey] = exists;\n            //         } catch (error) {\n            //             if (logalot) { console.log(`${lc2} Error creating. Trying next`); }\n            //         } finally {\n            //             if (logalot) { console.log(`${lc2} complete.`); }\n            //         }\n            //     }\n            // }\n\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /** */\n    protected async getMetaStoneAddrs({\n        ibGibAddr,\n        tjpGib,\n        fnFilterIb,\n    }: {\n        /**\n         * addr of ibGib for which we're getting the metastones.\n         */\n        ibGibAddr: IbGibAddr,\n        /**\n         * tjpGib of the metastone's target ibgib\n         */\n        tjpGib: Gib,\n        fnFilterIb?: (ib: Ib) => boolean,\n    }): Promise<string[]> {\n        const lc = `${this.lc}[${this.getMetaStoneAddrs.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: f9da77d2c1920dc33efabee27847d624)`); }\n\n            // first build the path with the given tjpGib\n            let pathSansBaseDir = await this.buildPath({\n                addr: ibGibAddr, ensureMetaStonePaths: false, isDna: false,\n                addrIsForAMetaStone: true,\n            });\n            let fullPath = pathUtils.join(this.data!.baseDir, pathSansBaseDir);\n            if (logalot) { console.log(`${lc} fullPath: ${fullPath} (I: 7d69faa728f178ef5261291b4a44a424)`); }\n\n            // the given ibgib's containing dir is the one that should contain\n            // the metastones.\n            let gibInfo = getGibInfo({ ibGibAddr });\n\n            let containingDir = !!gibInfo.tjpGib ?\n                pathUtils.dirname(pathUtils.join(fullPath, '..')) :\n                pathUtils.dirname(fullPath);\n            if (logalot) { console.log(`${lc} containingDir: ${containingDir} (I: 867174fbd4b3640d023dce741208b624)`); }\n\n            // iterate through the files for metastones.\n            const fnFilter = fnFilterIb ?\n                (s: string) => s.startsWith(META_STONE_ATOM) && fnFilterIb(s) :\n                (s: string) => s.startsWith(META_STONE_ATOM);\n            let filenames: string[] = [];\n            try {\n                if (logalot) { console.log(`${lc} calling readdir(containingDir) (I: 9adcee17e5b5121a36f3d6e29d3fb224)`); }\n                filenames = await readdir(containingDir, {\n                    recursive: false,\n                    withFileTypes: false,\n                });\n            } catch (error) {\n                let emsg = extractErrorMsg(error);\n                if (!emsg.includes('ENOENT')) { // no such file or directory\n                    console.warn(`${lc} readdir error did not contain ENOENT...not sure what this is...maybe a different OS no dir exists emsg? Treating this as if dir does not exist. (W: 4fee7ed52dc4c987559eead57c89f724)`);\n                } else {\n                    if (logalot) { console.log(`${lc} readdir errors: ${extractErrorMsg(error)} (I: 95d041a148844dd09700875a1a82c424)`); }\n                }\n                filenames = [];\n            }\n            if (filenames.length === 0) {\n                if (logalot) { console.log(`${lc} filenames: [empty]. no metastones found. (I: b42abb33f7636b49c195b36fca6dce24)`); }\n                return []; /* <<<< returns early */\n            }\n            if (logalot) { console.log(`${lc} filenames: ${filenames} (I: 18e77f7451ce57bbbccddf9bef768624)`); }\n\n            /**\n             * atow (11/2023) extensions are hard-coded to \".json\",\n             */\n            const dotExt = '.json';\n            const dotExtLength = 5;\n            const metaStoneAddrs = filenames\n                .filter(x => {\n                    // some filenames may be adjusted and not the full ibs.\n                    // however, the metastones are never shortened (atow\n                    // 11/2023), so those that don't have the delimiter will be\n                    // stored in ibIsh but they should get filtered out.\n                    const [ibIsh, gibPlusExt] = x.split(IBGIB_DELIMITER);\n                    return !!gibPlusExt?.endsWith(dotExt) && fnFilter(ibIsh);\n                }).map(addrPlusExt => {\n                    // strip the extension\n                    return addrPlusExt.substring(0, addrPlusExt.length - dotExtLength);\n                }).filter(metaStoneAddr => {\n                    // atow (11/2023) I'm not sure what other metastones are\n                    // going to be in this dir, so I'm saying it has to\n                    // explicitly contain the tjpGib.\n                    return isMetaStone({ addr: metaStoneAddr }) && metaStoneAddr.includes(tjpGib);\n                });\n\n            if (logalot) { console.log(`${lc} filtered/mapped filenames -> metaStoneAddrs: ${metaStoneAddrs} (I: d0396296e7de1167d226f3c84a283424)`); }\n\n            // do some basic validation\n            // throw (which could cripple in the future...), or silent fail\n            // (which could lead to corrupt data)...  hmm...going to throw for\n            // now.\n            for (let i = 0; i < metaStoneAddrs.length; i++) {\n                const metaStoneAddr = metaStoneAddrs[i];\n                let basicErrors = validateIbGibAddr({ addr: metaStoneAddr });\n                if ((basicErrors ?? []).length > 0) {\n                    throw new Error(`(UNEXPECTED) invalid metastone found? metaStoneAddr (${metaStoneAddr}) had basic validation errors: ${basicErrors!.join('|')} (E: c41e8797d56833c55e32d5b4c8f79524)`);\n                }\n                const { ib } = getIbAndGib({ ibGibAddr: metaStoneAddr });\n                let metaStoneErrors = validateCommonMetaStoneIb({ ib });\n                if (metaStoneErrors.length > 0) {\n                    throw new Error(`(UNEXPECTED) metaStoneIb had validation errors? metaStoneErrors: ${metaStoneErrors.join('|')} (E: 28ab913c2d7376843e7d94584fc94324)`);\n                }\n            }\n\n            // all good, return 'em!\n            if (logalot) { console.log(`${lc} returning metaStoneAddrs: ${metaStoneAddrs} (I: 491d7c31691e4938eb9d087f5854fa24)`); }\n            return metaStoneAddrs;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n}\nexport async function convertData({\n    data,\n    encoding,\n}: {\n    data: string,\n    encoding: any,\n}): Promise<any> {\n    const lc = `[${convertData.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 9de827dcf4715d3f1a81e6dd9ee9ff24)`); }\n\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n", "import { extractErrorMsg, getTimestamp, getUUID, pretty } from \"@ibgib/helper-gib/dist/helpers/utils-helper.mjs\";\nimport { getGib, isPrimitive } from \"@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs\";\nimport { GIB } from \"@ibgib/ts-gib/dist/V1/constants.mjs\";\nimport { IbGib_V1 } from \"@ibgib/ts-gib/dist/V1/types.mjs\";\nimport { IbGibAddr } from \"@ibgib/ts-gib/dist/types.mjs\";\nimport { getIbAndGib } from \"@ibgib/ts-gib/dist/helper.mjs\";\nimport { SyncSagaInfo, SyncStatusIbGib } from \"@ibgib/core-gib/dist/witness/space/outer-space/outer-space-types.mjs\";\nimport { SubscriptionWitness } from \"@ibgib/core-gib/dist/common/pubsub/subscription/subscription-types.mjs\";\nimport { fnObs } from \"@ibgib/core-gib/dist/common/pubsub/observer/observer-helper.mjs\";\nimport { ErrorIbGib_V1 } from \"@ibgib/core-gib/dist/common/error/error-types.mjs\";\nimport { IbGibSpaceAny } from \"@ibgib/core-gib/dist/witness/space/space-base-v1.mjs\";\nimport {\n    DtoToSpaceFunction, LocalSpaceFactoryFunction, MetaspaceService,\n} from \"@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs\";\nimport { isSpaceIb, spaceNameIsValid } from \"@ibgib/core-gib/dist/witness/space/space-helper.mjs\";\nimport {\n    IBGIB_BASE_DIR, IBGIB_BASE_SUBPATH, IBGIB_BIN_SUBPATH,\n    IBGIB_DNA_SUBPATH, IBGIB_ENCODING, IBGIB_IBGIBS_SUBPATH, IBGIB_META_SUBPATH\n} from \"@ibgib/core-gib/dist/witness/space/filesystem-space/filesystem-constants.mjs\";\nimport {\n    DEFAULT_LOCAL_SPACE_DESCRIPTION, DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS,\n    PERSIST_OPTS_AND_RESULTS_IBGIBS_DEFAULT\n} from \"@ibgib/core-gib/dist/witness/space/space-constants.mjs\";\nimport { toDto } from \"@ibgib/core-gib/dist/common/other/ibgib-helper.mjs\";\n\nimport { GLOBAL_LOG_A_LOT } from \"../../../../constants.mjs\";\nimport { getFnPrompt } from \"../../../../common/prompt-functions.web.mjs\";\nimport { WebFilesystemSpace_V1 } from \"../../web-filesystem-space/web-filesystem-space-v1.mjs\";\nimport { WebFilesystemSpaceData_V1, WebFilesystemSpaceRel8ns_V1 } from \"../../web-filesystem-space/web-filesystem-space-types.mjs\";\n\n/**\n * used in verbose logging (across all ibgib libs atow)\n */\nconst logalot = GLOBAL_LOG_A_LOT;\n\nexport const fnCreateNewLocalSpace: LocalSpaceFactoryFunction = async ({\n    allowCancel,\n    spaceName,\n    logalot,\n}) => {\n    const lc = `[fnCreateNewLocalSpace]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: b05e12810c1d32269b0fa7e965ccfd24)`); }\n\n        if (spaceName && !spaceNameIsValid(spaceName)) {\n            throw new Error(`spaceName (${spaceName}) is invalid.  (E: c54aa952ee34102befe5f47681cdf624)`);\n            // throw because this is used in RCLI and automated testing...\n        }\n        if (!spaceName) {\n\n            const promptName: () => Promise<void> = async () => {\n                const fnPrompt = getFnPrompt();\n                const resName = await fnPrompt({\n                    title: 'greetings program', msg: `this website does not use cookies. it's driven by ibgib's innovative protocol, and all of YOUR data is stored in a \"local space\" on YOUR device. in browsers, this means in IndexedDB.\n\nso give your local space a name like 'phone_alice' or 'web_bob_foo', or leave blank to get a random name. then click ok.\n`\n                });\n\n                if (resName === '' && !allowCancel) {\n                    spaceName = 'space_' + (await getUUID()).slice(0, 10);\n                } else {\n                    if (resName && spaceNameIsValid(resName)) {\n                        spaceName = resName;\n                    }\n                }\n            };\n\n            // ...prompt for name\n            await promptName();\n\n            if (!spaceName) { return undefined; /* <<<< returns early */ }\n        }\n\n        // ...create in memory with defaults\n        const now = new Date();\n        const timestamp = getTimestamp(now);\n        const timestampMs = now.getMilliseconds();\n        const newLocalSpace = new WebFilesystemSpace_V1(/*initialData*/ {\n            version: '1',\n            uuid: await getUUID(),\n            isTjp: true,\n            timestamp,\n            timestampMs,\n            name: spaceName,\n            baseDir: IBGIB_BASE_DIR,\n            spaceSubPath: spaceName,\n            baseSubPath: IBGIB_BASE_SUBPATH,\n            binSubPath: IBGIB_BIN_SUBPATH,\n            dnaSubPath: IBGIB_DNA_SUBPATH,\n            ibgibsSubPath: IBGIB_IBGIBS_SUBPATH,\n            metaSubPath: IBGIB_META_SUBPATH,\n            encoding: IBGIB_ENCODING,\n            persistOptsAndResultIbGibs: PERSIST_OPTS_AND_RESULTS_IBGIBS_DEFAULT,\n            validateIbGibAddrsMatchIbGibs: true,\n            trace: false,\n            description: DEFAULT_LOCAL_SPACE_DESCRIPTION,\n            allowPrimitiveArgs: false,\n            catchAllErrors: true,\n            longPollingIntervalMs: DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS,\n        } as WebFilesystemSpaceData_V1, /*initialRel8ns*/ undefined);\n        if (logalot) { console.log(`${lc} localSpace.ib: ${newLocalSpace.ib} (I: f57802654c5be84eb96d36d477425924)`); }\n        if (logalot) { console.log(`${lc} localSpace.gib: ${newLocalSpace.gib} (before sha256v1) (I: 4171271b7c1484e90205824a31067924)`); }\n        if (logalot) { console.log(`${lc} localSpace.data: ${pretty(newLocalSpace.data || 'falsy')} (I: 01221a1d7f6f19accf05b17534e3e624)`); }\n        if (logalot) { console.log(`${lc} localSpace.rel8ns: ${pretty(newLocalSpace.rel8ns || 'falsy')} (I: 750a7ec2b25b5d344dea900cf14ca524)`); }\n\n        // trying out with tjp, can't remember why didn't have it except for\n        // backwards compatability which i'm no longer shooting for (will be\n        // able to project old spaces to new ones i believe)\n        // newLocalSpace.gib = await getGib({ ibGib: newLocalSpace, hasTjp: false });\n        newLocalSpace.gib = await getGib({ ibGib: toDto({ ibGib: newLocalSpace }), hasTjp: true });\n\n        if (newLocalSpace.gib === GIB) { throw new Error(`localSpace.gib not updated correctly. (E: 277f8305ec3fd8dd4b023616c1fa0624)`); }\n        if (logalot) { console.log(`${lc} localSpace.gib: ${newLocalSpace.gib} (after sha256v1) (I: d3ab464fdb4500d95a50bf1e7c036524)`); }\n\n        return newLocalSpace as IbGibSpaceAny;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport const fnDtoToSpace_webFilesystem: DtoToSpaceFunction = (spaceDto) => {\n    return Promise.resolve(\n        WebFilesystemSpace_V1.createFromDto(spaceDto as IbGib_V1<WebFilesystemSpaceData_V1, WebFilesystemSpaceRel8ns_V1>)\n    );\n}\n\n/**\n * wrapper around metaspace.syncIbGibs\n * @param param0\n * @returns\n */\nexport async function doSync_awaitAllSagas({\n    addr,\n    metaspace,\n    localSpace,\n    syncSpaces,\n    sagaReporter,\n    verbose,\n}: {\n    /**\n     * the addr whose live dependency graph is going to be built and synced.\n     */\n    addr: IbGibAddr,\n    /**\n     * it's meta yo\n     */\n    metaspace: MetaspaceService,\n    /**\n     * the space which contains the syncSpace (proxy outer space).\n     */\n    localSpace: IbGibSpaceAny,\n    /**\n     * sync space witnesses (not just ibgib dtos)\n     */\n    syncSpaces: IbGibSpaceAny[],\n    sagaReporter: (msg: string, saga: SyncSagaInfo | null) => Promise<void>,\n    /**\n     * If true, will report more in {@link sagaReporter}\n     */\n    verbose?: boolean,\n}): Promise<SyncSagaInfo[] | undefined> {\n    const lc = `[${doSync_awaitAllSagas.name}]`;\n    try {\n        if (logalot || verbose) { console.log(`${lc} starting... (I: 78bf9e5bea88d9b3827bb991eeedc524)`); }\n        const { ib, gib } = getIbAndGib({ ibGibAddr: addr });\n\n        if (isPrimitive({ gib })) { throw new Error(`can't sync primitive ibgib (${addr}) (E: 915b331b00118b5f69e630ef5d2b8d24)`); }\n        if (isSpaceIb({ ib })) { throw new Error(`can't sync entire space ibgib (${addr}) (E: bd1b991e35a683df5a79c379c21d3924)`); }\n        if (syncSpaces.length === 0) { throw new Error(`syncSpaces required (E: 671b4f4adc6e009ed304419d662b2d24)`); }\n        if (syncSpaces.some(x => !x.witness)) { throw new Error(`(UNEXPECTED) syncSpaces.some(x => !x.witness)? sync spaces should all be witnesses (and have a witness function). these are not supposed to be just dtos (with ib, gib, data, rel8ns props). (E: 879c32b69856218f7eeafb89db491524)`); }\n\n        if (verbose) { await sagaReporter('getDependencyGraph starting... (I: 35cb6f89e87d7300b3be4088b4176a24)', null); }\n\n        const dependencyGraph = await metaspace.getDependencyGraph({\n            space: localSpace,\n            ibGibAddr: addr,\n            live: true,\n            msBetweenRetries: 1_000,\n        });\n\n        if (verbose) {\n            await sagaReporter('getDependencyGraph complete. (I: ec9aadd538ac3a61da3873c53852d324)', null);\n            await sagaReporter('syncIbGibs spinning off... (I: a15ddf897f8797848b350ad6a2067b24)', null);\n        }\n\n        const sagas = await metaspace.syncIbGibs({\n            dependencyGraphIbGibs: Object.values(dependencyGraph),\n            syncSpaceIbGibs: syncSpaces,\n            localSpace,\n        }) ?? [];\n        if (sagas.length === 0) { throw new Error(`(UNEXPECTED) metaspace.syncIbGibs returned undefined (no sagas)? (E: 4d7faeb9ed95fe4b162f2a1377928b24)`); }\n        if (verbose) {\n            await sagaReporter('syncIbGibs spin off complete. these are not yet done, it/they are just spun off and going. (I: a958a6b706c9b66933cb82ea7bbfcc24)', sagas.at(0) ?? null);\n        }\n\n        let sagaCount = sagas.length;\n        let sagaErrorCounter = 0;\n        /**\n         * using this during debugging...\n         */\n        const sagaErrorMsgs: string[] = [];\n        let sagaCompleteOrErrorCounter = 0;\n        let allSagasCompletePromise = new Promise<void>((resolve, reject) => {\n            const interval = setInterval(async () => {\n                if (sagaCompleteOrErrorCounter === sagaCount) {\n                    if (sagaErrorCounter > 0) {\n                        reject(`saga had errors: ${sagaErrorMsgs.join('|')} (E: c039232a158cd69669e233a84f9be924)`);\n                    }\n                    clearInterval(interval);\n                    resolve();\n                }\n            }, 500);\n        });\n\n        const fnIncCompleteOrError = async (saga: SyncSagaInfo) => {\n            const lcInner = `${lc}[fnIncCompleteOrError]`;\n            if (logalot || verbose) { console.log(`${lcInner} starting... (I: 1c41e7aaab13ecdf4f3608533f38b324)`); }\n            try {\n                sagaCompleteOrErrorCounter++;\n                let updateText: string;\n                if (sagaCompleteOrErrorCounter < sagaCount) {\n                    updateText = `saga (${saga.sagaId}) complete or errored. ONLY SOME (${sagaCompleteOrErrorCounter}/${sagaCount}) have completed or errored. still more to go...`;\n                } else if (sagaCompleteOrErrorCounter === sagaCount) {\n                    updateText = `saga (${saga.sagaId}) complete or errored. ALL ${sagaCount} sync sagas COMPLETE OR ERRORED.`;\n                } else {\n                    debugger; // unexpected error state. sagaCompleteOrErrorCounter > sagaCount\n                    updateText = `uhh, there is an error here. we have incremented sagaCompleteOrErrorCounter (${sagaCompleteOrErrorCounter}) to be greater than sagaCount (${sagaCount}) (E: b8e934cfce188f40a93cb90a462c7c24)`;\n                }\n                if (logalot || verbose) {\n                    console.log(`${lc} ${updateText} (I: 519a895d1a7ddc44cf8b4532cf3b6524)`);\n                    await sagaReporter(`${lcInner} ${updateText}`, saga);\n                }\n            } catch (error) {\n                console.error(`${lc} ${extractErrorMsg(error)}`);\n                throw error;\n            } finally {\n                if (logalot || verbose) { console.log(`${lc}[fnIncCompleteOrError] complete. (I: f2be67aa53e59ab2e5a7f89b26b4df24)`); }\n            }\n        };\n\n        for (let i = 0; i < sagas.length; i++) {\n            const saga = sagas[i];\n            let subscription: SubscriptionWitness = await saga.syncStatus$.subscribe(fnObs({\n                next: async (status: SyncStatusIbGib) => {\n                    if (logalot || verbose) {\n                        console.log(`${lc} console.dir(status)... (I: e786c4449ebf14be5b2d63a61d22c824)`);\n                        console.dir(status);\n                    } else {\n                        let statusCode = status.data?.statusCode;\n                        if (statusCode === \"already_synced\") {\n                            process.stdout.write('.');\n                        } else {\n                            console.log(statusCode);\n                        }\n                    }\n                },\n                complete: async () => {\n                    if (logalot || verbose) {\n                        console.log(`${lc}[saga complete] triggered for saga (${saga.spaceId}, ${saga.multiSpaceOpId}). (I: 999536aeb555ac9eaac88c98aee71224)`);\n                    }\n                    await fnIncCompleteOrError(saga);\n                    await subscription.unsubscribe();\n                },\n                error: async (err: string | Error | ErrorIbGib_V1) => {\n                    const errorMsg = extractErrorMsg(err);\n                    sagaErrorMsgs.push(errorMsg);\n                    if (errorMsg.includes('EAI_AGAIN')) {\n                        console.error(`this error may be because of no internet connection. ${errorMsg}`)\n                    }\n                    console.error(`${lc}[error] err: ${errorMsg} (E: 90b11d262194884ae8320ccbf7252124)`);\n                    sagaErrorCounter++;\n                    await fnIncCompleteOrError(saga);\n                    await subscription.unsubscribe();\n                    // sagaCompleteOrErrorCounter++;\n                }\n            }));\n        }\n        await allSagasCompletePromise;\n        return sagas;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot || verbose) { console.log(`${lc} complete.`); }\n    }\n}\n", "/**\n * @module metaspace-webspace driven by a web indexeddb storage substrate\n *\n * a metaspace is a space of spaces. it adds/removes spaces and does\n * inter-spatial composition related things. it's similar to what people think\n * of in terms of a node in a p2p network.\n */\n\nimport { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';\nimport { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';\nimport { IbGibCacheService } from '@ibgib/core-gib/dist/common/cache/cache-types.mjs';\nimport { MetaspaceBase } from '@ibgib/core-gib/dist/witness/space/metaspace/metaspace-base.mjs';\nimport { MetaspaceFactory, MetaspaceInitializeOptions } from '@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs';\n\nimport { GLOBAL_LOG_A_LOT, GLOBAL_TIMER_NAME, } from '../../../../constants.mjs';\nimport { fnCreateNewLocalSpace, fnDtoToSpace_webFilesystem } from './metaspace-webspace-helper.mjs';\nimport { WebFilesystemSpace_V1 } from '../../web-filesystem-space/web-filesystem-space-v1.mjs';\n// import { storageCreateStoreIfNotExist, initializeStorage, storageDBExists, } from '../../../../helpers.web.mjs';\nimport { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';\nimport { storageCreateStoreIfNotExist } from '../../../../storage/storage-helpers.web.mjs';\nimport { SpaceId } from '@ibgib/core-gib/dist/witness/space/space-types.mjs';\nimport { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';\nimport { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';\nimport { commandifyAnonFn } from '../../../../api/commands/command-helpers.mjs';\nimport { execInSpaceWithLocking } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';\nimport { SpecialIbGibType } from '@ibgib/core-gib/dist/common/other/other-types.mjs';\nimport { getGlobalDbName } from '../../../../helpers.web.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT;\n\nconst NAIVE_SPACE_CACHE: Map<IbGibAddr, IbGibSpaceAny> = new Map();\nconst ZERO_SPACE_CACHE_ADDR = 'zero_space^gib';\nconst STORES_CONFIRMED: Set<string> = new Set();\n\ninterface TempCacheEntry {\n    /**\n     * Password to the user's password.\n     */\n    tempMetaPassword: string;\n    /**\n     * Encrypted user password\n     */\n    encryptedPassword: string;\n    /**\n     * salt used in cached encryption.\n     */\n    salt: string;\n}\n\n\n/**\n * All-purpose mega service (todo: which we'll need to break up!) to interact\n * with ibgibs at the app/device level.\n *\n * This works with the local app user space.\n *\n * ## regarding special ibgibs\n *\n * Special ibgibs' behaviors are what hold in other apps configuration data.\n * Of course the difference is that most special ibgibs can leverage the \"on-chain\"\n * functionality of \"regular\" ibgibs.\n *\n * There are a couple meta ibgibs (which I also call \"special\"):\n *   * roots^gib\n *     * tracks other special root^gib ibgibs, which are like local app-level indexes.\n *   * tags^gib\n *     * tracks other special tag^gib ibgibs, which you can apply to any ibgib\n *   * latest^gib\n *     * tracks mappings between tjp -> latest ib^gib address\n *     * ephemeral (deletes past rel8ns and past ibGib frames)\n *   * ...\n *\n * ## regarding latest ibgibs\n *\n * The tjp (temporal junction point) defines atow the beginning of an ibGib\n * timeline.  it's like the birthday for an ibGib. (Or you can think if it as\n * the id for the stream of ibgib frames in a given timeline.)\n *\n * The latest ibGib in that timeline is also special, because it's often what\n * you want to work with.\n *\n * So ideally, when an ibgib, A, has a tjp A1, and it is updated to A2, A3, An\n * via `mut8` and/or `rel8` transforms, that ibgib creates a single timeline.\n * This service attempts to track the relationship between that starting tjp\n * address and its corresponding latest frame in that timeline, i.e., A1 -> An.\n *\n * ### mapping persistence implementation details\n *\n * The latest ibGib service is backed by a special ibgib that maintains the\n * mapping index.  It does this by rel8-ing that special backing ibgib via the\n * tjp pointer, e.g. [special latest ibgib^XXX000].rel8ns[A^TJP123] ===\n * [A^N12345] . It does this via the ib^gib content address pointer, so this\n * becomes a mapping from A^TJP123 to A^N12345.\n *\n * This backing ibGib is special (even for special ibGibs) in that:\n *   * it does not relate itself with the current root of the application\n *   * it does not maintain references to its past (i.e. rel8ns['past'] === [])\n *   * it DELETES its previous incarnation from the files service\n *\n * In other words, this service is meant to be as ephemeral as possible. I am\n * keeping it as an ibGib and not some other data format (like straight in\n * storage/some other db) because I've found this is often useful and what I end\n * up doing anyway to leverage other ibgib behavior. For example, in the future\n * it may be good to take snapshots, which is a simple copy operation of the\n * file persistence.\n *\n * ### current naive implementation notes\n *\n * questions:\n *   * What do we want to do if we can't locate an ibGib record?\n *   * How/when do we want to alert the user/our own code that we've found\n *     multiple timelines for an ibGib with a tjp (usually a thing we want to\n *     avoid)?\n *   * Who do we want to notify when new ibGibs arrive?\n *   * How often do we want to check external sources for latest?\n *   * When do we get to merging ibGib timelines?\n *\n * This is behavior that is somewhat taken care of, e.g. in git, with the HEAD\n * pointer for a repo.  But we're talking about here basically as a metarepo or\n * \"repo of repos\", and unlike git, we don't want our HEAD metadata living \"off\n * chain\" (outside of the DLT itself that it's modifying).  So eventually, what\n * we want is just like what we want with ALL ibGibs: perspective. From \"the\n * app\"'s perspective, the latest is mapped. But really, apps can't view slices\n * of ibGib graphs in all sorts of interesting ways and still be productive &\n * beneficial to the ecosystem as a whole.\n */\nexport class Metaspace_Webspace extends MetaspaceBase {\n\n    // we won't get an object back, only a DTO ibGib essentially\n    protected lc: string = `[${Metaspace_Webspace.name}]`;\n\n    get zeroSpace(): IbGibSpaceAny {\n        const lc = `[${this.lc}][get zeroSpace]`;\n        if (NAIVE_SPACE_CACHE.has(ZERO_SPACE_CACHE_ADDR)) {\n            return NAIVE_SPACE_CACHE.get(ZERO_SPACE_CACHE_ADDR)!;\n        } else if (this.metaspaceFactory.fnZeroSpaceFactory) {\n            const zeroSpace = this.metaspaceFactory.fnZeroSpaceFactory();\n            NAIVE_SPACE_CACHE.set(ZERO_SPACE_CACHE_ADDR, zeroSpace);\n            return zeroSpace;\n        } else {\n            throw new Error(`${lc} (UNEXPECTED) this.metaspaceFactory.fnZeroSpaceFactory falsy. not initialized? (E: 9e6c6954dacd868b18c9f34a71e63523)`);\n        }\n    }\n\n    constructor(\n        // public modalController: ModalController,\n        // public alertController: AlertController,\n        protected cacheSvc: IbGibCacheService | undefined,\n        // private latestCacheSvc: IonicStorageLatestIbgibCacheService,\n    ) {\n        super(cacheSvc);\n        const lc = `${this.lc}[ctor]`;\n        if (logalot) {\n            console.log(`${lc}${GLOBAL_TIMER_NAME}`);\n            console.timeLog(GLOBAL_TIMER_NAME);\n            console.log(`${lc} created. (I: 5690dc2ebf774df3a442bd463dee7455)`);\n        }\n\n    }\n\n    protected async initializeMetaspaceFactory({ metaspaceFactory }: {\n        metaspaceFactory: MetaspaceFactory,\n    }): Promise<void> {\n        const lc = `[${this.initializeMetaspaceFactory.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 5a29670439ac47634dcdfe25225c8223)`); }\n\n            await super.initializeMetaspaceFactory({ metaspaceFactory });\n\n            metaspaceFactory.fnDefaultLocalSpaceFactory ??= async (opts) => {\n                const createdSpace = await fnCreateNewLocalSpace(opts);\n                if (!createdSpace) { throw new Error(`(UNEXPECTED) createdSpace undefined? (E: 21258175efdd1a9cb1f9fc8ab59e0324)`); }\n                if (!createdSpace.data?.uuid) { throw new Error(`(UNEXPECTED) createdSpace.data.uuid undefined? (E: 0a6c44c078d9e21e92f703adbc995c24)`); }\n\n                // ensure the local space exists in storage (db & store)\n                const storeNameForSpace = createdSpace.data.uuid;\n                await storageCreateStoreIfNotExist({\n                    dbName: getGlobalDbName(),\n                    storeName: storeNameForSpace,\n                    logalot,\n                });\n\n                // cache newly created space\n                const spaceAddr = getIbGibAddr({ ibGib: createdSpace });\n                NAIVE_SPACE_CACHE.set(spaceAddr, createdSpace);\n\n                // return it\n                return createdSpace;\n            };\n            metaspaceFactory.fnDtoToSpace ??= async (spaceDto) => {\n                // first ensure that the store exists in IndexedDB\n                const storeNameForSpace = spaceDto.data?.uuid;\n                if (!storeNameForSpace) { throw new Error(`spaceDto.data?.uuid falsy? (E: b73bded9ebede92b8ef53b8d05dca225)`); }\n                if (!STORES_CONFIRMED.has(storeNameForSpace)) {\n                    await storageCreateStoreIfNotExist({\n                        dbName: getGlobalDbName(),\n                        storeName: storeNameForSpace,\n                        logalot,\n                    });\n                    STORES_CONFIRMED.add(storeNameForSpace);\n                }\n\n                // get the space from cache if available, else create it\n\n                const spaceAddr = getIbGibAddr({ ibGib: spaceDto });\n                let resSpace = NAIVE_SPACE_CACHE.get(spaceAddr);\n                resSpace = undefined; // testing bug\n                if (!resSpace) {\n                    resSpace = await fnDtoToSpace_webFilesystem(spaceDto);\n                    if (!resSpace.data?.uuid) { throw new Error(`(UNEXPECTED) resCreateNewSpace.data.uuid undefined? (E: f1e0e75f02b607b349b4102a8c8f7724)`); }\n                    NAIVE_SPACE_CACHE.set(spaceAddr, resSpace);\n                }\n                return resSpace;\n            };\n\n            this.metaspaceFactory.fnZeroSpaceFactory ??= () => {\n                // default to web space\n                const zeroSpace = new WebFilesystemSpace_V1(/*initialData*/ undefined, /*initialRel8ns*/ undefined);\n                zeroSpace.gib = 'gib';\n                return zeroSpace;\n            }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    override async initialize(args: MetaspaceInitializeOptions): Promise<void> {\n        const lc = `${this.lc}[${this.initialize.name}]`;\n\n        // const {\n        //   spaceName,\n        //   metaspaceFactory,\n        //   getFnAlert, getFnPrompt, getFnPromptPassword,\n        // } = args;\n        await this.initializeZeroSpace();\n        await super.initialize(args);\n    }\n\n    async initializeZeroSpace(): Promise<void> {\n        const lc = `[${this.initializeZeroSpace.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: a3364e9601c70c8163e67868e5d67723)`); }\n\n            // make sure the db and store exist for the zero space.\n\n            // I'll reuse storagePut to ensure the store exists for the zero space?\n\n            // is this initilizeStorage necessary with the initialization as\n            // referenced in the proceeding code with storageCreateStoreIfNotExist?\n\n            // await initializeStorage({\n            //   dbName: BLANK_GIB_DB_NAME,\n            //   storeName: ZERO_SPACE_ID,\n            //   logalot,\n            // });\n\n            if (logalot) { console.log(`${lc} we are assuming zero space storage is initialized in indexed db. atow (03/2025), this is done in initBlankGibStorage in index.mts (I: cb1dd69b21efc2fc366956349e865125)`); }\n            // this is now done in initBlankGibStorage in index.mts\n            // await storageCreateStoreIfNotExist({\n            //   dbName: BLANK_GIB_DB_NAME,\n            //   storeName: ZERO_SPACE_ID,\n            //   logalot,\n            // });\n\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * I'm overriding this to troubleshoot figuring out why the space is\n     * becoming invalid.\n     */\n    override async getLocalUserSpace({ lock, localSpaceId, }: { lock?: boolean; localSpaceId?: SpaceId; }): Promise<IbGibSpaceAny | undefined> {\n        const lc = `${this.lc}[${this.getLocalUserSpace.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: e68ae7f617e4a1af026ab1ac1c52f425)`); }\n            const space = await super.getLocalUserSpace({ lock, localSpaceId });\n            if (!space) {\n                console.error(`(UNEXPECTED) local user space falsy? NOTE: This error is just logged, not thrown as I don't know if this is always improper behavior. (E: 3c7cac40d11b26c3fd95183d06ffc225)`);\n                return space; /* <<<< returns early */\n            }\n\n            const errors = await validateIbGibIntrinsically({ ibGib: space }) ?? [];\n            if (errors.length > 0) {\n                // debugger; // space is invalid intrinsically? I'm putting this here to try to troubleshoot how this is coming to be.\n                console.error(`(UNEXPECTED) local user space is invalid intrinsically? when did this happen? (E: df5c8e62c204a6972e364fa33d9b7725)`);\n            }\n\n            return space;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * overriding to try to execute serially via commanding architecture.\n     *\n     * just wraps super call with {@link commandifyAnonFn}.\n     *\n     * @see {@link commandifyAnonFn}\n     */\n    override async rel8ToCurrentRoot(opts: { ibGib: IbGib_V1; linked?: boolean; rel8nName?: string; space?: IbGibSpaceAny; }): Promise<void> {\n        const lc = `${this.lc}[${this.rel8ToCurrentRoot.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 0f999532d51b1ad2084ed30670297125)`); }\n\n            // const cmd = commandifyAnonFn<any>({\n            //     fn: () => {\n            const space = opts.space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`(UNEXPECTED) space falsy and couldn't get default local user space? (E: e8b63af1b0fb692c4761fe9627eaf525)`); }\n            await execInSpaceWithLocking({\n                fn: async () => {\n                    const lc = `${this.lc}[${this.rel8ToCurrentRoot.name}]`;\n                    try {\n                        if (logalot) { console.log(`${lc} starting... (I: 5444c70bd93b13b59ef9cd06ee72d825)`); }\n\n                        return super.rel8ToCurrentRoot(opts);\n\n                    } catch (error) {\n                        console.error(`${lc} ${extractErrorMsg(error)}`);\n                        throw error;\n                    } finally {\n                        if (logalot) { console.log(`${lc} complete.`); }\n                    }\n                },\n                scope: lc,\n                secondsValid: 60,\n                maxDelayMs: 100,\n                maxLockAttempts: 600, // 60 seconds worth\n                space,\n                callerInstanceId: this.instanceId,\n            });\n\n            // debugger; // before viacmd?\n            // const result = cmd.fnViaCmd();\n            // debugger; // after viacmd?\n            // return result;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n\n    }\n\n    override async rel8ToSpecialIbGib(opts: {\n        type: SpecialIbGibType;\n        rel8nName: string;\n        ibGibsToRel8?: IbGib_V1[];\n        ibGibsToUnRel8?: IbGib_V1[];\n        linked?: boolean;\n        severPast?: boolean;\n        deletePreviousSpecialIbGib?: boolean;\n        space?: IbGibSpaceAny;\n    }): Promise<IbGibAddr> {\n        const lc = `${this.lc}[${this.rel8ToSpecialIbGib.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 906d2e553f163405f3238f141ed6fb25)`); }\n            // const { type, rel8nName, ibGibsToRel8, ibGibsToUnRel8, linked, severPast, deletePreviousSpecialIbGib, space, } = opts;\n\n            const space = opts.space ?? await this.getLocalUserSpace({});\n            if (!space) { throw new Error(`(UNEXPECTED) space falsy and couldn't get default local user space? (E: 3c587503d08aa8b8cda25bb7064bf125)`); }\n            const result = await execInSpaceWithLocking({\n                fn: async () => {\n                    const lc = `${this.lc}[${this.rel8ToCurrentRoot.name}]`;\n                    try {\n                        if (logalot) { console.log(`${lc} starting... (I: 3b9f44934d88196bc3d0087cadd23125)`); }\n\n                        return super.rel8ToSpecialIbGib(opts);\n\n                    } catch (error) {\n                        console.error(`${lc} ${extractErrorMsg(error)}`);\n                        throw error;\n                    } finally {\n                        if (logalot) { console.log(`${lc} complete.`); }\n                    }\n                },\n                scope: lc,\n                secondsValid: 60,\n                maxDelayMs: 100,\n                maxLockAttempts: 600, // 60 seconds worth\n                space,\n                callerInstanceId: this.instanceId,\n            });\n\n            return result;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n}\n", "/**\n * @module bootstrap\n *\n * Shared bootstrap entry point for ibgib-based web apps.\n * Collapses the metaspace, globalThis, and shell-init boilerplate.\n */\n\nimport {\n    clone, extractErrorMsg, getTimestamp, getUUID, pickRandom_Letters,\n} from \"@ibgib/helper-gib/dist/helpers/utils-helper.mjs\";\nimport { RCLIArgInfo, RCLIParamInfo } from \"@ibgib/helper-gib/dist/rcli/rcli-types.mjs\";\nimport { buildArgInfos } from \"@ibgib/helper-gib/dist/rcli/rcli-helper.mjs\";\nimport { IbGibAddr, TransformResult } from \"@ibgib/ts-gib/dist/types.mjs\";\nimport { getIbAndGib, getIbGibAddr } from \"@ibgib/ts-gib/dist/helper.mjs\";\nimport { Factory_V1 as factory } from \"@ibgib/ts-gib/dist/V1/factory.mjs\";\nimport { Rel8n } from \"@ibgib/ts-gib/dist/V1/types.mjs\";\nimport { IbGibAppAny, AppBase_V1 } from \"@ibgib/core-gib/dist/witness/app/app-base-v1.mjs\";\nimport { getFromSpace } from \"@ibgib/core-gib/dist/witness/space/space-helper.mjs\";\nimport { createNewApp, getAppIb, getInfoFromAppIb } from \"@ibgib/core-gib/dist/witness/app/app-helper.mjs\";\nimport { MetaspaceService } from \"@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs\";\nimport { IbGibSpaceAny } from \"@ibgib/core-gib/dist/witness/space/space-base-v1.mjs\";\nimport { APP_REL8N_NAME } from '@ibgib/core-gib/dist/witness/app/app-constants.mjs';\nimport { TAG_REL8N_NAME } from \"@ibgib/core-gib/dist/common/tag/tag-constants.mjs\";\nimport { TagIbGib_V1 } from \"@ibgib/core-gib/dist/common/tag/tag-types.mjs\";\nimport { SPACE_NAME_REGEXP } from \"@ibgib/core-gib/dist/witness/space/space-constants.mjs\";\nimport { SpecialIbGibType } from \"@ibgib/core-gib/dist/common/other/other-types.mjs\";\n\nimport { alertUser, promptForSecret, promptForText } from \"../helpers.web.mjs\";\nimport { Metaspace_Webspace } from \"../witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs\";\nimport { LiveProxyIbGib } from \"../witness/live-proxy-ibgib/live-proxy-ibgib-one-file.mjs\";\nimport { storageGet } from \"../storage/storage-helpers.web.mjs\";\nimport { getIbGibGlobalThis_IbGib } from \"../helpers.mjs\";\n\nimport {\n    IbGibAmbientContextConfig,\n    IbGibGlobalThis_IbGibApp,\n    IbGibIdentityContext,\n    RequestCommentData_V1,\n    RequestCommentIbGib_V1,\n} from \"./types.mjs\";\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface TagConfig {\n    text: string;\n    icon: string;\n    description: string;\n}\n\nexport interface BootstrapIbGibAppOptions<TApp extends IbGibAppAny> {\n    /** Application context configuration (IndexedDB names, etc.) */\n    config: IbGibAmbientContextConfig;\n\n    /** Accessor for the application's typed globalThis slot */\n    getGlobalThis: (config?: IbGibAmbientContextConfig) => IbGibGlobalThis_IbGibApp;\n\n    /** The main application witness class */\n    AppClass: new (data?: any, rel8ns?: any) => TApp;\n\n    /**\n     * Default data used when generating the very first version of this app.\n     * Only applied if `fnGetOrCreateApp` is omitted.\n     */\n    defaultAppData: any;\n\n    /**\n     * Optional. Provide an array of parameters the application supports.\n     */\n    paramInfos?: RCLIParamInfo[];\n\n    /**\n     * Optional. Provide initial args for bootstrap.\n     * Defaults to `['--interactive']`.\n     */\n    getOpeningArgs?: () => Promise<string[]>;\n\n    /**\n     * Optional. RCLI argument validation hook.\n     */\n    validateArgInfos?: (opts: { argInfos: RCLIArgInfo[] }) => string | undefined;\n\n    /**\n     * Optional. Hook called before initializing the app, but after metaspace is ready.\n     * Can be used to check environment, space state, etc.\n     */\n    onBeforeCreate?: (metaspace: MetaspaceService, space: IbGibSpaceAny) => Promise<void>;\n\n    /**\n     * Optional. Hook called immediately after the application witness is loaded or created.\n     * A good place to execute migrations before returning the 'ready' app.\n     */\n    onAppLoaded?: (app: TApp, isNew: boolean) => Promise<TApp>;\n\n    /**\n     * Nuclear escape hatch. Provide this to replace the entire app get-or-create flow.\n     * If provided, `onBeforeCreate`, `onAppLoaded`, and `defaultAppData` are ignored.\n     */\n    fnGetOrCreateApp?: (metaspace: MetaspaceService, space: IbGibSpaceAny) => Promise<TApp>;\n\n    /**\n     * Optional. Hook called to initialize identity context (e.g., keystone based auth).\n     */\n    resolveIdentity?: (metaspace: MetaspaceService) => Promise<IbGibIdentityContext | undefined>;\n\n    /**\n     * Optional. The point at which the application logic dictates its readiness to UI components.\n     * Typically this executes `getAppShellSvc().onEngineReady()`.\n     */\n    onReady?: (app: TApp) => void | Promise<void>;\n\n    /**\n     * Tags verified to exist in the global user space at startup.\n     */\n    ensureTags?: TagConfig[];\n\n    /**\n     * The key prefix used for allocating new spaces (e.g. `test_app_space`).\n     */\n    localSpaceNamePrefix?: string;\n\n    /**\n     * Optional hook to register AI agent function tracking and deprecations.\n     */\n    registerAgentFunctionInfos?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Main Flow\n// ---------------------------------------------------------------------------\n\nexport async function bootstrapIbGibApp<TApp extends IbGibAppAny>(\n    opts: BootstrapIbGibAppOptions<TApp>\n): Promise<void> {\n    const lc = `[${bootstrapIbGibApp.name}]`;\n    const logalot = true; // Use a general log flag or derive from config\n\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n\n        const ibGibGlobalThis = opts.getGlobalThis(opts.config);\n\n        if (ibGibGlobalThis.bootstrapStarted) {\n            if (ibGibGlobalThis.bootstrapPromise) {\n                console.warn(`${lc} already bootstrapping \u2014 awaiting that promise.`);\n            } else {\n                throw new Error(`(UNEXPECTED) bootstrapStarted but bootstrapPromise is falsy?`);\n            }\n        } else {\n            ibGibGlobalThis.bootstrapStarted = true;\n            ibGibGlobalThis.bootstrapPromise = new Promise<void>(async (resolve, reject) => {\n                try {\n                    const args = opts.getOpeningArgs\n                        ? await opts.getOpeningArgs()\n                        : ['--interactive'];\n\n                    const paramInfos = opts.paramInfos ?? [{ name: 'interactive', isFlag: true, argTypeName: 'boolean' }];\n\n                    const paramInfosErrors = validateParamInfos({ paramInfos });\n                    if (paramInfosErrors.length > 0) {\n                        throw new Error(`(UNEXPECTED) invalid PARAM_INFOS: ${paramInfosErrors.join('|')}`);\n                    }\n\n                    const argInfos = buildArgInfos({ args, paramInfos, logalot });\n\n                    if (opts.validateArgInfos) {\n                        const validationErrors = opts.validateArgInfos({ argInfos });\n                        if (validationErrors) {\n                            throw new Error(`Arg validation errors: ${validationErrors}`);\n                        }\n                    }\n\n                    await execFromArgs({ opts, args, argInfos, logalot });\n                    resolve();\n                } catch (error) {\n                    reject(error);\n                }\n            });\n        }\n\n        await ibGibGlobalThis.bootstrapPromise;\n\n        // Execute onReady securely outside the promise resolution to prevent deadlock\n        // when getComponentInstance is used by shell service.\n        if (opts.onReady) {\n\n            // Re-fetch the loaded app wrapper dynamically\n            const getApp = () => ((ibGibGlobalThis as any).appInstance as TApp) || null;\n            await opts.onReady(getApp());\n        }\n\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`\\n${lc} complete.`); }\n    }\n}\n\nasync function execFromArgs<TApp extends IbGibAppAny>({\n    opts, args, argInfos, logalot,\n}: {\n    opts: BootstrapIbGibAppOptions<TApp>,\n    args: string[],\n    argInfos: RCLIArgInfo[],\n    logalot: boolean\n}): Promise<void> {\n    const lc = `[${execFromArgs.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n\n        const metaspace = await initMetaspace({ opts, logalot });\n\n        const ibgibGlobalThis_core = getIbGibGlobalThis_IbGib();\n        ibgibGlobalThis_core.metaspace = metaspace;\n\n        const ibgibGlobalThis = opts.getGlobalThis(opts.config);\n        ibgibGlobalThis.metaspace = metaspace;\n\n        if (opts.ensureTags) {\n            await ensureTagsExist({ metaspace, tags: opts.ensureTags, logalot });\n        }\n\n        if (opts.registerAgentFunctionInfos) {\n            opts.registerAgentFunctionInfos();\n        }\n\n        const resRequestCommentIbGib = await createRequestCommentIbGib_Common({\n            args, interpretedArgInfos: argInfos,\n        });\n\n        await metaspace.persistTransformResult({ resTransform: resRequestCommentIbGib });\n        ibgibGlobalThis.initialCommentIbGib = resRequestCommentIbGib.newIbGib;\n\n        const proxy = new LiveProxyIbGib();\n        await proxy.initialized;\n        proxy.setWrappedIbGib({ ibGib: resRequestCommentIbGib.newIbGib });\n        ibgibGlobalThis.initialCommentIbGibProxy = proxy;\n\n        if (opts.resolveIdentity) {\n            ibgibGlobalThis.identity = await opts.resolveIdentity(metaspace);\n        }\n\n        await execInteractive({ opts, resRequestCommentIbGib, metaspace, logalot });\n\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`\\n${lc} complete.`); }\n    }\n}\n\nasync function initMetaspace<TApp extends IbGibAppAny>({\n    opts, logalot\n}: {\n    opts: BootstrapIbGibAppOptions<TApp>,\n    logalot: boolean\n}): Promise<MetaspaceService> {\n    const lc = `[${initMetaspace.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n\n        let metaspace = new Metaspace_Webspace(/*cacheSvc*/undefined);\n\n        const localSpaceNameKey = opts.localSpaceNamePrefix\n            ? `${opts.localSpaceNamePrefix}_local_space_name`\n            : `local_space_name`;\n\n        const existingLocalSpaceName = await storageGet({\n            dbName: opts.config.dbName,\n            storeName: opts.config.storeName,\n            key: localSpaceNameKey,\n        });\n\n        const prefix = opts.localSpaceNamePrefix ?? 'app_space';\n        const spaceName = existingLocalSpaceName\n            ? undefined\n            : await generateLocalSpaceName(prefix);\n\n        await metaspace.initialize({\n            spaceName,\n            metaspaceFactory: undefined,\n            getFnAlert: () => ({ title, msg }) => alertUser({ title, msg }),\n            getFnPrompt: () => ({ title, msg }) => promptForText({ title, msg, confirm: false }),\n            getFnPromptPassword: () => () => promptForSecret({ confirm: true }),\n        });\n\n        return metaspace;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nasync function generateLocalSpaceName(prefix: string): Promise<string> {\n    const name = prefix + '_' + pickRandom_Letters({ count: 12 });\n    if (!SPACE_NAME_REGEXP.test(name)) {\n        throw new Error(`(UNEXPECTED) generated space name (${name}) failed regexp`);\n    }\n    return name;\n}\n\nasync function execInteractive<TApp extends IbGibAppAny>({\n    opts, resRequestCommentIbGib, metaspace, logalot\n}: {\n    opts: BootstrapIbGibAppOptions<TApp>,\n    resRequestCommentIbGib: TransformResult<RequestCommentIbGib_V1>,\n    metaspace: MetaspaceService,\n    logalot: boolean\n}): Promise<void> {\n    const lc = `[${execInteractive.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n\n        const localUserSpace = await metaspace.getLocalUserSpace({ lock: false });\n        if (!localUserSpace) {\n            throw new Error(`(UNEXPECTED) localUserSpace falsy?`);\n        }\n\n        const app = opts.fnGetOrCreateApp\n            ? await opts.fnGetOrCreateApp(metaspace, localUserSpace)\n            : await defaultGetOrCreateApp({\n                AppClass: opts.AppClass,\n                defaultAppData: opts.defaultAppData,\n                onBeforeCreate: opts.onBeforeCreate,\n                onAppLoaded: opts.onAppLoaded,\n                metaspace,\n                space: localUserSpace,\n            });\n\n        // Track the app so `onReady` can access it cleanly\n        const ibgibGlobalThis = opts.getGlobalThis(opts.config);\n        (ibgibGlobalThis as any).appInstance = app;\n\n        app.metaspace = metaspace;\n        await app.witness(resRequestCommentIbGib.newIbGib);\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nasync function defaultGetOrCreateApp<TApp extends IbGibAppAny>({\n    AppClass,\n    defaultAppData,\n    onBeforeCreate,\n    onAppLoaded,\n    metaspace,\n    space,\n}: {\n    AppClass: new (data?: any, rel8ns?: any) => TApp,\n    defaultAppData: any,\n    onBeforeCreate?: (metaspace: MetaspaceService, space: IbGibSpaceAny) => Promise<void>,\n    onAppLoaded?: (app: TApp, isNew: boolean) => Promise<TApp>,\n    metaspace: MetaspaceService,\n    space: IbGibSpaceAny,\n}): Promise<TApp> {\n    const lc = `[${defaultGetOrCreateApp.name}]`;\n    const logalot = true;\n\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n\n        let appsIbGib = await metaspace.getSpecialIbGib({\n            type: SpecialIbGibType.apps,\n            initialize: false, lock: false, space,\n        });\n\n        if (!appsIbGib) { throw new Error(`(UNEXPECTED) no apps index ibgib`); }\n        if (!appsIbGib.rel8ns) { throw new Error(`(UNEXPECTED) appsIbGib.rel8ns falsy`); }\n\n        const appAddrs = (appsIbGib.rel8ns[APP_REL8N_NAME] ?? [] as IbGibAddr[])\n            .filter(addr => {\n                const { ib } = getIbAndGib({ ibGibAddr: addr });\n                return getInfoFromAppIb({ appIb: ib }).appClassname === AppClass.name;\n            });\n\n        let app: TApp;\n        let appAddr: IbGibAddr;\n        let isNew = false;\n\n        if (appAddrs.length === 0) {\n            isNew = true;\n            if (onBeforeCreate) {\n                await onBeforeCreate(metaspace, space);\n            }\n            app = await createAndSaveNewApp({ AppClass, defaultAppData, metaspace, space });\n            appAddr = getIbGibAddr({ ibGib: app });\n        } else if (appAddrs.length === 1) {\n            appAddr = appAddrs[0];\n        } else {\n            const list = appAddrs\n                .map(a => getIbAndGib({ ibGibAddr: a }).ib)\n                .map((ib, idx) => `\\n${idx}) ${ib}`);\n\n            let idx: number | undefined;\n            let retry = false;\n            do {\n                const response = await promptForText({\n                    title: 'Which App?',\n                    msg: `${retry ? 'huh? ' : ''}Multiple apps found. Which one?${list}`,\n                });\n                const parsed = Number.parseInt(response);\n                retry = Number.isNaN(parsed) || parsed >= appAddrs.length;\n                if (!retry) { idx = parsed; }\n            } while (retry);\n            appAddr = appAddrs[idx!];\n        }\n\n        const resGet = await getFromSpace({ addr: appAddr, space });\n        if (resGet.success && resGet.ibGibs?.length === 1) {\n            app = resGet.ibGibs[0] as TApp;\n        } else {\n            throw new Error(`Couldn't get app (${appAddr}).`);\n        }\n\n        if (!app.witness) {\n            const witness = new AppClass(undefined, undefined);\n            await witness.loadIbGibDto(app);\n            app = witness;\n        }\n\n        if (onAppLoaded) {\n            app = await onAppLoaded(app, isNew);\n        }\n\n        return app;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nasync function createAndSaveNewApp<TApp extends IbGibAppAny>({\n    AppClass,\n    defaultAppData,\n    metaspace,\n    space,\n}: {\n    AppClass: new (data?: any, rel8ns?: any) => TApp,\n    defaultAppData: any,\n    metaspace: MetaspaceService,\n    space: IbGibSpaceAny\n}): Promise<TApp> {\n    const lc = `[${createAndSaveNewApp.name}]`;\n    const logalot = true;\n\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n\n        const fnPromptApp = (() => {\n            return async () => {\n                const name = `${AppClass.name}_${pickRandom_Letters({ count: 8 })}`;\n                const data = clone(defaultAppData);\n                data.name = name;\n                data.uuid = await getUUID();\n                const rel8ns = undefined; // App templates usually have DEFAULT_APP_REL8NS as undefined\n\n                const { classname } = data;\n                const ib = getAppIb({ appData: data, classname });\n                return await factory.firstGen({\n                    ib,\n                    parentIbGib: factory.primitive({ ib: `app ${classname}` }),\n                    data, rel8ns,\n                    dna: true,\n                    linkedRel8ns: [Rel8n.ancestor, Rel8n.past],\n                    nCounter: true,\n                    tjp: { timestamp: true },\n                }) as TransformResult<IbGibAppAny>;\n            };\n        })();\n\n        const app = await createNewApp({\n            fnPromptApp,\n            space,\n            ibgibs: metaspace,\n        });\n\n        if (!app) { throw new Error(`Failed to create app (falsy).`); }\n        if (app?.data?.classname !== AppClass.name) {\n            throw new Error(`(UNEXPECTED) wrong app classname.`);\n        }\n        return app as TApp;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nasync function ensureTagsExist({\n    metaspace, tags, logalot\n}: {\n    metaspace: MetaspaceService,\n    tags: TagConfig[],\n    logalot: boolean\n}): Promise<void> {\n    const lc = `[${ensureTagsExist.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n        const tagIbGibs = await metaspace.getSpecialRel8dIbGibs({\n            type: \"tags\", rel8nName: TAG_REL8N_NAME,\n        }) as TagIbGib_V1[];\n\n        for (const tag of tags) {\n            if (!tagIbGibs.some(x => x.data?.text === tag.text)) {\n                await metaspace.createTagIbGib({\n                    text: tag.text,\n                    icon: tag.icon,\n                    description: tag.description,\n                    space: undefined,\n                });\n            }\n        }\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport async function createRequestCommentIbGib_Common({\n    args, interpretedArgInfos,\n}: {\n    args: string[],\n    interpretedArgInfos: RCLIArgInfo[],\n}): Promise<TransformResult<RequestCommentIbGib_V1>> {\n    const text = args.join(' ');\n    const data: RequestCommentData_V1 = {\n        uuid: await getUUID(),\n        text,\n        args,\n        interpretedArgInfos,\n        textTimestamp: getTimestamp(),\n    };\n\n    return await factory.firstGen({\n        parentIbGib: factory.primitive({ ib: 'comment' }),\n        ib: `comment ${text.substring(0, 32).replace(/ /g, '_')}`,\n        data,\n        dna: true,\n        tjp: { uuid: true, timestamp: true },\n        nCounter: true,\n    }) as TransformResult<RequestCommentIbGib_V1>;\n}\n\nexport function validateParamInfos({ paramInfos }: { paramInfos: RCLIParamInfo[] }): string[] {\n    const errors: string[] = [];\n    const identifiers: string[] = [];\n    paramInfos.forEach(p => {\n        const names = [p.name, ...(p.synonyms ?? [])];\n        names.forEach(name => {\n            if (identifiers.includes(name.toLowerCase())) {\n                errors.push(`Duplicate identifier found: ${name}`);\n            }\n            identifiers.push(name.toLowerCase());\n        });\n    });\n    return errors;\n}\n", "import { IbGibAddr, TransformResult } from '@ibgib/ts-gib/dist/types.mjs';\nimport { IbGibRel8ns_V1, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/index.mjs';\n\n\nimport {\n  WitnessData_V1, WitnessRel8ns_V1,\n  WitnessResultData, WitnessResultRel8ns, WitnessResultIbGib,\n} from '../witness-types.mjs';\nimport { IbGibSpaceData_Subpathed } from '../space/space-types.mjs';\nimport { IbGibAppAny } from './app-base-v1.mjs';\nimport { WitnessCmdData, WitnessCmdRel8ns, WitnessCmdIbGib, } from '../witness-cmd/witness-cmd-types.mjs';\n\n\n\n/**\n * ...hmm...?\n *\n * This originally descends from IonicSpaceData_V1. I need to figure out what\n * this is doing, because this shouldn't be scoped to even subpathed strategy.\n * That is entirely an implementation decision.\n */\nexport interface AppSpaceData extends IbGibSpaceData_Subpathed { }\n\nexport enum AppSpaceRel8n {\n  roots = 'roots',\n  tags = 'tags',\n  latest = 'latest',\n  outerspaces = 'outerspaces',\n  secrets = \"secrets\",\n  encryptions = \"encryptions\",\n}\n\nexport interface AppSpaceRel8ns extends IbGibRel8ns_V1 {\n  [AppSpaceRel8n.tags]?: IbGibAddr[];\n  [AppSpaceRel8n.roots]?: IbGibAddr[];\n  [AppSpaceRel8n.latest]?: IbGibAddr[];\n  [AppSpaceRel8n.outerspaces]?: IbGibAddr[];\n  [AppSpaceRel8n.secrets]?: IbGibAddr[];\n  [AppSpaceRel8n.encryptions]?: IbGibAddr[];\n}\n\n/**\n * An app space itself works as the config instead of\n * having an external config object.\n *\n * ## notes\n *\n * Probably need to change this at some point...\n */\nexport interface ConfigIbGib_V1 extends IbGib_V1<AppSpaceData, AppSpaceRel8ns> { }\n\n\nexport interface AppData_V1 extends WitnessData_V1 {\n\n  /**\n   * Name of a App instance...after all, Robbie was only the first App.\n   */\n  name: string;\n\n  /**\n   * Redeclared over {@link WitnessData_V1.uuid} making it a required field.\n   */\n  uuid: string;\n\n  /**\n   * Right now, this will be just for ionicons.\n   */\n  icon: string;\n\n}\n\nexport interface AppRel8ns_V1 extends WitnessRel8ns_V1 {\n}\n\n/**\n */\nexport interface AppIbGib_V1<TData extends AppData_V1 = any, TRel8ns extends AppRel8ns_V1 = any>\n  extends IbGib_V1<TData, TRel8ns> {\n}\n\n\n/**\n * Cmds for interacting with ibgib app witnesses.\n *\n * Not all of these will be implemented for witness.\n *\n * ## todo\n *\n * change these commands to better structure, e.g., verb/do/mod, can/get/addrs\n * */\nexport type AppCmd =\n  'ib' | 'gib' | 'ibgib';\n/** Cmds for interacting with ibgib app witnesses. */\nexport const AppCmd = {\n  /**\n   * it's more like a grunt that is intepreted by context from the app.\n   *\n   * my initial use of this will be to\n   * ...\n   */\n  ib: 'ib' as AppCmd,\n  /**\n   * it's more like a grunt that is intepreted by context from the app.\n   *\n   * my initial use of this will be to indicate to a app ...\n   */\n  gib: 'gib' as AppCmd,\n  /**\n   * third placeholder command.\n   *\n   * I imagine this will be like \"what's up\", but who knows.\n   */\n  ibgib: 'ibgib' as AppCmd,\n}\n\n/**\n * Flags to affect the command's interpretation.\n */\nexport type AppCmdModifier =\n  'ib' | 'gib' | 'ibgib';\n/**\n * Flags to affect the command's interpretation.\n */\nexport const AppCmdModifier = {\n  /**\n   * hmm...\n   */\n  ib: 'ib' as AppCmdModifier,\n  /**\n   * hmm...\n   */\n  gib: 'gib' as AppCmdModifier,\n  /**\n   * hmm...\n   */\n  ibgib: 'ibgib' as AppCmdModifier,\n}\n\n/** Information for interacting with spaces. */\nexport interface AppCmdData<TData extends AppCmd = any, TRel8ns extends AppCmdModifier = any>\n  extends WitnessCmdData<TData, TRel8ns> {\n}\n\nexport interface AppCmdRel8ns extends WitnessCmdRel8ns {\n}\n\n/**\n * Shape of options ibgib if used for a app.\n *\n * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface AppCmdIbGib<\n  TIbGib extends IbGib_V1 = IbGib_V1,\n  TCmd extends AppCmd = AppCmd,\n  TCmdModifier extends AppCmdModifier = AppCmdModifier,\n  TCmdData extends AppCmdData<TCmd, TCmdModifier> = AppCmdData<TCmd, TCmdModifier>,\n  TCmdRel8ns extends AppCmdRel8ns = AppCmdRel8ns,\n> extends WitnessCmdIbGib<TIbGib, AppCmd, AppCmdModifier, TCmdData, TCmdRel8ns> {\n}\n\n/**\n * Optional shape of result data to app interactions.\n *\n * This is in addition of course to {@link WitnessResultData}.\n *\n * ## notes\n *\n * * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface AppResultData extends WitnessResultData {\n}\n\n/**\n * Marker interface rel8ns atm...\n *\n * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface AppResultRel8ns extends WitnessResultRel8ns { }\n\n/**\n * Shape of result ibgib if used for a app.\n *\n * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface AppResultIbGib<\n  TIbGib extends IbGib_V1,\n  TResultData extends AppResultData,\n  TResultRel8ns extends AppResultRel8ns\n>\n  extends WitnessResultIbGib<TIbGib, TResultData, TResultRel8ns> {\n}\n\n// /**\n//  * When coming from the extension in firefox/chrome(chromium), this info\n//  * represents a selection to be converted/saved in an ibgib graph.\n//  */\n// export interface ExtensionSelectionInfo {\n//   type: 'comment' | 'link';\n//   text: string;\n//   url?: string;\n//   children?: ExtensionSelectionInfo[];\n// }\n\n/**\n * this is generated in background.js (WARNING! background.js atow is generated\n * from background.v2.js or background.v3.js . ...do NOT make changes directly\n * in background.js!).\n *\n * When the user is in their browser with the ibgib extension and selects some\n * text or clicks an ibgib context menu item to initiate the app, this info is\n * passed to the app via query params (atow).\n */\n// export interface ExtensionLaunchInfo {\n//   /** brand the event so we know it's ours */\n//   ib: boolean;\n//   /**\n//    * indicate to the receiving angular app that we're launching\n//    * from an extension in firefox/chrome. (this is obvious here in\n//    * background.js but in the angular app, not so much).\n//    */\n//   isExtensionLaunch: boolean;\n//   /**\n//    * So consumer knows where this is coming from. (obvious to us\n//    * here, but helps consumer)\n//    */\n//   lc: string,\n//   /**\n//    * text of the context menu clicked\n//    * @link https://developer.chrome.com/docs/extensions/reference/contextMenus/#type-OnClickData\n//    */\n//   menuItemId: string;\n//   /**\n//    * url of the page that _initiates_ the click and starts the app.\n//    * so if the user is on wikipedia.org, selects some text and clicks on the ibgib link,\n//    * in order to generate some ibgib data based on the page, this will be\n//    * https://en.wikipedia.org/wiki/Phanerozoic (or whatever).\n//    *\n//    * @link https://developer.chrome.com/docs/extensions/reference/contextMenus/#type-OnClickData\n//    */\n//   pageUrl: string;\n//   /**\n//    * info about selections user made when starting the (extension) app.\n//    *\n//    * So if they highlight some text and add it, that is one info. If they highlight a whole paragraph\n//    * it will create a comment for the p and possibly children infos for links in that paragraph.\n//    *\n//    * Same goes for if they select a header tag.\n//    *\n//    * @link https://developer.chrome.com/docs/extensions/reference/contextMenus/#type-OnClickData\n//    */\n//   selectionInfos?: ExtensionSelectionInfo[];\n// }\n\nexport type AppPromptResult = TransformResult<IbGibAppAny>;\n", "import { delay, getFileReaderHack, hash } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { TransformResult, } from '@ibgib/ts-gib/dist/types.mjs';\nimport { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';\nimport { Factory_V1 as factory, IbGibRel8ns_V1, IBGIB_DELIMITER, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/index.mjs';\nimport { getGib } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';\nimport { PicData_V1, PicIbGib_V1 } from './pic-types.mjs';\nimport { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';\nimport { BinIbGib_V1 } from '../bin/bin-types.mjs';\nimport { persistTransformResult, putInSpace } from '../../witness/space/space-helper.mjs';\nimport { getBinIb } from '../other/ibgib-helper.mjs';\nimport { BINARY_REL8N_NAME } from './pic-constants.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT || false;\n\nexport interface PicDependencyGraph {\n  picIbGib: PicIbGib_V1;\n  binIbGib: BinIbGib_V1;\n  dependencies: IbGib_V1[];\n}\n\nexport async function createBinIbGib({\n  base64Data,\n  binHash,\n  ext,\n  saveInSpace,\n  space,\n}: {\n  /**\n   * base64-encoded binary data\n   */\n  base64Data: string,\n  /**\n   * Hash of data\n   */\n  binHash: string,\n  /**\n   * extension of the binary\n   *\n   * this will be included in the ib\n   */\n  ext?: string,\n  /**\n   * If true, will save the ibgibs created in the given `space`.\n\n   * @see {@link space}\n   */\n  saveInSpace?: boolean,\n  /**\n   * space to save the ibgib(s) if `saveInSpace` is truthy.\n   *\n   * @see {@link saveInSpace}\n   */\n  space?: IbGibSpaceAny,\n}): Promise<TransformResult<BinIbGib_V1>> {\n  const lc = `[${createBinIbGib.name}]`;\n  try {\n    if (logalot) { console.log(`${lc} starting...`); }\n\n    if (!binHash) { throw new Error(`binHash required (E: 09da0190a9353089a9ed8a641fe0bc22)`); }\n\n    const binIb = getBinIb({ binHash, binExt: ext, binEncoding: 'base64' });\n    const binIbGib: BinIbGib_V1 = { ib: binIb, data: (base64Data as any) };\n\n    const binGib = await getGib({ ibGib: binIbGib, hasTjp: false });\n    binIbGib.gib = binGib;\n\n    if (saveInSpace) {\n      // prepare\n      if (!space) { throw new Error(`space required if saveInSpace is truthy. (E: b8a5ebbac47d757afce940d2f0af3122)`); }\n      if (logalot) { console.log(`${lc} saving binary ibgib in space... (I: 8235addb1b3e4e638ef568da5f219d29)`); }\n\n      // execute put\n      const resSaveBin = await putInSpace({ ibGib: binIbGib, space });\n\n      // if errored, throw\n      if (!resSaveBin.success) { throw new Error(resSaveBin.errorMsg || 'error saving pic (E: cf892bc62ab44ec58534d9881c9c4332)'); }\n\n      // cleanup\n      if (logalot) { console.log(`${lc} saving binary ibgib in space complete. (I: 4aa8d03088ad477dbee089394b3b9902)`); }\n    }\n\n    return { newIbGib: binIbGib };\n  } catch (error) {\n    console.error(`${lc} ${error.message}`);\n    throw error;\n  } finally {\n    if (logalot) { console.log(`${lc} complete.`); }\n  }\n}\n\n/**\n * shared pic code between camera and loading image via picking a file.\n */\nexport async function createPicAndBinIbGibs({\n  imageBase64,\n  binHash,\n  filename,\n  ext,\n  saveInSpace,\n  space,\n}: {\n  imageBase64: string,\n  binHash: string,\n  filename?: string,\n  ext?: string,\n  /**\n   * If true, will save the ibgibs created in the given `space`.\n   */\n  saveInSpace?: boolean,\n  /**\n   * If `saveInSpace`, all ibgibs created in this function will be stored in\n   * this space.\n   */\n  space?: IbGibSpaceAny,\n}): Promise<[TransformResult<PicIbGib_V1>, TransformResult<BinIbGib_V1>]> {\n  const lc = `[${createPicAndBinIbGibs.name}]`;\n\n  if (logalot) { console.log(`${lc} starting...`); }\n  try {\n    const resCreateBin =\n      await createBinIbGib({ base64Data: imageBase64, binHash, ext, saveInSpace, space });\n    const { newIbGib: binIbGib } = resCreateBin;\n    const binAddr = getIbGibAddr({ ibGib: binIbGib });\n\n    // todo: do thumbnail also\n\n    // NOTE: This is not the same filename that is saved in the bin folder!\n    // This is for when the picture is downloaded outside of the ibGib system\n    // or for display purposes.\n    const timestamp = (new Date).toUTCString();\n    filename = filename || timestamp\n      .replace(':', '-')\n      .replace(':', '-')\n      .replace(',', '')\n      // .replace(new RegExp(/\\W/), '') // any remaining-non-word chars\n      ; // temporary eek.\n\n    if (logalot) { console.log(`${lc} binHash: ${binHash}`); }\n    if (logalot) { console.log(`${lc} ext: ${ext}`); }\n    const data: PicData_V1 = ext ?\n      { binHash, ext, filename, timestamp } :\n      { binHash, filename, timestamp };\n    const rel8ns: IbGibRel8ns_V1 = {\n      // 'pic on': [addr], // makes it more difficult to share/sync ibgibs\n      [BINARY_REL8N_NAME]: [binAddr],\n    };\n\n    // create an ibgib with the filename and ext\n    const resPicIbGib = await factory.firstGen({\n      parentIbGib: factory.primitive({ ib: 'pic' }),\n      ib: `pic ${binHash}`,\n      data,\n      rel8ns,\n      dna: true,\n      tjp: { uuid: true, timestamp: true },\n      nCounter: true,\n    }) as TransformResult<PicIbGib_V1>;\n\n    if (saveInSpace) {\n      if (!space) { throw new Error(`space required if saveInSpace is truthy (E: 966901041c9e166c0f5ed23114003722)`); }\n      await persistTransformResult({ resTransform: resPicIbGib, space });\n    }\n\n    return [resPicIbGib, resCreateBin];\n  } catch (error) {\n    console.error(`${lc} ${error.message}`);\n    throw error;\n  }\n}\n\n/**\n * @deprecated not really deprecated but i'm indicating here that this function\n * is to be changed when i am back on the web browser side of things. i have\n * changed the internal structure of the {@link BinIbGib_V1} to use `Uint8Array`\n * objects on the node side.\n */\nexport async function createPicAndBinIbGibsFromInputFilePickedEvent({\n  event,\n  saveInSpace,\n  space,\n}: {\n  event: any,\n  /**\n   * If true, will save the ibgibs created in the given `space`.\n\n   * @see {@link space}\n   */\n  saveInSpace?: boolean,\n  space: IbGibSpaceAny,\n}): Promise<[TransformResult<PicIbGib_V1>, TransformResult<BinIbGib_V1>][]> {\n  const lc = `[${createPicAndBinIbGibsFromInputFilePickedEvent.name}]`;\n  try {\n    // validate incoming input picker result\n    // thanks https://edupala.com/capacitor-camera-example/\n    const target = event.target as HTMLInputElement;\n    if (!target) { throw new Error(`event.target required (E: a9ade57d4359d3b0bbc75c3fea093a22)`); }\n    if ((target.files ?? []).length === 0) { throw new Error(`target.files is falsy/empty (E: f2932f1012c9e04a5f06a521a381ff22)`); }\n\n    const result: [TransformResult<PicIbGib_V1>, TransformResult<BinIbGib_V1>][] = [];\n\n    // going to execute serially to maintain order of incoming target files\n    // IOW not going to do a Promise.all equivalent\n    for (let i = 0; i < target.files!.length; i++) {\n      const file = target.files![i];\n      if (!file) { throw new Error(`file required. (E: 24a8bf4cdf17dcae04b15438bc0a4522)`); }\n      const pattern = /image-*/;\n      if (!file.type.match(pattern)) { throw new Error(`File format not supported. file: ${file} (E: dca558def013c1c85c83f0ac088b2122)`); }\n      // wrap reader in promise for use with async/await\n      const resSingleCreate =\n        await new Promise<[TransformResult<PicIbGib_V1>, TransformResult<BinIbGib_V1>]>((resolve, reject) => {\n          // const reader = new FileReader();\n          throw new Error(`not implemented since change of BinIbGib.data to be Uint8Array in node. I believe here we may want to read the file as an ArrayBuffer (see readAsArrayBuffer documentation on mdn https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsArrayBuffer) (E: bb806524120cd5e40e168ef87a3ede24)`);\n          const reader = getFileReaderHack();\n          reader.onload = async (_: any) => {\n            const lc2 = `${lc}[reader.onload]`;\n            try {\n              if (logalot) { console.log(`${lc2} starting... (I: 1e948476ca86b328a12700dc57be0a22)`); }\n              if (!reader.result) { throw new Error(`(UNEXPECTED) reader.result falsy but onload fired? (E: fdac6638fe6e2db3de1ac277bc29dc23)`); }\n              let imageBase64 = reader.result.toString().split('base64,')[1];\n              let binHash = await hash({ s: imageBase64 });\n              const filenameWithExt = file.name;\n              const filenamePieces = filenameWithExt.split('.');\n              const filename = filenamePieces.slice(0, filenamePieces.length - 1).join('.');\n              const ext = filenamePieces.slice(filenamePieces.length - 1)[0];\n              if (ext.includes(IBGIB_DELIMITER)) {\n                throw new Error(`file extension cannot contain the character ${IBGIB_DELIMITER} (E: f5bc9ef79f7efe01cd53abd49d9f6122)`);\n              }\n\n              await delay(32); // slight doProcesses UI thread hack - not sure how much it helps (if any)\n              const resCreate = await createPicAndBinIbGibs({\n                imageBase64, binHash, filename, ext, saveInSpace, space,\n              });\n              resolve(resCreate);\n\n            } catch (error) {\n              console.error(`${lc2} ${error.message}`);\n              reject(error);\n            } finally {\n              if (logalot) { console.log(`${lc2} complete. (I: d88dcaeb874c4f049d51d58655dc2b62)`); }\n            }\n          };\n          reader.readAsDataURL(file);\n        });\n\n      result.push(resSingleCreate);\n    }\n\n    return result;\n\n  } catch (error) {\n    console.error(`${lc} ${error.message}`);\n    throw error;\n  }\n}\n\nexport function isPic({\n  ibGib,\n}: {\n  ibGib: IbGib_V1,\n}): boolean {\n  const lc = `[${isPic.name}]`;\n  try {\n    if (logalot) { console.log(`${lc} starting...`); }\n\n    if (!ibGib) { throw new Error(`ibGib required (E: 1237b2d4602a3d526f6b159cb6ad0922)`); }\n\n    const { ib, data, rel8ns } = ibGib;\n\n    // try rel8ns first\n    if (!rel8ns) {\n      if (logalot) { console.log(`${lc} rel8ns falsy, not a pic (I: 563a3e779b85b070550581e652e0ca22)`); }\n      return false;\n    }\n\n    // descends from pic^gib\n    const ancestors = rel8ns.ancestor || [];\n    if (ancestors && ancestors.includes('pic^gib')) {\n      return true;\n    }\n\n    // has binary qualities and ib contains 'pic'\n    if (!data) {\n      if (logalot) { console.log(`${lc} data falsy, not a pic (I: 6c05c03cdfca4085aef8f2a19df91690)`); }\n      return false;\n    }\n    if (data.binHash && data.ext && data.filename && ib?.includes('pic')) {\n      if (logalot) { console.log(`${lc} has binHash, ext, filename and ib has pic (I: f754b6b023d5379ee770038617edc722)`); }\n      return true;\n    }\n\n    if (logalot) { console.log(`${lc} reached end, doesn't have pic qualities. not a pic. (I: 298c5e9a2916445df1cdd22a96f57522)`); }\n    return false;\n  } catch (error) {\n    console.error(`${lc} ${error.message}`);\n    throw error;\n  } finally {\n    if (logalot) { console.log(`${lc} complete.`); }\n  }\n}\n", "import { extractErrorMsg, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport {\n    IbGib_V1, IbGibRel8ns_V1,\n} from '@ibgib/ts-gib/dist/V1/index.mjs';\n\nimport {\n    AppData_V1, AppRel8ns_V1, AppIbGib_V1,\n    AppCmd,\n    AppCmdData, AppCmdRel8ns, AppCmdIbGib,\n    AppResultData, AppResultRel8ns, AppResultIbGib,\n} from './app-types.mjs';\nimport { WitnessBase_V1, } from '../witness-base-v1.mjs';\nimport { CommentIbGib_V1 } from '../../common/comment/comment-types.mjs';\nimport { PicIbGib_V1 } from '../../common/pic/pic-types.mjs';\nimport { ErrorIbGib_V1 } from '../../common/error/error-types.mjs';\nimport { validateCommonAppData } from './app-helper.mjs';\nimport { argy_, isArg, isCommand, resulty_ } from '../witness-helper.mjs';\nimport { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';\nimport { getErrorIbGib } from '../../common/error/error-helper.mjs';\nimport { isComment } from '../../common/comment/comment-helper.mjs';\nimport { isPic } from '../../common/pic/pic-helper.mjs';\nimport { WitnessWithContextBase_V1 } from '../witness-with-context/witness-with-context-base-v1.mjs';\nimport { MetaspaceService } from '../space/metaspace/metaspace-types.mjs';\n\nconst logalot = GLOBAL_LOG_A_LOT || false;\n\n/**\n * ## distinguishing characteristics of apps\n *\n * So for example, one of the simplest apps is one which\n * ...\n *\n * ## architecture\n *\n * ...\n */\nexport abstract class AppBase_V1<\n    TOptionsData extends any = any,\n    TOptionsRel8ns extends IbGibRel8ns_V1 = IbGibRel8ns_V1,\n    TOptionsIbGib extends IbGib_V1<TOptionsData, TOptionsRel8ns>\n    = IbGib_V1<TOptionsData, TOptionsRel8ns>,\n    TResultData extends any = any,\n    TResultRel8ns extends IbGibRel8ns_V1 = IbGibRel8ns_V1,\n    TResultIbGib extends IbGib_V1<TResultData, TResultRel8ns> | ErrorIbGib_V1\n    = IbGib_V1<TResultData, TResultRel8ns>,\n    TData extends AppData_V1 = AppData_V1,\n    TRel8ns extends AppRel8ns_V1 = AppRel8ns_V1,\n>\n    extends WitnessWithContextBase_V1<\n        TOptionsData, TOptionsRel8ns, TOptionsIbGib,\n        TResultData, TResultRel8ns, TResultIbGib,\n        TData, TRel8ns>\n    implements AppIbGib_V1<TData, TRel8ns> {\n\n    /**\n     * Log context for convenience with logging. (Ignore if you don't want to use this.)\n     */\n    protected lc: string = `[${AppBase_V1.name}]`;\n\n    // /**\n    //  * Reference to the local ibgibs service, which is one way at getting at the\n    //  * local user space.\n    //  */\n    // metaspace: MetaspaceService | undefined;\n\n    constructor(initialData?: TData, initialRel8ns?: TRel8ns) {\n        super(initialData, initialRel8ns);\n    }\n\n    /**\n     * At this point in time, the arg has already been intrinsically validated,\n     * as well as the internal state of this app. so whatever this app's\n     * function is, it should be good to go.\n     *\n     * In the base class, this just returns {@link routeAndDoArg}. If you don't\n     * want to route, then override this.\n     */\n    protected async witnessImpl(arg: TOptionsIbGib): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.witnessImpl.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n\n            await this.loadNewerSelfIfAvailable();\n\n            let result: TResultIbGib | undefined = undefined;\n\n            if (isArg({ ibGib: arg as IbGib_V1 })) {\n                result = await this.routeAndDoArg({ arg });\n            } else {\n                result = await this.doNonArg({ ibGib: arg as IbGib_V1 });\n            }\n\n            // if we didn't get a result, try the default.\n            if (!result) {\n                console.warn(`${lc} result still falsy. doing default handler. (W: aba0de32c3835056447d7de3a2fb0223)`);\n                result = await this.doDefault({ ibGib: arg as IbGib_V1 });\n            }\n\n            if (!result) { console.warn(`${lc} result falsy...Could not produce result? Was doDefault implemented in concrete class? (W: 15e70486bc33922f9388961bab815223)`); }\n\n            return result;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Base routing executes different if incoming is a cmd options arg, i.e.,\n     * if the `data.cmd` is truthy (atow). {@link isArg} is expected to be true\n     * at this point. If not, logs an error, **but does not throw**, and returns\n     * undefined.\n     *\n     * Default routing checks arg for command, or if not, checks if comment/pic.\n     * If neither of those, then returns undefined atow.\n     *\n     * Override this function to create more advanced custom routing.\n     *\n     * ## notes\n     *\n     * In general, an app ibgib acts more like a normal application in that it\n     * accepts commands and not requests. Robbots are more geared to requests,\n     * handled semantically.\n     *\n     * @see {@link isArg}\n     * @see {@link doCmdArg}\n     * @see {@link doDefault}.\n     */\n    protected async routeAndDoArg({\n        arg,\n    }: {\n        arg: TOptionsIbGib,\n    }): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.routeAndDoArg.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            const ibGib = arg as IbGib_V1;\n            if (!isArg({ ibGib })) { throw new Error(`ibGib is not an arg (E: f0e36b13acbcdb1123ee72bdb9ee7723)`); }\n            if (isCommand({ ibGib })) {\n                return this.doCmdArg({ arg: arg as AppCmdIbGib<IbGib_V1, any, any, AppCmdData<any, any>, AppCmdRel8ns> });\n            } else {\n                return undefined;\n            }\n\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            if (this.data?.catchAllErrors) {\n                return (await getErrorIbGib({ rawMsg: extractErrorMsg(error) })) as TResultIbGib;\n            } else {\n                throw error;\n            }\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #region do cmd args\n\n    /**\n     * By default, this routes to {@link doCmdIb}, {@link doCmdGib} & {@link\n     * doCmdIbgib}. This is largely to limit scope of responsibility of app to\n     * basic functions. But this is not a concrete rule written in stone.\n     *\n     * You can always override this and route to other commands before calling\n     * this with `super.doCmdArg` as a fallback (if you still want to use this\n     * function.)\n     *\n     * Note that this @throws an error if the data.cmd is not recognized. In this\n     * implementation, this occurs if it isn't an ib/gib/ibgib _command_.\n     */\n    protected doCmdArg({\n        arg,\n    }: {\n        arg: AppCmdIbGib<IbGib_V1, any, any, AppCmdData<any, any>, AppCmdRel8ns>,\n    }): Promise<TResultIbGib> {\n        const lc = `${this.lc}[${this.doCmdArg.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (!arg.data?.cmd) { throw new Error(`invalid cmd arg. arg.data.cmd required. (E: aec4dd5bd967fbf36f9c4fad22210222)`); }\n            if (arg.data.cmd === AppCmd.ib) {\n                return this.doCmdIb({ arg: arg });\n            } else if (arg.data.cmd === AppCmd.gib) {\n                return this.doCmdGib({ arg: arg });\n            } else if (arg.data.cmd === AppCmd.ibgib) {\n                return this.doCmdIbgib({ arg: arg });\n            } else {\n                throw new Error(`unknown arg.data.cmd: ${arg.data.cmd} (E: 721fa6a5166327134f9504c1caa3e422)`);\n            }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected doCmdIb({\n        arg,\n    }: {\n        arg: IbGib_V1,\n    }): Promise<TResultIbGib> {\n        const lc = `${this.lc}[${this.doCmdIb.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            throw new Error(`not implemented in base class (E: 7298662a2b8f67611d16a8af0e499422)`);\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n    protected doCmdGib({\n        arg,\n    }: {\n        arg: IbGib_V1,\n    }): Promise<TResultIbGib> {\n        const lc = `${this.lc}[${this.doCmdGib.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            throw new Error(`not implemented in base class (E: b6bf2c788c734051956481be7283d006)`);\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n    protected doCmdIbgib({\n        arg,\n    }: {\n        arg: IbGib_V1,\n    }): Promise<TResultIbGib> {\n        const lc = `${this.lc}[${this.doCmdIbgib.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            throw new Error(`not implemented in base class (E: 4fee11f05315467abd036cd8555d27db)`);\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #endregion do cmd args\n\n    // #region other stubbed do functions (doPic, doComment, doDefault)\n\n    /**\n     * Stubbed in base class for convenience. Doesn't have to be implemented.\n     */\n    protected doPic({\n        ibGib,\n    }: {\n        ibGib: PicIbGib_V1,\n    }): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.doPic.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            throw new Error(`not implemented in base class (E: 16ba889931644d42ad9e476757dd0617)`);\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * Stubbed in base class for convenience. Doesn't have to be implemented.\n     */\n    protected doComment({\n        ibGib,\n    }: {\n        ibGib: CommentIbGib_V1,\n    }): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.doComment.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n\n            throw new Error(`not implemented in base class (E: 0486a7864729456d993a1afe246faea4)`);\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected doNonArg({\n        ibGib,\n    }: {\n        ibGib: IbGib_V1,\n    }): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.doNonArg.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (isComment({ ibGib })) {\n                return this.doComment({ ibGib: ibGib as CommentIbGib_V1 });\n            } else if (isPic({ ibGib })) {\n                return this.doPic({ ibGib: ibGib as PicIbGib_V1 });\n            } else {\n                return this.doDefault({ ibGib });\n            }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n    /**\n     * Stubbed in base class for convenience. Doesn't have to be implemented.\n     */\n    protected doDefault({\n        ibGib,\n    }: {\n        ibGib: IbGib_V1,\n    }): Promise<TResultIbGib | undefined> {\n        const lc = `${this.lc}[${this.doDefault.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            throw new Error(`not implemented in base class (E: 5038662186617aaf1f0cc698fd1f9622)`);\n            // return this.doDefaultImpl({ibGib});\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // #endregion other stubbed do functions (doPic, doComment, doDefault)\n\n    /**\n     * validates against common app qualities.\n     *\n     * Override this with a call to `super.validateThis` for custom validation\n     * for descending app classes.\n     *\n     * @returns validation errors common to all apps, if any errors exist.\n     */\n    protected async validateThis(): Promise<string[]> {\n        const lc = `${this.lc}[${this.validateThis.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (!this.data) {\n\n            }\n            const errors = [\n                // ...await super.validateThis(),\n                ...validateCommonAppData({ appData: this.data }),\n            ];\n            return errors;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * builds an arg ibGib.\n     *\n     * wrapper convenience to avoid long generic calls.\n     */\n    async argy<\n        TCmdOptionsData extends AppCmdData<any, any> = AppCmdData<any, any>,\n        TCmdOptionsRel8ns extends AppCmdRel8ns = AppCmdRel8ns,\n        TCmdOptionsIbGib extends AppCmdIbGib<IbGib_V1, any, any, TCmdOptionsData, TCmdOptionsRel8ns> =\n        AppCmdIbGib<IbGib_V1, any, any, TCmdOptionsData, TCmdOptionsRel8ns>\n    >({\n        argData,\n        ibMetadata,\n        noTimestamp,\n        ibGibs,\n    }: {\n        argData: TCmdOptionsData,\n        ibMetadata?: string,\n        noTimestamp?: boolean,\n        ibGibs?: IbGib_V1[],\n    }): Promise<TCmdOptionsIbGib> {\n        const arg = await argy_<TCmdOptionsData, TCmdOptionsRel8ns, TCmdOptionsIbGib>({\n            argData,\n            ibMetadata,\n            noTimestamp\n        });\n\n        if (ibGibs) { arg.ibGibs = ibGibs; }\n\n        return arg;\n    }\n\n    /**\n     * builds a result ibGib, if indeed a result ibgib is required.\n     *\n     * This is only useful in apps that have more structured inputs/outputs.\n     * For those that simply accept any ibgib incoming and return a\n     * primitive like ib^gib or whatever, then this is unnecessary.\n     *\n     * wrapper convenience to avoid long generic calls.\n     */\n    async resulty<\n        TResultData extends AppResultData = AppResultData,\n        TResultRel8ns extends AppResultRel8ns = AppResultRel8ns,\n        TResultIbGib extends AppResultIbGib<IbGib_V1, TResultData, TResultRel8ns> =\n        AppResultIbGib<IbGib_V1, TResultData, TResultRel8ns>\n    >({\n        resultData,\n        ibGibs,\n    }: {\n        resultData: TResultData,\n        ibGibs?: IbGib_V1[],\n    }): Promise<TResultIbGib> {\n        const result = await resulty_<TResultData, TResultIbGib>({\n            // ibMetadata: getAppResultMetadata({space: this}),\n            resultData,\n        });\n        if (ibGibs) { result.ibGibs = ibGibs; }\n        return result;\n    }\n\n}\n\nexport interface IbGibAppAny\n    extends AppBase_V1<any, any, any, any, any, any, any, any> {\n}\n", "/**\n * @module blank-canvas app types (and some enums/constants)\n */\n\nimport { DEFAULT_COMMAND_ESCAPE_STRING, BlankCanvasCommand } from \"./blank-canvas-constants.mjs\";\nimport { RCLIArgInfo, RCLIArgType } from \"@ibgib/helper-gib/dist/rcli/rcli-types.mjs\";\nimport { IbGib_V1 } from \"@ibgib/ts-gib/dist/V1/types.mjs\";\nimport { IbGibAddr } from \"@ibgib/ts-gib/dist/types.mjs\";\nimport { CommentIbGib_V1 } from \"@ibgib/core-gib/dist/common/comment/comment-types.mjs\";\nimport { MetaspaceService } from \"@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs\";\n\nimport {\n    AppData_V1, AppRel8ns_V1,\n    AppCmdData, AppCmdRel8ns, AppCmdIbGib,\n    // AppCmd, AppCmdModifier,\n    AppResultData, AppResultRel8ns, AppResultIbGib,\n    AppIbGib_V1,\n} from \"@ibgib/core-gib/dist/witness/app/app-types.mjs\";\n\n// /**\n//  * example enum-like type+const that I use in ibgib. sometimes i put\n//  * these in the types.mts and sometimes in the const.mts, depending\n//  * on context.\n//  */\n// export type SomeEnum =\n//     'ib' | 'gib';\n// /**\n//  * @see {@link SomeEnum}\n//  */\n// export const SomeEnum = {\n//     ib: 'ib' as SomeEnum,\n//     gib: 'gib' as SomeEnum,\n// } satisfies { [key: string]: SomeEnum };\n// /**\n//  * values of {@link SomeEnum}\n//  */\n// export const SOME_ENUM_VALUES: SomeEnum[] = Object.values(SomeEnum);\n\nexport const DEFAULT_UUID_BLANK_CANVAS_APP = '';\nexport const DEFAULT_NAME_BLANK_CANVAS_APP = 'blank_canvas';\nexport const DEFAULT_DESCRIPTION_BLANK_CANVAS_APP =\n    `HMM what is our description?`;\n\n/**\n * ibgib's intrinsic data goes here.\n *\n * @see {@link IbGib_V1.data}\n */\nexport interface BlankCanvasAppData_V1 extends AppData_V1 {\n    // ibgib data (settings/values/etc) goes here\n    // /**\n    //  * docs yo\n    //  */\n    // setting: string;\n}\n\n/**\n * rel8ns (named edges/links in DAG) go here.\n *\n * @see {@link IbGib_V1.rel8ns}\n */\nexport interface BlankCanvasAppRel8ns_V1 extends AppRel8ns_V1 {\n    // /**\n    //  * required rel8n. for most, put in blank-canvas-constants.mts file\n    //  *\n    //  * @see {@link REQUIRED_REL8N_NAME}\n    //  */\n    // [REQUIRED_REL8N_NAME]: IbGibAddr[];\n    // /**\n    //  * optional rel8n. for most, put in blank-canvas-constants.mts file\n    //  *\n    //  * @see {@link OPTIONAL_REL8N_NAME}\n    //  */\n    // [OPTIONAL_REL8N_NAME]?: IbGibAddr[];\n}\n\n/**\n * this is the ibgib DTO itself. this is NOT the ibgib app class.\n *\n * If this is a plain ibgib data only object, this acts as a dto. The app\n * witness class is slightly different, as this adds on a single method called\n * `witness`. The general design is to send commands and other ibgibs to the\n * witness and receive an ibgib as a result. this acts as a single point of\n * binding interaction and has many other consequences. see the `Witness`\n * interface in core-gib `witness-types.mts` for more information.\n *\n * @see {@link BlankCanvasAppData_V1}\n * @see {@link BlankCanvasAppRel8ns_V1}\n */\nexport interface BlankCanvasAppIbGib_V1 extends IbGib_V1<BlankCanvasAppData_V1, BlankCanvasAppRel8ns_V1> {\n}\n\n/**\n * Default data values for a BlankCanvas app.\n *\n * If you change this, please bump the version\n *\n * (but of course won't be the end of the world when this doesn't happen).\n */\nexport const DEFAULT_BLANK_CANVAS_APP_DATA_V1: BlankCanvasAppData_V1 = {\n    version: '1',\n    uuid: DEFAULT_UUID_BLANK_CANVAS_APP,\n    name: DEFAULT_NAME_BLANK_CANVAS_APP,\n    description: DEFAULT_DESCRIPTION_BLANK_CANVAS_APP,\n    classname: `BlankCanvasApp_V1`,\n\n    icon: 'square',\n\n    /**\n     * if true, then the app will attempt to persist ALL calls to\n     * `app.witness`.\n     */\n    persistOptsAndResultIbGibs: false,\n    /**\n     * allow ibgibs like 42^gib ({ib: 42, gib: 'gib'} with `data` and `rel8ns` undefined)\n     */\n    allowPrimitiveArgs: true,\n    /**\n     * witnesses should be guaranteed not to throw uncaught exceptions.\n     */\n    catchAllErrors: true,\n    /**\n     * if true, would enable logging of all calls to `app.witness`\n     */\n    trace: false,\n\n    cmdEscapeString: DEFAULT_COMMAND_ESCAPE_STRING,\n}\nexport const DEFAULT_BLANK_CANVAS_APP_REL8NS_V1: BlankCanvasAppRel8ns_V1 | undefined = undefined;\n\n/**\n * Cmds for interacting with ibgib apps.\n *\n * Not all of these will be implemented for every app.\n *\n * ## todo\n *\n * change these commands to better structure, e.g., verb/do/mod, can/get/addrs\n * */\nexport type BlankCanvasAppCmd =\n    'ib' | 'gib' | 'ibgib';\n/** Cmds for interacting with ibgib spaces. */\nexport const BlankCanvasAppCmd = {\n    /**\n     * it's more like a grunt that is intepreted by context.\n     */\n    ib: 'ib' satisfies BlankCanvasAppCmd,\n    /**\n     * it's more like a grunt that is intepreted by context.\n     */\n    gib: 'gib' satisfies BlankCanvasAppCmd,\n    /**\n     * third placeholder command.\n     *\n     * I imagine this will be like \"what's up\", but who knows.\n     */\n    ibgib: 'ibgib' satisfies BlankCanvasAppCmd,\n} satisfies { [cmd: string]: BlankCanvasAppCmd }\n\n/**\n * Flags to affect the command's interpretation.\n */\nexport type BlankCanvasAppCmdModifier =\n    'ib' | 'gib' | 'ibgib';\n/**\n * Flags to affect the command's interpretation.\n */\nexport const BlankCanvasAppCmdModifier = {\n    /**\n     * hmm...\n     */\n    ib: 'ib' satisfies BlankCanvasAppCmdModifier,\n    /**\n     * hmm...\n     */\n    gib: 'gib' satisfies BlankCanvasAppCmdModifier,\n    /**\n     * hmm...\n     */\n    ibgib: 'ibgib' satisfies BlankCanvasAppCmdModifier,\n} satisfies { [cmdModifier: string]: BlankCanvasAppCmdModifier }\n\n/** Information for interacting with spaces. */\nexport interface BlankCanvasAppCmdData\n    extends AppCmdData<BlankCanvasAppCmd, BlankCanvasAppCmdModifier> {\n}\n\nexport interface BlankCanvasAppCmdRel8ns extends AppCmdRel8ns {\n}\n\n/**\n * Shape of options ibgib if used for a command-based app.\n */\nexport interface BlankCanvasAppCmdIbGib\n    extends AppCmdIbGib<\n        IbGib_V1,\n        BlankCanvasAppCmd, BlankCanvasAppCmdModifier,\n        BlankCanvasAppCmdData, BlankCanvasAppCmdRel8ns\n    > {\n}\n\n/**\n * Optional shape of result data to app interactions.\n *\n * This is in addition of course to {@link BlankCanvasAppResultData}.\n *\n * so if you're sending a cmd to this app, this should probably be the shape\n * of the result.\n *\n * ## notes\n *\n * * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface BlankCanvasAppResultData extends AppResultData {\n}\n\n/**\n * Marker interface rel8ns atm...\n *\n * so if you're sending a cmd to this app, this should probably be the shape\n * of the result.\n *\n * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface BlankCanvasAppResultRel8ns extends AppResultRel8ns { }\n\n/**\n * Shape of result ibgib if used for a app.\n *\n * so if you're sending a cmd to this app, this should probably be the shape\n * of the result.\n *\n * I'm not sure what to do with this atm, so I'm just stubbing out...\n */\nexport interface BlankCanvasAppResultIbGib\n    extends AppResultIbGib<IbGib_V1, BlankCanvasAppResultData, BlankCanvasAppResultRel8ns> {\n}\n\n/**\n * used with app's ib additional metadata. most app ibs I've made have this addl\n * metadata field which is an underscore-delimited field (which is why\n * underscores are removed). the purpose of this is to have per-use-case addl\n * metadata that would be useful to someone (person, api function, whatever)\n * looking at only the ib without loading the entire ibgib data (which could be\n * very expensive).\n */\nexport interface BlankCanvasAppAddlMetadata {\n    /**\n     * should be $snake_name\n     */\n    atom?: \"blank_canvas_app\";\n    /**\n     * classname of blank-canvas **with any underscores removed**.\n     */\n    classnameIsh?: string;\n    /**\n     * name of blank-canvas app witness **with any underscores removed**.\n     */\n    nameIsh?: string;\n    /**\n     * id of blank-canvas app witness **with any underscores removed**.\n     */\n    idIsh?: string;\n}\n\nimport { BlankCanvasApp_V1 } from \"./blank-canvas-app-v1.mjs\";\n// import {\n//     WitnessArgData, WitnessArgRel8ns, WitnessArgIbGib,\n//     WitnessResultData, WitnessResultRel8ns, WitnessResultIbGib,\n// } from \"@ibgib/core-gib/dist/witness/witness-types.mjs\";\n\nexport const DEFAULT_UUID_RCLI_APP = '';\nexport const DEFAULT_NAME_RCLI_APP = 'rcli_gib';\nexport const DEFAULT_DESCRIPTION_RCLI_APP =\n    `A RCLI (Request/Command Line Interface) app done ibgib style. Instead of rigid RCLI-style\ncommands, uses more flexible natural language with chat robbots for request\nrouting to interface with ibgib data space(s).`;\n\n\nexport interface BlankCanvasAppData_V1 extends AppData_V1 {\n    /**\n     * escape sequence when commanding this rcli app to do something.\n     *\n     * works basically the same as robbots' requestEscapeString.\n     */\n    cmdEscapeString: string;\n}\n\nexport const RCLI_ROBBOT_REL8N_NAME = 'rliRobbot';\nexport interface BlankCanvasAppRel8ns_V1 extends AppRel8ns_V1 {\n    /**\n     * robbot(s) that this RCLI uses to interact with the user.\n     *\n     * the first robbot takes precedence(?)...hmm\n     */\n    [RCLI_ROBBOT_REL8N_NAME]: IbGibAddr[];\n}\n\nexport interface BlankCanvasAppIbGib_V1 extends AppIbGib_V1<BlankCanvasAppData_V1, BlankCanvasAppRel8ns_V1> {\n\n}\n\n/**\n * Default data values for a random app.\n *\n * If you change this, please bump the version\n *\n * (but of course won't be the end of the world when this doesn't happen).\n */\nexport const DEFAULT_RCLI_APP_DATA_V1: BlankCanvasAppData_V1 = {\n    version: '1',\n    uuid: DEFAULT_UUID_RCLI_APP,\n    name: DEFAULT_NAME_RCLI_APP,\n    description: DEFAULT_DESCRIPTION_RCLI_APP,\n    classname: `BlankCanvasApp_V1`,\n\n    icon: 'code-slash',\n\n    persistOptsAndResultIbGibs: false,\n    allowPrimitiveArgs: true,\n    catchAllErrors: true,\n    trace: false,\n\n    cmdEscapeString: DEFAULT_COMMAND_ESCAPE_STRING,\n}\nexport const DEFAULT_RCLI_APP_REL8NS_V1: BlankCanvasAppRel8ns_V1 | undefined = undefined;\n\nexport interface BlankCanvasAppAddlMetadata {\n    /**\n     * should be rcli\n     */\n    atom?: 'blank_canvas_app';\n    /**\n     * classname of app **with any underscores removed**.\n     */\n    classnameIsh?: string;\n    /**\n     * name of app witness **with any underscores removed**.\n     */\n    nameIsh?: string;\n    /**\n     * id of app witness **with any underscores removed**.\n     */\n    idIsh?: string;\n}\n\nexport type ExpectPathType = 'file' | 'directory' | 'exists' | 'empty-directory' | undefined;\n\nexport interface BlankCanvasCommandTextInfo {\n    /**\n     * raw text from the command ibgib. (i.e. ibgib.data.text)\n     */\n    rawText: string,\n    /**\n     * If the command is valid, then this should be the command name (i.e.\n     * paramInfo.name not a synonym if that was what was provided in the raw\n     * text).\n     */\n    cmd?: BlankCanvasCommand,\n    /**\n     * If the command is valid, then this should be populated with\n     * the argInfos generated from parsing the command.\n     */\n    argInfos?: RCLIArgInfo<RCLIArgType>[],\n    /**\n     * If true, then there was an error with the command, not necessarily with\n     * its processing.\n     *\n     * I think most likely this is a validation error.\n     */\n    errorMsg?: string\n    /**\n     * If true, then the command is either the bare help command or\n     * we are showing the help for the command.\n     */\n    showHelp?: boolean;\n}\n\nexport interface BlankCanvasCommandHandlerAddCommentFunctionArgs {\n    text: string,\n    contextIbGib: IbGib_V1,\n    rel8nName: string,\n}\n\n/**\n * BlankCanvasApp_V1 handler for commands via comment ibgibs.\n */\nexport interface BlankCanvasCommandHandlerArg {\n    fnAddComment: (arg: BlankCanvasCommandHandlerAddCommentFunctionArgs) => Promise<void>;\n    cmdInfo: BlankCanvasCommandTextInfo;\n    metaspace: MetaspaceService;\n    contextIbGib: IbGib_V1;\n    ibGib: CommentIbGib_V1;\n    cmdEscapeString: string;\n}\n\nexport type BlankCanvasCommandHandler =\n    (arg: BlankCanvasCommandHandlerArg) => Promise<IbGib_V1 | undefined>;\n\n// /**\n//  * currently i'm just taking this from the definition of node's `Buffer` type.\n//  *\n//  * using this with handle-reify-file.mts when reading the file.\n//  * note that 'binary' may reoslve to 'latin1' per SO at https://stackoverflow.com/questions/46441667/reading-binary-data-in-node-js\n//  */\n// export type FileEncoding =\n//     | 'ascii'\n//     | 'utf8'\n//     | 'utf-8'\n//     | 'utf16le'\n//     | 'ucs2'\n//     | 'ucs-2'\n//     | 'base64'\n//     | 'base64url'\n//     | 'latin1'\n//     | 'binary'\n//     | 'hex';\n// export const FileEncoding = {\n//     ascii: 'ascii' as FileEncoding,\n//     utf8: 'utf8' as FileEncoding,\n//     utf_8: 'utf-8' as FileEncoding,\n//     ['utf-8']: 'utf-8' as FileEncoding,\n//     utf16le: 'utf16le' as FileEncoding,\n//     ucs2: 'ucs2' as FileEncoding,\n//     ucs_2: 'ucs-2' as FileEncoding,\n//     ['ucs-2']: 'ucs-2' as FileEncoding,\n//     base64: 'base64' as FileEncoding,\n//     base64url: 'base64url' as FileEncoding,\n//     latin1: 'latin1' as FileEncoding,\n//     binary: 'binary' as FileEncoding,\n//     hex: 'hex' as FileEncoding,\n// };\n// /**\n//  * valid file encoding values per {@link FileEncoding}\n//  */\n// export const FILE_ENCODINGS = Object.values(FileEncoding);\n", "/*\n * @module blank-canvas helper/util/etc. functions\n *\n * this is where you will find helper functions like those that generate and\n * parse ibs for blank-canvas.\n */\n\n// import * as pathUtils from 'path';\n// import { statSync } from 'node:fs';\n// import { readFile, } from 'node:fs/promises';\n// import * as readline from 'node:readline/promises';\n// import { stdin, stdout } from 'node:process'; // decide if use this or not\n\nimport {\n    extractErrorMsg,\n    getSaferSubstring,\n    getTimestamp,\n    getUUID,\n    pretty,\n    // delay, getSaferSubstring,\n    // getTimestampInTicks, getUUID, pretty,\n} from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { UUID_REGEXP, CLASSNAME_REGEXP, } from '@ibgib/helper-gib/dist/constants.mjs';\nimport { RCLIArgInfo, RCLIParamInfo } from '@ibgib/helper-gib/dist/rcli/rcli-types.mjs';\nimport { Ib, TransformResult, } from '@ibgib/ts-gib/dist/types.mjs';\nimport { validateIbGibIntrinsically, } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';\nimport { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs';\nimport { WitnessFormBuilder } from '@ibgib/core-gib/dist/witness/witness-form-builder.mjs';\nimport { isComment } from '@ibgib/core-gib/dist/common/comment/comment-helper.mjs';\nimport { persistTransformResult } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';\nimport { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';\n// import { IbGibBlankCanvasAppAny } from './blank-canvas-app-v1.mjs';\nimport {\n    BlankCanvasAppData_V1, BlankCanvasAppRel8ns_V1, BlankCanvasAppIbGib_V1,\n} from './blank-canvas-types.mjs';\nimport { BLANK_CANVAS_APP_NAME_REGEXP, DEFAULT_COMMAND_ESCAPE_STRING, DEFAULT_PROMPT_TEMPLATE, PARAM_INFO_INIT, PARAM_INFO_IN_MEMORY, } from './blank-canvas-constants.mjs';\nimport { RequestCommentData_V1, RequestCommentIbGib_V1 } from '../../../types.mjs';\nimport { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';\n\n/**\n * for logging. import this constant from your project.\n */\nconst logalot = GLOBAL_LOG_A_LOT;\n\nif (logalot) { console.warn(`[TODO] do more COMMON_SPECIALS_REPLACE_MAP_BLANK_CANVAS (W: 083f629f91a9dd9dfbc3f49b0e102c24)`); }\nexport const COMMON_SPECIALS_REPLACE_MAP_BLANK_CANVAS: { [char: string]: string } = {\n    \" \": \"__space__\",\n    \"/\": \"__slash__\",\n    \"\\\\\\\\\": \"__2backslash__\", // not sure if this will work\n    \"\\\\\": \"__backslash__\",\n    \".\": \"__dot__\",\n    \"=\": \"__equals__\",\n    \"`\": \"__backtick__\",\n    \"'\": \"__quote__\",\n    \"\\\"\": \"__doublequote__\",\n    \"?\": \"__question__\",\n    \"$\": \"__dollar__\",\n    \"&\": \"__ampersand__\",\n    \":\": \"__colon__\",\n    \";\": \"__semicolon__\",\n    // do more of these for fuller support\n}\n\nexport function validateCommonBlankCanvasAppData({\n    BlankCanvasAppData,\n}: {\n    BlankCanvasAppData?: BlankCanvasAppData_V1,\n}): string[] {\n    const lc = `[${validateCommonBlankCanvasAppData.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n        if (!BlankCanvasAppData) { throw new Error(`BlankCanvasAppData required (E: 1059b99f79bb8e7ef8bdff4231895924)`); }\n        const errors: string[] = [];\n\n        const { name, uuid, classname, } = BlankCanvasAppData;\n\n        if (name) {\n            if (!name.match(BLANK_CANVAS_APP_NAME_REGEXP)) {\n                errors.push(`name must match regexp: ${BLANK_CANVAS_APP_NAME_REGEXP}`);\n            }\n        } else {\n            errors.push(`name required. (E: 926f32b8cb9857fc6402d073db2f3324)`);\n        }\n\n        if (uuid) {\n            if (!uuid.match(UUID_REGEXP)) {\n                errors.push(`uuid must match regexp: ${UUID_REGEXP}`);\n            }\n        } else {\n            errors.push(`uuid required. (E: 3e1da2476137dcb7565ad51702611224)`);\n        }\n\n        if (classname) {\n            if (!classname.match(CLASSNAME_REGEXP)) {\n                errors.push(`classname must match regexp: ${CLASSNAME_REGEXP}`);\n            }\n        }\n\n        return errors;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport async function validateCommonBlankCanvasAppIbGib({\n    BlankCanvasIbGib,\n}: {\n    BlankCanvasIbGib: BlankCanvasAppIbGib_V1,\n}): Promise<string[] | undefined> {\n    const lc = `[${validateCommonBlankCanvasAppIbGib.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 3f4ca397ebf2f09f0422145304c83b24)`); }\n        const intrinsicErrors: string[] = await validateIbGibIntrinsically({ ibGib: BlankCanvasIbGib }) ?? [];\n\n        if (!BlankCanvasIbGib.data) { throw new Error(`BlankCanvasIbGib.data required (E: 1bac4b40b07798f2eafbbe72f3c19224)`); }\n        const ibErrors: string[] = [];\n        let { BlankCanvasClassname, BlankCanvasName, BlankCanvasId } =\n            parseBlankCanvasAppIb({ BlankCanvasIb: BlankCanvasIbGib.ib });\n        if (!BlankCanvasClassname) { ibErrors.push(`BlankCanvasClassname required (E: f66599ce4a551c53356e7dc4217ccc24)`); }\n        if (!BlankCanvasName) { ibErrors.push(`BlankCanvasName required (E: 6df367875ed3398896719d46122ae524)`); }\n        if (!BlankCanvasId) { ibErrors.push(`BlankCanvasId required (E: bfe3f4cd2ff352efeee5d4dacc162e24)`); }\n\n        const dataErrors = validateCommonBlankCanvasAppData({ BlankCanvasAppData: BlankCanvasIbGib.data });\n\n        let result = [...(intrinsicErrors ?? []), ...(ibErrors ?? []), ...(dataErrors ?? [])];\n        if (result.length > 0) {\n            return result;\n        } else {\n            return undefined;\n        }\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport function getBlankCanvasAppIb({\n    BlankCanvasAppData,\n    classname,\n}: {\n    BlankCanvasAppData: BlankCanvasAppData_V1,\n    classname?: string,\n}): Ib {\n    const lc = `[${getBlankCanvasAppIb.name}]`;\n    try {\n        const validationErrors = validateCommonBlankCanvasAppData({ BlankCanvasAppData });\n        if (validationErrors.length > 0) { throw new Error(`invalid BlankCanvasAppData: ${validationErrors} (E: 3bf22fc28f79ccf8a158573377549824)`); }\n        if (classname) {\n            if (BlankCanvasAppData.classname && BlankCanvasAppData.classname !== classname) { throw new Error(`classname does not match BlankCanvasAppData.classname (E: 3a9c16a053acd665638c2a98e0daa924)`); }\n        } else {\n            classname = BlankCanvasAppData.classname;\n            if (!classname) { throw new Error(`classname required (E: d6becb28769b82d74b39d9c6e4078c24)`); }\n        }\n\n        // ad hoc validation here. should centralize witness classname validation\n\n        const { name, uuid } = BlankCanvasAppData;\n        return `app typing_gib ${classname} ${name} ${uuid}`;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\n/**\n * Current schema is 'app [TYPING_GIB_ATOM] [classname] [BlankCanvasName] [BlankCanvasId]'\n *\n * NOTE this is space-delimited\n */\nexport function parseBlankCanvasAppIb({\n    BlankCanvasIb,\n}: {\n    BlankCanvasIb: Ib,\n}): {\n    BlankCanvasClassname: string,\n    BlankCanvasName: string,\n    BlankCanvasId: string,\n} {\n    const lc = `[${parseBlankCanvasAppIb.name}]`;\n    try {\n        if (!BlankCanvasIb) { throw new Error(`BlankCanvasIb required (E: 4708f384e18e429a6a3c664e154b0c24)`); }\n\n        const pieces = BlankCanvasIb.split(' ');\n\n        return {\n            BlankCanvasClassname: pieces[2],\n            BlankCanvasName: pieces[3],\n            BlankCanvasId: pieces[4],\n        };\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\n/**\n * stubbed validation function. there is also validation\n * when building the arg info objects.\n *\n * @returns error string if found, otherwise null\n *\n * @param argInfos\n */\nexport function validateArgInfos({ argInfos }: { argInfos: RCLIArgInfo[] }): string | undefined {\n    const lc = `[${validateArgInfos.name}]`;\n    let validationErrorIfAny: string | undefined = undefined;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 8f6f3df4b06b2b1838fcb90f2afe8f24)`); }\n        // if (!argInfos || argInfos.length === 0) { throw new Error(`argInfos required. (E: fa4599a1181ad85b7e155d3bbec89c24)`); }\n\n        // const hasInit = argInfos.some(x => x.name === PARAM_INFO_INIT.name);\n        // const hasInMemory = argInfos.some(x => x.name === PARAM_INFO_IN_MEMORY.name);\n\n        // if (hasInit && hasInMemory) {\n        //     throw new Error(`cannot have both init and in-memory args (E: 61ac81a0ab222c6f4f0c5ddcf3e1d624)`);\n        // }\n\n        // // todo: flesh out argInfos validation\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        validationErrorIfAny = error.message;\n    } finally {\n        if (logalot) { console.log(`\\n${lc} complete.`); }\n        return validationErrorIfAny;\n    }\n}\n\nexport function getPrompt({\n    id,\n    promptTemplate = DEFAULT_PROMPT_TEMPLATE,\n}: {\n    /**\n     * identifier, not necessarily a uuid.\n     * so, e.g., a username or name of a witness\n     */\n    id: string\n    /**\n     * should have $id where the id will go.\n     *\n     * really i should be incorporating lex-gib here.\n     */\n    promptTemplate?: string,\n}): string {\n    promptTemplate ??= DEFAULT_PROMPT_TEMPLATE;\n    let result: string;\n    if (!!id && promptTemplate.includes('$id')) {\n        result = promptTemplate.replace('$id', id);\n    } else {\n        result = id || '[?]>';\n    }\n    return result;\n}\n\nexport class BlankCanvasAppFormBuilder extends WitnessFormBuilder {\n    protected lc: string = `[${BlankCanvasAppFormBuilder.name}]`;\n\n    constructor() {\n        super();\n        this.what = 'blank-canvas';\n    }\n\n    // exampleSetting({\n    //     of,\n    //     required,\n    // }: {\n    //     of: string,\n    //     required?: boolean,\n    // }): BlankCanvasAppFormBuilder {\n    //     this.addItem({\n    //         // BlankCanvas.data.exampleSetting\n    //         name: \"exampleSetting\",\n    //         description: `example description`,\n    //         label: \"Example Label\",\n    //         regexp: EXAMPLE_REGEXP,\n    //         regexpErrorMsg: EXAMPLE_REGEXP_DESC,\n    //         dataType: 'textarea',\n    //         value: of,\n    //         required,\n    //     });\n    //     return this;\n    // }\n\n}\n\n/**\n * main priority is to ensure that there are no duplicate param infos.\n *\n * use this function at the start of application in order to check\n * that you have built a good parameter configuration.\n */\nexport function validateParamInfos({\n    paramInfos,\n}: {\n    paramInfos: RCLIParamInfo[],\n}): string[] {\n    const lc = `[${validateParamInfos.name}]`;\n    const errors: string[] = [];\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 476d92b192df5d06e81713ed99d2b924)`); }\n\n        // verify no duplicate param identifiers\n        const identifiers: string[] = [];\n        const doIdentifier = (identifier: string) => {\n            identifier = identifier.toLowerCase();\n            if (identifiers.includes(identifier)) {\n                const paramInfosWithDuplicates = paramInfos.filter(x => x.name === identifier || x.synonyms?.includes(identifier));\n                errors.push(`${lc} identifier duplicate found: ${identifier}. paramInfosWithDuplicates: ${pretty(paramInfosWithDuplicates)} (E: 0df8d8da7055dbff18522213dd9d1424)`);\n            } else {\n                identifiers.push(identifier);\n            }\n        }\n        paramInfos.forEach(paramInfo => {\n            doIdentifier(paramInfo.name);\n            (paramInfo.synonyms ?? []).forEach(x => doIdentifier(x));\n        });\n\n        return errors;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * creates an RCLI comment ibgib, returning the transform result,\n * optionally saving it in a given {@link space}.\n */\nexport async function createRequestCommentIbGib({\n    args,\n    interpretedArgInfos,\n    addlMetadataText,\n    saveInSpace,\n    space,\n}: {\n    /**\n     * As close to the raw args as we can get.\n     */\n    args: string[];\n    /**\n     * interpreted infos for args\n     */\n    interpretedArgInfos: RCLIArgInfo[];\n    /**\n     * Optional metadata string to be included in the comment's ib.\n     * Should be underscore-delimited but not a hard rule atow.\n     *\n     * @example \"comment thisisacomm here_is_addl_metadata\"\n     */\n    addlMetadataText?: string;\n    /**\n     * If true, will save the ibgibs created in the given {@link space}.\n     */\n    saveInSpace?: boolean,\n    /**\n     * If {@link saveInSpace}, all ibgibs created in this function will be stored in\n     * this space.\n     */\n    space?: IbGibSpaceAny,\n}): Promise<TransformResult<RequestCommentIbGib_V1>> {\n    const lc = `[${createRequestCommentIbGib.name}]`;\n\n    if (logalot) { console.log(`${lc} starting...`); }\n    try {\n        if (!args) { throw new Error(`args required (E: b568890319dbea91e77180f4adf8df24)`); }\n        if (args.length === 0) { throw new Error(`args.length must be at least 1 (E: af2c93ebda940d96bf8e904831904c24)`); }\n        if (!interpretedArgInfos) { throw new Error(`interpretedArgInfos required (E: a3b1030a8bb64fc9e431d8b6bd9dd224)`); }\n        if (!interpretedArgInfos.length) { throw new Error(`interpretedArgInfos.length must be at least 1 (E: 994254208957873a1700efe23ee77b24)`); }\n\n        // if any of the args have spaces, then we want to quote them\n        // const text = args.join(' ');\n        const text = getOriginalCmdTextFromStrippedArgs({ args });\n\n        const data: RequestCommentData_V1 = {\n            uuid: await getUUID(),\n            text,\n            args,\n            interpretedArgInfos,\n            textTimestamp: getTimestamp(),\n        };\n\n        // create an ibgib with the filename and ext\n        const opts: any = {\n            parentIbGib: factory.primitive({ ib: 'comment' }),\n            ib: getRequestCommentIb({ rcliCommentData: data, addlMetadataText }),\n            data,\n            dna: true,\n            tjp: { uuid: true, timestamp: true },\n            nCounter: true,\n        };\n\n        // this makes it more difficult to share/sync ibgibs...\n        // if (this.addr) { opts.rel8ns = { 'comment on': [this.addr] }; }\n\n        if (logalot) { console.log(`${lc} opts: ${pretty(opts)}`); }\n        const resCommentIbGib = await factory.firstGen(opts) as TransformResult<RequestCommentIbGib_V1>;\n\n        if (saveInSpace) {\n            if (!space) { throw new Error(`space required if saveInSpace is truthy (E: bc87e2606d133c164f74d41856788124)`); }\n            await persistTransformResult({ resTransform: resCommentIbGib, space });\n        }\n\n        return resCommentIbGib;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\nexport function getOriginalCmdTextFromStrippedArgs({\n    args\n}: {\n    args: string[],\n}): string {\n    const lc = `[${getOriginalCmdTextFromStrippedArgs.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 61dbff42fd24820c7edc05d4d3078924)`); }\n\n        const adjustedArgs: string[] = [];\n        for (let i = 0; i < args.length; i++) {\n            const arg = args[i];\n            if (arg.includes(' ')) {\n                // includes space so we need to adjust\n\n                /**\n                 * helper fn to wrap\n                 */\n                const fnWrapInQuotesIfNeeded = (str: string) => {\n                    str = str.concat();\n                    let prefix = '';\n                    if (str.startsWith('--')) {\n                        prefix = '--';\n                        str = str.substring(2)\n                    } else if (str.startsWith(DEFAULT_COMMAND_ESCAPE_STRING)) {\n                        prefix = DEFAULT_COMMAND_ESCAPE_STRING;\n                        str = str.substring(DEFAULT_COMMAND_ESCAPE_STRING.length);\n                    }\n                    if (str.includes(' ')) {\n                        // wrap str in single or double quotes\n                        if (str.startsWith('\"') || str.startsWith(\"'\")) {\n                            str = stripQuotes(str);\n                        }\n                        if (str.includes(\"'\") && str.includes('\"')) {\n                            throw new Error(`edge case detected. value (${str}) includes both single and double quote. you win. (E: c1508b3a7cd8130153dcbcbf5601e724)`);\n                        } else if (str.includes('\"')) {\n                            // includes double quotes, so wrap in single quotes\n                            str = `'${str}'`;\n                        } else {\n                            // includes single quotes or none at all, so wrap in\n                            // double quotes\n                            str = `\"${str}\"`;\n                        }\n                    }\n                    return prefix ? prefix + str : str;\n                }\n\n                if (arg.includes('=')) {\n                    if (arg.indexOf('=') !== arg.lastIndexOf('=')) {\n                        throw new Error(`more than one equals sign (=) found. these ='s in arg must only be to separate key=value. Neither key nor value can contain an equals sign. (E: b0dc97a5f19454da19284b3e811df824)`);\n                    }\n\n                    // adjust with quotes around value\n                    let [key, value] = arg.split('=');\n                    value = fnWrapInQuotesIfNeeded(value);\n                    if (key.includes(' ')) { throw new Error(`arg key (${key}) cannot contain a space. (E: 2179ad43294dee4e038da9085c24d524)`); }\n                    adjustedArgs.push(`${key}=${value}`);\n                } else {\n                    // just wrap the entire arg\n                    adjustedArgs.push(fnWrapInQuotesIfNeeded(arg));\n                }\n            } else {\n                // no space in arg so no need to adjust\n                adjustedArgs.push(arg.concat());\n            }\n        }\n        const result = adjustedArgs.join(' ');\n        if (logalot) { console.log(`${lc} result: ${result} (I: 838d1d5c7646ef4ccc0c4521984d0b24)`); }\n        return result;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n\nexport function validateCommonRequestCommentData({\n    rcliCommentData,\n}: {\n    rcliCommentData?: RequestCommentData_V1,\n}): string[] {\n    const lc = `[${validateCommonRequestCommentData.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting...`); }\n        if (!rcliCommentData) { throw new Error(`rcliCommentData required (E: 19bf1c3ac64de8bf1a0dd5cdf24aa524)`); }\n        const errors: string[] = [];\n        const {\n            uuid,\n            text,\n            args,\n            interpretedArgInfos,\n        } = rcliCommentData;\n\n        if (uuid) {\n            if (!uuid.match(UUID_REGEXP)) {\n                errors.push(`uuid must match regexp: ${UUID_REGEXP}`);\n            }\n        } else {\n            errors.push(`uuid required.`);\n        }\n\n        if (!text) { errors.push(`text required`); }\n        if (!args) { errors.push(`args required`); }\n        if (!interpretedArgInfos) { errors.push(`interpretedArgInfos required`); }\n\n        return errors;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport async function validateCommonRequestCommentIbGib({\n    rcliCommentIbGib,\n}: {\n    rcliCommentIbGib: RequestCommentIbGib_V1,\n}): Promise<string[] | undefined> {\n    const lc = `[${validateCommonRequestCommentIbGib.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: ce94adde144fb23327ace37f3cf3b724)`); }\n        const intrinsicErrors: string[] = await validateIbGibIntrinsically({ ibGib: rcliCommentIbGib }) ?? [];\n\n        if (!rcliCommentIbGib.data) { throw new Error(`rcliCommentIbGib.data required (E: 20e0d6c75a464da4ac04e238231d8724)`); }\n        const ibErrors: string[] = [];\n        let { text } = parseRequestCommentIb({ rcliCommentIb: rcliCommentIbGib.ib });\n        if (!text) { ibErrors.push(`ib text required (E: b25ccb5f2b69971c83741e85cba39724)`); }\n\n        const dataErrors = validateCommonRequestCommentData({ rcliCommentData: rcliCommentIbGib.data });\n\n        let result = [...(intrinsicErrors ?? []), ...(ibErrors ?? []), ...(dataErrors ?? [])];\n        if (result.length > 0) {\n            return result;\n        } else {\n            return undefined;\n        }\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\nexport function getRequestCommentIb({\n    rcliCommentData,\n    addlMetadataText,\n}: {\n    rcliCommentData: RequestCommentData_V1,\n    addlMetadataText?: string,\n}): Ib {\n    const lc = `[${getRequestCommentIb.name}]`;\n    try {\n        const validationErrors = validateCommonRequestCommentData({ rcliCommentData });\n        if (validationErrors.length > 0) { throw new Error(`invalid rcliCommentData: ${validationErrors} (E: 39a94de70943256271ca7ccbb4d9ce24)`); }\n        if (addlMetadataText?.includes(' ')) { throw new Error(`addlMetadataText should not include a space, as this is a delimiter in the rcliCommentIb (E: 44a94ab6b474acabe785d1573d1df224)`); }\n\n        const saferText = getSaferSubstring({\n            text: rcliCommentData.text,\n            keepLiterals: [\"-\", \".\"],\n            length: 64,\n            replaceMap: {\n                ...COMMON_SPECIALS_REPLACE_MAP_BLANK_CANVAS,\n            }\n        });\n        if (saferText.includes(' ')) { throw new Error(`saferText should not include a space, as this is a delimiter in the rcliCommentIb (E: e90757d4f2162e39c82eb7fce38a9d24)`); }\n\n        return addlMetadataText ?\n            `comment ${saferText} ${addlMetadataText}` :\n            `comment ${saferText}`;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\n/**\n * Current schema is `comment ${saferText} ${addlMetadataText}`;\n *\n * NOTE this is space-delimited\n */\nexport function parseRequestCommentIb({\n    rcliCommentIb,\n}: {\n    rcliCommentIb: Ib,\n}): {\n    text: string,\n    addlMetadataText?: string,\n} {\n    const lc = `[${parseRequestCommentIb.name}]`;\n    try {\n        if (!rcliCommentIb) { throw new Error(`rcliCommentIb required (E: df06f2c150de3e82a90b8ba3c5eea224)`); }\n\n        const [_, text, addlMetadataText] = rcliCommentIb.split(' ');\n\n        return {\n            text,\n            addlMetadataText,\n        };\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n}\n\nexport function isRequestComment({ ibGib }: { ibGib: IbGib_V1 }): boolean {\n    const lc = `[${isRequestComment.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 1c8b1cc716b37601e76edd73d690ac24)`); }\n\n        if (!isComment({ ibGib })) { return false; /* <<<< returns early */ }\n\n        let { data } = ibGib;\n        if (!data) { return false; /* <<<< returns early */ }\n\n        let castedData = data as RequestCommentData_V1;\n        if ((castedData.args ?? []).length === 0) {\n            return false; /* <<<< returns early */\n        }\n\n        if ((castedData.interpretedArgInfos ?? []).length === 0) {\n            return false; /* <<<< returns early */\n        }\n\n        return true;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * utility to strip quotes in an unknown string format. the incoming str may be\n * a key=value, or empty or no quotes, or double-quoted, or single-quoted\n * warning, this is duplicated here and in @ibgib/ibgib package (rcli-helper?)\n * @param str is the string to strip\n * @returns original str if no quotes found, else  strips entire str or if has key=value format this will strip the value of quotes.\n */\nexport function stripQuotes(str: string): string {\n    const lc = `[${stripQuotes.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 544d6f5b32d2a880b33692da1a201724)`); }\n        let s = str.concat();\n        if (!s.includes(\"'\") && !s.includes('\"')) {\n            // doesn't contain quotes\n            return s; /* <<<< returns early */\n        }\n        if (s.includes('=')) {\n            let [key, value] = s.split('=');\n            if (value.startsWith('\"') && !value.endsWith('\"')) {\n                throw new Error(`invalid string. value starts with \" but doesn't end with it (E: f710f3c9d99dc789abea460d61a59924)`);\n            } else if (value.startsWith(\"'\") && !value.endsWith(\"'\")) {\n                throw new Error(`invalid string. value starts with ' but doesn't end with it (E: 924bd700afa2e61fcf284578f944a624)`);\n            } else {\n                // strip the right side value\n                value = value.substring(1);\n                value = value.substring(0, value.length - 1);\n            }\n            s = `${key}=${value}`;\n        } else {\n            if (s.startsWith('\"') && !s.endsWith('\"')) {\n                throw new Error(`invalid string. starts with \" but doesn't end with it (E: 9778a4bba892d4cfd62f181590f7a724)`);\n            } else if (s.startsWith(\"'\") && !s.endsWith(\"'\")) {\n                throw new Error(`invalid string. starts with ' but doesn't end with it (E: ec1fcea648641f105b025424aabbd924)`);\n            } else {\n                // strip the right side value\n                s = s.substring(1);\n                s = s.substring(0, s.length - 1);\n            }\n        }\n        return s;\n\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n", "import { extractErrorMsg, getTimestampInTicks, getUUID, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\n// import { PARAM_INFO_OUTPUT_PATH } from \"@ibgib/helper-gib/dist/rcli/rcli-constants.mjs\";\nimport { RCLIArgInfo, RCLIArgType, RCLIParamInfo, } from \"@ibgib/helper-gib/dist/rcli/rcli-types.mjs\";\nimport { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';\nimport { isComment } from '@ibgib/core-gib/dist/common/comment/comment-helper.mjs';\n\nimport { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';\nimport { ExpectPathType, } from './blank-canvas-types.mjs';\nimport { DEFAULT_COMMAND_ESCAPE_STRING } from './blank-canvas-constants.mjs';\nimport { stripQuotes } from './blank-canvas-helper.mjs';\nimport { ID_PRIMARY_AGENT_CHAT_LOG } from '../../../ui/shell/shell-constants.mjs';\n// import {\n//     RCLI_DEFAULT_COMMAND_ESCAPE_STRING, RCLI_MAX_ESCAPE_STRING_LENGTH,\n//     PARAM_INFO_INIT, PARAM_INFO_IN_MEMORY,\n//     PARAM_INFO_SPACE_ID, PARAM_INFO_SPACE_NAME,\n//     DEFAULT_PROMPT_TEMPLATE,\n//     RCLI_DEFAULT_OUTPUT_PATH,\n//     PARAM_INFO_SRC_ADDR,\n//     DEFAULT_LOCAL_USER_SPACE_VAR,\n//     PARAM_INFO_OUTER_SPACE_ID,\n//     PARAM_INFO_OUTER_SPACE_NAME,\n// } from \"./rcli-constants.mjs\";\n\n\n/**\n * used in verbose logging\n */\nconst logalot = GLOBAL_LOG_A_LOT;\n\n\n/**\n * helper that checks a given `relOrAbsPath` against expectations per\n * `expectType`.\n *\n * @returns true if path points to something as given with `expectType`, else false.\n */\nexport function pathIsAsExpected({\n    relOrAbsPath,\n    expectType,\n    throwIfNotExpected,\n    warnIfNotExpected,\n    mkdirIfNotExist,\n}: {\n    /**\n     * path to check\n     */\n    relOrAbsPath: string,\n    /**\n     * expectations about path. is it a file, is it a folder, does it exist, is it undefined\n     */\n    expectType: ExpectPathType,\n    /**\n     * side effect on if does not meet expectation\n     */\n    throwIfNotExpected?: boolean,\n    /**\n     * side effect on if does not meet expectation\n     */\n    warnIfNotExpected?: boolean,\n    /**\n     * if true and expectType is directory, then this will mkdir before deciding if expected.\n     */\n    mkdirIfNotExist?: boolean,\n}): boolean {\n    const lc = `[${pathIsAsExpected.name}]`;\n    try {\n        throw new Error(`not implemented (E: cc4361fe749f73bb068030247e15ea24)`);\n        // if (logalot) { console.log(`${lc} starting... (I: e20eb5de572d0d0a68b3b182dbcc4624)`); }\n\n        // const stat = statSync(relOrAbsPath, { throwIfNoEntry: false });\n        // if (stat === undefined) {\n        //     if (expectType === undefined) {\n        //         // good, it's as expected\n        //         return true; /* <<<< returns early */\n        //     } else {\n        //         if (expectType === 'directory' && mkdirIfNotExist) {\n        //             mkdirSync(relOrAbsPath);\n        //             const statTryAgain = statSync(relOrAbsPath, { throwIfNoEntry: false });\n        //             if (statTryAgain?.isDirectory()) {\n        //                 return true; /* <<<< returns early */\n        //             }\n        //         }\n        //         // no existing file or folder of this path? A relOrAbsPath should\n        //         const emsg = `relOrAbsPath not found. relOrAbsPath was expected as ${expectType}. initialize relOrAbsPath before proceeding. relOrAbsPath from args: ${relOrAbsPath}`;\n        //         if (throwIfNotExpected) {\n        //             throw new Error(`${emsg} (E: 4ab864c77045c025017a2e829045b424)`);\n        //         } else if (warnIfNotExpected) {\n        //             console.warn(`${lc} ${emsg} (W: 616009ed5b0d63cf6b78389ec60c8a24)`);\n        //         }\n        //         return false; /* <<<< returns early */\n        //     }\n        // } else if (expectType === 'exists') {\n        //     // good, it's as expected\n        //     return true; /* <<<< returns early */\n        // } else if (stat.isFile()) {\n        //     if (expectType === 'file') {\n        //         // good, it's as expected\n        //         return true; /* <<<< returns early */\n        //     } else {\n        //         const emsg = `relOrAbsPath found pointed to a file. relOrAbsPath was expected as ${expectType}. initialize relOrAbsPath before proceeding. relOrAbsPath from args: ${relOrAbsPath}`;\n        //         if (throwIfNotExpected) {\n        //             throw new Error(`${emsg} (E: 9fb8c885cd4ecaee0bf8a43eea8e3424)`);\n        //         } else if (warnIfNotExpected) {\n        //             console.warn(`${lc} ${emsg} (W: 398385b626adc55f2c0a7928ca9b3e24)`);\n        //         }\n        //         return false; /* <<<< returns early */\n        //     }\n        // } else if (stat.isDirectory()) {\n        //     if (expectType === 'directory') {\n        //         // good, it's as expected\n        //         return true; /* <<<< returns early */\n        //     } else if (expectType === 'empty-directory') {\n        //         // it's a directory, but we need to ensure there are no children\n        //         const children = readdirSync(relOrAbsPath);\n        //         return children.length === 0; /* <<<< returns early */\n        //     } else {\n        //         const emsg = `relOrAbsPath found pointed to a directory. relOrAbsPath was expected as ${expectType}. initialize relOrAbsPath before proceeding. relOrAbsPath from args: ${relOrAbsPath}`;\n        //         if (throwIfNotExpected) {\n        //             throw new Error(`${emsg} (E: 2532ecc8c6d363e27a4e890361a03d24)`);\n        //         } else if (warnIfNotExpected) {\n        //             console.warn(`${lc} ${emsg} (W: 4141696d491aa585aeb2d03693f22d24)`);\n        //         }\n        //         return false; /* <<<< returns early */\n        //     }\n        // } else {\n        //     throw new Error(`(UNEXPECTED) unknown stat from statSync call? (E: 3e64675d739e41b56c00a2763439f424)`);\n        // }\n\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * atow this is for an output file\n */\nexport async function extractArg_outputPath({\n    argInfos,\n    doIfExists = 'throw',\n    createUniqueSubdirIfExists,\n    defaultPathIfNotFound,\n    throwIfNotFound,\n}: {\n    argInfos: RCLIArgInfo<RCLIArgType>[],\n    doIfExists: 'warn' | 'throw' | 'nada',\n    createUniqueSubdirIfExists: boolean,\n    defaultPathIfNotFound?: string,\n    throwIfNotFound?: boolean,\n}): Promise<string> {\n    const lc = `[${extractArg_outputPath.name}]`;\n    try {\n        throw new Error(`not implemented (E: 32382e33b56e2f7c361ed8cf182e8d24)`);\n        // if (logalot) { console.log(`${lc} starting... (I: 24506dca24df15046ef27ce11ce32b24)`); }\n\n        // let relOrAbsPath: string;\n        // if (argInfos.some(x => x.name === PARAM_INFO_OUTPUT_PATH.name)) {\n        //     const argInfo = argInfos.filter(x => x.name === PARAM_INFO_OUTPUT_PATH.name)[0];\n        //     if (!argInfo.value) {\n        //         throw new Error(`(UNEXPECTED) output path arg found but value is falsy? (E: f18f86120133830cfa91f0cfba87fa24)`);\n        //     }\n        //     relOrAbsPath = argInfo.value! as string;\n        // } else if (throwIfNotFound) {\n        //     throw new Error(`output path is required. PARAM_INFO_OUTPUT_PATH: ${pretty(PARAM_INFO_OUTPUT_PATH)} (E: 279f7700cc922add449f0a73edf2f624)`);\n        // } else {\n        //     defaultPathIfNotFound ??= RCLI_DEFAULT_OUTPUT_PATH;\n        //     if (defaultPathIfNotFound) {\n        //         // only warn if we're initializing without specifying the path explicitly.\n        //         if (argInfos.some(x => x.name === PARAM_INFO_INIT.name)) {\n        //             console.warn(`no output path arg provided. using default path: ${defaultPathIfNotFound} (E: 874f0d53f1bfd25e979e132d9eb95b24)`);\n        //         }\n        //     } else {\n        //         console.warn(`no output path arg provided and defaultPathIfNotFound is empty string. (E: c32d6277382f65136eb9b5d6fec4c324)`);\n        //     }\n        //     relOrAbsPath = defaultPathIfNotFound;\n        // }\n\n        // const stat = statSync(relOrAbsPath, { throwIfNoEntry: false });\n        // if (stat === undefined) {\n        //     // no existing file or folder of this path, so we're good\n        // } else {\n        //     switch (doIfExists) {\n        //         case 'warn':\n        //             if (createUniqueSubdirIfExists) {\n        //                 console.warn(`${lc}[WARNING] output path already exists. creating unique sub-directory. (W: c7ed5b7ef3cf8c559a36d91dada94224)`);\n        //             } else {\n        //                 console.warn(`${lc}[WARNING] output path already exists. (W: b979d4fa0f98c1c61615097d77d3bc24)`);\n        //             }\n        //             break;\n        //         case 'throw':\n        //             throw new Error(`data output path already exists. (E: 568ec79cb7b224f8663948363ac02f24`);\n        //         case 'nada':\n        //             if (logalot) { console.log(`${lc} doIfExists === 'nada' (I: 639d4e477b5b4511dcf3b5cffa4a4d24)`); }\n        //             break;\n        //         default:\n        //             throw new Error(`(UNEXPECTED) unknown value for doIfExists: ${doIfExists}? (E: 67bcd5ef4aff1c638463ce6daf24f424)`);\n        //     }\n        //     const getSubdirName = async () => {\n        //         return getTimestampInTicks() + (await getUUID()).slice(0, 6);\n        //     }\n        //     if (stat.isFile()) {\n        //         if (createUniqueSubdirIfExists) {\n        //             // create subdir in relOrAbsPath but use the same filename\n        //             const subdirName = await getSubdirName();\n        //             const filenameWithExt = pathUtils.basename(relOrAbsPath);\n        //             const pathWithoutFilename = pathUtils.parse(relOrAbsPath).dir;\n        //             relOrAbsPath = pathUtils.join(pathWithoutFilename, subdirName, filenameWithExt);\n        //         } else {\n        //             // relOrAbsPath already set to existing file but create unique\n        //             // dir didn't happen, so overwrite\n        //             throw new Error(`overwriting existing outputPath file ain't happening yet (E: 1e072594b24c7324992fb48f3f6a9224)`);\n        //         }\n        //     } else if (stat.isDirectory()) {\n        //         if (createUniqueSubdirIfExists) {\n        //             const subdirName = await getSubdirName();\n        //             relOrAbsPath = pathUtils.join(relOrAbsPath, subdirName);\n        //         } else {\n        //             // relOrAbsPath already set to existing dir\n        //         }\n        //     }\n        // }\n\n        // // add file extension only if we're encrypting and it isn't already there\n        // // const isEncrypt = argInfos.some(x => x.name === PARAM_INFO_ENCRYPT.name);\n        // // if (isEncrypt && !relOrAbsPath.endsWith(ENCRYPTED_OUTPUT_FILE_EXT)) {\n        // //     console.log(`${lc} adding file extension .${ENCRYPTED_OUTPUT_FILE_EXT}`);\n        // //     relOrAbsPath += (relOrAbsPath.endsWith('.') ? ENCRYPTED_OUTPUT_FILE_EXT : `.${ENCRYPTED_OUTPUT_FILE_EXT}`);\n        // // }\n\n        // return relOrAbsPath;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n\n/**\n * In blank-gib (@ibgib/blank-gib am I making this a package?), this is in the\n * rcli-comment helper. in this hack of a port from rcli (@ibgib/ibgib), i'm\n * just shoving this here.\n *\n * @returns true if it finds the expected contract of a request comment, else false.\n */\nexport function isRequestComment({ ibGib }: { ibGib: IbGib_V1 }): boolean {\n    const lc = `[${isRequestComment.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 2c2b47ce3b58a60594af650475b5b124)`); }\n\n        if (!isComment({ ibGib })) { return false; /* <<<< returns early */ }\n\n        let { data } = ibGib;\n        if (!data) { return false; /* <<<< returns early */ }\n\n        // let castedData = data as RCLICommentData_V1;\n        let castedData = data as any;\n        if ((castedData.args ?? []).length === 0) {\n            return false; /* <<<< returns early */\n        }\n\n        if ((castedData.interpretedArgInfos ?? []).length === 0) {\n            return false; /* <<<< returns early */\n        }\n\n        return true;\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\nexport function parseCommandRawTextIntoArgs({\n    rawText,\n    validCommandIdentifiers,\n    logErrors = false,\n}: {\n    rawText: string,\n    validCommandIdentifiers: string[],\n    logErrors?: boolean,\n}): {\n    /**\n     * true if the incoming `rawText` was a valid args string, i.e., represented\n     * something a user should type into a command line.\n     */\n    validArgsString: boolean,\n    /**\n     * firstArg should be a command.\n     */\n    cmd_ie_firstArgSansPrefix?: string,\n    /**\n     * hopefully a recreation of what would get passed to process.vargs\n     */\n    args?: string[],\n    validationErrorMsg?: string,\n} {\n    const lc = `[${parseCommandRawTextIntoArgs.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 21f7a3bba0e4c339abcaa7bb7b62cf24)`); }\n\n        if (rawText === '') { throw new Error(`rawText is empty string (E: 89ce8662adc84e5cc1620538e0c7a324)`); }\n\n        /**\n         * we will mutate this, splicing off/combining as we go from the first arg\n         */\n        const mutatingNaiveSpaceDelimited = rawText.split(' ');\n\n        // first do the first arg, which must be a valid command identifier with\n        // either a command prefix or a regular arg prefix\n        const doubleDashPrefix = '--';\n        const commandPrefix = DEFAULT_COMMAND_ESCAPE_STRING;\n        const rawFirstArg = mutatingNaiveSpaceDelimited.splice(0, 1)[0];\n        /**\n         * first arg must be the command\n         */\n        let cmd_ie_firstArgSansPrefix: string;\n        if (rawFirstArg.startsWith(commandPrefix)) {\n            cmd_ie_firstArgSansPrefix = rawFirstArg.substring(commandPrefix.length);\n        } else if (rawFirstArg.startsWith(doubleDashPrefix)) {\n            cmd_ie_firstArgSansPrefix = rawFirstArg.substring(doubleDashPrefix.length);\n        } else {\n            throw new Error(`first arg must be a command without spaces that starts with either the command prefix (${commandPrefix}) or regular arg prefix (${doubleDashPrefix}) (E: 77a878c3c6a9c413238eb75c55e7d424)`);\n        }\n\n        if (!validCommandIdentifiers.includes(cmd_ie_firstArgSansPrefix)) {\n            throw new Error(`first arg (${cmd_ie_firstArgSansPrefix}) must be a valid command. validCommandIdentifiers: ${validCommandIdentifiers} (E: b1a14dac1b0665860c8234a5fc752f24)`);\n        }\n\n        // if we have nothing left, then we have a bare command and we're done\n        if (mutatingNaiveSpaceDelimited.length === 0) {\n            return {\n                validArgsString: true,\n                cmd_ie_firstArgSansPrefix,\n                args: [`--${cmd_ie_firstArgSansPrefix}`], // args always contains double-dash\n            }; /* <<<< returns early */\n        }\n\n        // we have at least one additional arg\n        /**\n         * once we have a double-dash arg (not the command), we cannot have a bare arg.\n         */\n        let doubleDashFound = false;\n        // const resArgs: string[] = [rawFirstArg.startsWith(doubleDashPrefix) ? rawFirstArg : `--${rawFirstArg}`]; // args always contains double-dash\n        const resArgs: string[] = [`--${cmd_ie_firstArgSansPrefix}`]; // args always contains double-dash\n        let tmpArgWhileBuilding: string = '';\n        for (let i = 0; i < mutatingNaiveSpaceDelimited.length; i++) {\n            const textPiece = mutatingNaiveSpaceDelimited[i];\n            if (textPiece.startsWith(doubleDashPrefix)) {\n                doubleDashFound = true;\n                if (textPiece === doubleDashPrefix) { throw new Error(`invalid rawText. textPiece is just -- with no additional text, which is invalid. flags should be --my-flag (no spaces) and args with values should be like --key=value or --key=\"value here\" or --key='value here' (E: 8a7962b6f8c3e120cad8f192e1ae6f24)`); }\n                if (tmpArgWhileBuilding.length > 0) {\n                    // we have been building an arg and have hit a new argPrefix\n                    // which means our previous building is done so flush it to\n                    // the remainderArgs. this is guaranteed not to be a\n                    // quote-surrounded value because that is flushed elsewhere.\n                    // (so we don't need to strip the quotes at this point)\n                    resArgs.push(tmpArgWhileBuilding.concat());\n                    tmpArgWhileBuilding = '';\n                }\n                if (textPiece.includes('=')) {\n                    // --identifier=value\n                    // --identifier='value\n                    // --identifier=\"value\n                    // --identifier=\"value\"\n                    // --identifier='value'\n                    if (textPiece.endsWith('\"') || textPiece.endsWith(\"'\")) {\n                        // --identifier=\"value\"\n                        // --identifier='value'\n                        resArgs.push(stripQuotes(textPiece.concat()));\n                        tmpArgWhileBuilding = '';\n                    } else {\n                        // --identifier=value\n                        // --identifier='value\n                        // --identifier=\"value\n                        tmpArgWhileBuilding = textPiece.concat();\n                    }\n                } else {\n                    // flag arg needs no more processing, e.g., --my-flag\n                    tmpArgWhileBuilding = textPiece.concat();\n                }\n            } else if (textPiece.startsWith(\"'\") || textPiece.startsWith('\"')) {\n                if (doubleDashFound) { throw new Error(`invalid (edge case?) rawText. textPiece starts with a quote to indicate a bare arg, but bare args can only come immediately after the command. IOW You can't have a --key=value arg and then a bare arg. (E: b01dd628b299fbad42047064957df424)`); }\n                if (textPiece.endsWith(\"'\") || textPiece.endsWith('\"')) {\n                    // starts and ends with quote, so we have an unnecessarily quoted value\n                    if (tmpArgWhileBuilding) {\n                        throw new Error(`invalid (edge case?) rawText. testPiece starts and ends with quote which is only expected if we were doing a bare arg immediately after the cmd. but tmpArgWhileBuilding is truthy, which means we have a weird quote edge case. (E: 4972edcf2c4ab1fbf63e954136d52224)`);\n                    } else {\n                        resArgs.push(stripQuotes(textPiece.concat()));\n                    }\n                } else {\n                    // start of single or double quote entry\n                    if (tmpArgWhileBuilding) {\n                        // we have already started a tmp arg meaning found one with a quote and now we have another one started...so throw\n                        throw new Error(`invalid (edge case?) rawText. While parsing the  (E: e281aed3e9e91ff8882e9647c166fb24)`);\n                    } else {\n                        // start of a tmp\n                        tmpArgWhileBuilding = textPiece.concat();\n                    }\n                }\n            } else if (textPiece.endsWith(\"'\") || textPiece.endsWith('\"')) {\n                if (textPiece.length === 1) {\n                    // textPiece is only a quote\n                    throw new Error(`invalid (edge case?) rawText. textPiece is only a single or double quote. does the text inside the quotes end in a space? (E: 2a4134a410852ec762055f35e3a49524)`);\n                }\n                // end of single or double quote entry with guaranteed text of at least length 1\n                if (tmpArgWhileBuilding) {\n\n                    // complete tmp arg\n                    tmpArgWhileBuilding += ` ${textPiece}`; // add the space + textPiece\n\n                    // at this point, tmpArgWhileBuilding has completed a quoted\n                    // segment. but this might be a bare arg or a name=value arg\n                    // and we need to strip the quotes\n\n                    if (tmpArgWhileBuilding.includes('=')) {\n                        if (logalot) { console.log(`${lc} key=value arg closed with quotes (I: 2398c644afd78c833fba2274a4ef1424)`); }\n                        const subPieces = tmpArgWhileBuilding.split('=');\n                        if (subPieces.length !== 2) { throw new Error(`textPiece has more than one equals sign? (=) (E: 333acd4130763e7c09ea57285bf55d24)`); }\n                        let [left, right] = subPieces;\n                        if (!right.startsWith('\"') && !right.startsWith(\"'\")) { throw new Error(`we had a close quote in a --key=value arg but the value did not start with a quote? (E: 1cbdf326c56566a497b4dedb329e5624)`); }\n                        tmpArgWhileBuilding = `${left}=${stripQuotes(right)}`;\n                    } else {\n                        if (logalot) { console.log(`${lc} bare arg closed with quotes (I: 602aeba88cc3631ebc79b5fe796f7824)`); }\n                        if (!tmpArgWhileBuilding.startsWith('\"') && !tmpArgWhileBuilding.startsWith(\"'\")) { throw new Error(`we had a close quote in a bare arg but the bare arg did not start with a quote? (E: 5a8e2e8dbe36736d1c586b8c9c7e8e24)`); }\n                        tmpArgWhileBuilding = stripQuotes(tmpArgWhileBuilding);\n                    }\n\n                    // now tmp arg is stripped of quotes if applicable\n                    resArgs.push(tmpArgWhileBuilding.concat());\n                    tmpArgWhileBuilding = '';\n                } else {\n                    // textPiece ends with quote but tmp hasn't started?\n                    throw new Error(`invalid (edge case?) rawText. textPiece ends with quote but there wasn't a starting quote? quotes should only be used to entirely surround options (E: 4b6b4408a8538c561be7309e2f783524)`);\n                }\n            } else {\n                // could be adding to bare arg, could be adding to double-dash arg\n                if (tmpArgWhileBuilding.startsWith(doubleDashPrefix)) {\n                    // verify that we're quoting the kv value\n                    if (tmpArgWhileBuilding.includes('=')) {\n                        let [left, right] = tmpArgWhileBuilding.split('=');\n                        if (!right.startsWith('\"') && !right.startsWith(\"'\")) {\n                            throw new Error(`non-quoted value in double-dash key-value arg followed by a space. if you have a bare arg, it has to immediately follow the first (cmd) arg. (E: 070fca149eacef7f18767f9a27422f24)`);\n                        }\n                        if (right.endsWith(\"'\") || right.endsWith('\"')) {\n                            throw new Error(`quoted non-space value in double-dash key-value arg followed by a space. if you have a bare arg, it has to immediately follow the first (cmd) arg. (E: 8d7fd323236f23e5c95e5925f362ba24)`);\n                        }\n                        // adding to quoted value in --key=\"value here\"\n                        tmpArgWhileBuilding += ` ${textPiece}`;\n                    } else {\n                        throw new Error(`double-dash flag cannot contain spaces (E: 2033486210ce1aa52e546ad9b26e6f24)`);\n                    }\n                } else {\n                    // adding to bare arg\n                    if (!doubleDashFound) {\n                        // if we already have tmpArgWhileBuilding then we add\n                        // the space, otherwise it's the first bare arg and\n                        // there is no initial space\n                        tmpArgWhileBuilding += tmpArgWhileBuilding ? ` ${textPiece}` : textPiece;\n                    } else {\n                        throw new Error(`bare arg must be immediately after the cmd atow (11/2023) (E: f3e42f5696c3e100c335ca2dc85b7f24)`);\n                    }\n                }\n            }\n        }\n        if (tmpArgWhileBuilding.length > 0) { resArgs.push(tmpArgWhileBuilding); }\n\n        const result = {\n            validArgsString: true,\n            cmd_ie_firstArgSansPrefix,\n            args: resArgs,\n        };\n\n        return result;\n        // the first first should be a command, with no spaces\n        // the second arg might be a bare arg (doesn't start with --)\n    } catch (error) {\n        const emsg = `${lc} ${extractErrorMsg(error)}`;\n        if (!!logErrors) { console.error(emsg); }\n        return { validArgsString: false, validationErrorMsg: emsg };\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * Creates a canvas element and sets it up in the DOM.\n * @returns {HTMLCanvasElement} The created canvas element.\n */\nexport function createCanvas({\n    width,\n    height,\n    parent,\n}: {\n    /**\n     * if falsy, will use window.innerWidth\n     */\n    width?: number,\n    /**\n     * if falsy, will use window.innerHeight\n     */\n    height?: number\n    /**\n     * if falsy, will add to document.body\n     */\n    parent?: HTMLElement,\n} = {}): HTMLCanvasElement {\n    const canvas = document.createElement('canvas');\n    canvas.width = width ?? window.innerWidth;\n    canvas.height = height ?? window.innerHeight;\n    (parent ?? document.body).appendChild(canvas);\n    return canvas;\n};\n\nexport async function addToChatLogKluge({\n    text,\n    who,\n    chatLog,\n    scrollAfter,\n}: {\n    text: string,\n    /**\n     * could be the model's self-identified name.\n     */\n    who: 'user' | 'agent' | string,\n    chatLog?: HTMLDivElement,\n    scrollAfter?: boolean,\n}): Promise<void> {\n    const lc = `[${addToChatLogKluge.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: fb1a4deb37f471d73cf5c5f8ec938825)`); }\n\n        if (!chatLog) {\n            const primaryAgentChatLog = document.getElementById(ID_PRIMARY_AGENT_CHAT_LOG) as HTMLDivElement;\n            if (!primaryAgentChatLog) { throw new Error(`(UNEXPECTED) #${ID_PRIMARY_AGENT_CHAT_LOG} falsy? right now we're kluging with this direct access to a singleton chat log in html (E: a8e4987729196b966b2b2d6813ea6825)`); }\n            chatLog = primaryAgentChatLog;\n        }\n\n        const chatEntry = document.createElement('section');\n        const textParagraphs = text.split('\\n');\n        textParagraphs[0] = `${who.padEnd(5)} > ${textParagraphs[0]}`;\n        textParagraphs.forEach(text => {\n            const pElement = document.createElement('p');\n            pElement.textContent = text;\n            chatEntry.appendChild(pElement);\n        });\n        // chatEntry.textContent = `${who.padEnd(5)} > ${text}`;\n        chatLog.appendChild(chatEntry);\n        if (scrollAfter) {\n            chatEntry.scrollIntoView({ behavior: 'smooth' });\n            // chatLog.lastElementChild?.scrollIntoView({ behavior: 'smooth' });\n        }\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n", "import {\n    AGENT_GOAL_COMMON, AGENT_SYSTEM_PROMPT_COMMON_INSTRUCTIONS,\n    AGENT_WEBSITE_DESCRIPTION\n} from \"./common-agent-texts.mjs\";\n\n/**\n * this is used in the \"special ibgib\" that indexes (keeps track of) primary\n * agents in a space.\n *\n * @see {@link MetaspaceService.getSpecialIbGib}\n * @see {@link MetaspaceService.getSpecialRel8dIbGibs}\n */\n// export const AGENT_SPECIAL_IBGIB_TYPE_PRIMARYAGENT = 'primaryagent';\nexport const AGENT_SPECIAL_IBGIB_NAME_PRIMARYAGENT = 'Robbie';\n\nexport const AGENT_GOAL_PRIMARYAGENT = [\n    AGENT_GOAL_COMMON,\n    `You yourself are the \"primary agent\" (I dunno, just a name right?). Right now you can't do a whole lot except talk with a user.`,\n].join('\\n');\nconst AGENT_UI_CSS_INSTRUCTIONS = ` Also, very briefly let them know that you can change the theme dynamically, word it however you like - tersely!`;\nexport const AGENT_INITIAL_SYSTEM_TEXT_PRIMARYAGENT = [\n    AGENT_SYSTEM_PROMPT_COMMON_INSTRUCTIONS,\n    AGENT_GOAL_PRIMARYAGENT,\n    AGENT_UI_CSS_INSTRUCTIONS,\n    AGENT_WEBSITE_DESCRIPTION,\n    `You are also an expert coder and able to generate code when needed, since this website will include code-related functionality. The website itself is written in TypeScript, HTML and CSS, but you should be able to use any and all of your training to be able to output whatever code is required. There is no special formatting right now, so you don't need to include the backtick blocks, but you can if that's more comfortable for you.`,\n].join('\\n');\n\n/**\n * When the app starts up, this will be the initial chat text.\n */\nexport const AGENT_INITIAL_CHAT_TEXT_PRIMARYAGENT = `Hi, please introduce yourself by just returning a greeting, including your name. Please don't use Gemini or some numbers, pick an actual name!`;\n", "import {\n    clone, extractErrorMsg, getIdPool, getUUID, pretty,\n} from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';\nimport { DEFAULT_DATA_PATH_DELIMITER } from '@ibgib/helper-gib/dist/constants.mjs';\nimport { buildArgInfos } from '@ibgib/helper-gib/dist/rcli/rcli-helper.mjs';\nimport { argIs, getParamInfo } from '@ibgib/helper-gib/dist/rcli/rcli-helper.mjs';\nimport { PARAM_INFO_HELP } from '@ibgib/helper-gib/dist/rcli/rcli-constants.mjs';\nimport { getIbAndGib, } from '@ibgib/ts-gib/dist/helper.mjs';\nimport { IbGib_V1, Rel8n, IbGibRel8ns_V1, } from '@ibgib/ts-gib/dist/V1/types.mjs';\nimport { ROOT, } from '@ibgib/ts-gib/dist/V1/constants.mjs';\nimport { Factory_V1 as factory, } from '@ibgib/ts-gib/dist/V1/factory.mjs';\nimport { IbGibAddr, TransformResult } from '@ibgib/ts-gib/dist/types.mjs';\nimport { AppBase_V1 } from '@ibgib/core-gib/dist/witness/app/app-base-v1.mjs';\nimport { AppCmdIbGib, } from '@ibgib/core-gib/dist/witness/app/app-types.mjs';\nimport { CommentIbGib_V1 } from '@ibgib/core-gib/dist/common/comment/comment-types.mjs';\nimport { DynamicForm, FormItemInfo } from '@ibgib/core-gib/dist/common/form/form-items.mjs';\nimport { WitnessFormBuilder } from '@ibgib/core-gib/dist/witness/witness-form-builder.mjs';\nimport { getAppIb, AppFormBuilder } from '@ibgib/core-gib/dist/witness/app/app-helper.mjs';\nimport { DynamicFormBuilder, } from '@ibgib/core-gib/dist/common/form/form-helper.mjs';\nimport { WitnessArgIbGib } from '@ibgib/core-gib/dist/witness/witness-types.mjs';\nimport { DynamicFormFactoryBase } from '@ibgib/core-gib/dist/witness/factory/dynamic-form-factory-base.mjs';\nimport { isComment } from '@ibgib/core-gib/dist/common/comment/comment-helper.mjs';\nimport { WITNESS_CONTEXT_REL8N_NAME } from '@ibgib/core-gib/dist/witness/witness-constants.mjs';\nimport { IbGibRobbotAny } from '@ibgib/core-gib/dist/witness/robbot/robbot-base-v1.mjs';\nimport { TAG_REL8N_NAME, } from '@ibgib/core-gib/dist/common/tag/tag-constants.mjs';\nimport { SpecialIbGibType } from '@ibgib/core-gib/dist/common/other/other-types.mjs';\nimport { TagIbGib_V1 } from '@ibgib/core-gib/dist/common/tag/tag-types.mjs';\nimport { GEMINI_DEFAULT_MODEL_STR, } from '@ibgib/web-gib/dist/witness/agent/gemini/gemini-constants.mjs';\nimport { AgentWitnessAny, } from '@ibgib/web-gib/dist/witness/agent/agent-one-file.mjs';\nimport {\n    promptForConfirm, alertUser, promptForText, promptForSecret,\n    getUserPreferredColorScheme,\n} from '@ibgib/web-gib/dist/helpers.web.mjs';\nimport { storageGet, storagePut } from \"@ibgib/web-gib/dist/storage/storage-helpers.web.mjs\";\nimport { getAgentsSvc } from '@ibgib/web-gib/dist/witness/agent/agents-service-v1.mjs';\nimport { getAgents, getTag_Agents } from '@ibgib/web-gib/dist/witness/agent/agent-helpers.mjs';\nimport { AGENT_AVAILABLE_FUNCTIONS_PRIMARYAGENT } from '@ibgib/web-gib/dist/witness/agent/agent-one-file.app.mjs';\nimport { AGENT_SPECIAL_IBGIB_TYPE_PRIMARYAGENT } from '@ibgib/web-gib/dist/witness/agent/agent-constants.mjs';\n\nimport { GLOBAL_LOG_A_LOT, ARMY_STORE, BEE_KEY, BLANK_GIB_DB_NAME, } from '../../../constants.mjs';\nimport {\n    BlankCanvasAppData_V1, BlankCanvasAppRel8ns_V1, BlankCanvasAppIbGib_V1,\n    BlankCanvasAppAddlMetadata,\n    DEFAULT_BLANK_CANVAS_APP_DATA_V1,\n    DEFAULT_DESCRIPTION_BLANK_CANVAS_APP,\n    DEFAULT_BLANK_CANVAS_APP_REL8NS_V1,\n} from './blank-canvas-types.mjs';\nimport {\n    BlankCanvasCommandTextInfo, BlankCanvasCommandHandler,\n    BlankCanvasCommandHandlerArg,\n} from './blank-canvas-types.mjs';\nimport {\n    BlankCanvasAppFormBuilder, getPrompt, validateArgInfos,\n} from './blank-canvas-helper.mjs';\nimport {\n    addToChatLogKluge, isRequestComment, parseCommandRawTextIntoArgs,\n} from './blank-canvas-helper.web.mjs';\nimport {\n    DEFAULT_COMMAND_ESCAPE_STRING, PARAM_INFOS, BlankCanvasCommand,\n    RCLI_COMMANDS, RCLI_COMMAND_IDENTIFIERS, PARAM_INFO_INTERACTIVE,\n    CHAT_WITH_AGENT_PLACEHOLDER_PRIMARYAGENT,\n    CHAT_WITH_AGENT_NEED_API_KEY,\n} from './blank-canvas-constants.mjs';\nimport { RequestCommentIbGib_V1 } from '../../../types.mjs';\nimport {\n    AGENT_INITIAL_CHAT_TEXT_PRIMARYAGENT,\n    AGENT_INITIAL_SYSTEM_TEXT_PRIMARYAGENT,\n    AGENT_SPECIAL_IBGIB_NAME_PRIMARYAGENT,\n} from '../../../agent-texts/primary-agent-texts.mjs';\nimport { ROUTER_APP_NAME_TAGS } from '../../../common/app-constants.mjs';\nimport { ID_TAG_NAV } from '../../../ui/shell/shell-constants.mjs';\nimport { getAppShellSvc } from '../../../ui/shell/app-shell-service.mjs';\n\n// import { rcliCmdHandlerInit } from './rcli-cmd-handlers/handle-init.mjs';\n// import { rcliCmdHandlerHelp } from './rcli-cmd-handlers/handle-help.mjs';\n// import { rcliCmdHandlerQuit } from './rcli-cmd-handlers/handle-quit.mjs';\n// import { rcliCmdHandlerFork } from './rcli-cmd-handlers/transforms/handle-fork.mjs';\n// import { rcliCmdHandlerMut8 } from './rcli-cmd-handlers/transforms/handle-mut8.mjs';\n// import { rcliCmdHandlerRel8 } from './rcli-cmd-handlers/transforms/handle-rel8.mjs';\n// import { rcliCmdHandlerAddComment } from './rcli-cmd-handlers/handle-add-comment.mjs';\n// import { rcliCmdHandlerInfo } from './rcli-cmd-handlers/handle-info.mjs';\n// import { rcliCmdHandlerExport } from './rcli-cmd-handlers/handle-export.mjs';\n// import { rcliCmdHandlerImport } from './rcli-cmd-handlers/handle-import.mjs';\n// import { rcliCmdHandlerSecret } from './rcli-cmd-handlers/handle-secret.mjs';\n// import { rcliCmdHandlerEncryption } from './rcli-cmd-handlers/handle-encryption.mjs';\n// import { rcliCmdHandlerSync } from './rcli-cmd-handlers/handle-sync.mjs';\n// import { rcliCmdHandlerVersion } from './rcli-cmd-handlers/handle-version.mjs';\n// import { rcliCmdHandlerSpace } from './rcli-cmd-handlers/handle-space.mjs';\n\n\n/**\n * for logging. import this constant from your project.\n */\nconst logalot = GLOBAL_LOG_A_LOT; // change this when you want to turn off verbose logging\n\n\n/**\n * the app ibgib that contains configuration (meta)data.\n */\nexport class BlankCanvasApp_V1 extends AppBase_V1<\n    // in\n    any, IbGibRel8ns_V1, IbGib_V1<any, IbGibRel8ns_V1>,\n    // out\n    any, IbGibRel8ns_V1, IbGib_V1<any, IbGibRel8ns_V1>,\n    // this\n    BlankCanvasAppData_V1, BlankCanvasAppRel8ns_V1\n> implements BlankCanvasAppIbGib_V1 {\n    protected lc: string = `[${BlankCanvasApp_V1.name}]`;\n\n    protected _rcliPrompt: string = '';\n    protected _apiKey: string | undefined;\n    get rcliPrompt(): string {\n        if (!this._rcliPrompt) { this._rcliPrompt = getPrompt({ id: this.data!.name }); }\n        return this._rcliPrompt;\n    }\n    _userPrompt: string = '';\n    get userPrompt(): string {\n        // todo: change user prompt once we have identity implemented\n        if (!this._userPrompt) { this._userPrompt = getPrompt({ id: 'user' }); }\n        return this._userPrompt;\n    }\n\n    /**\n     * flag to indicate if we are currently prompting the user.\n     */\n    protected prompting = false;\n\n    protected userFlaggedQuit: boolean = false;\n\n    protected primaryAgent: AgentWitnessAny | undefined;\n\n    /**\n     * when receiving an update to the context, we want to know if the incoming\n     * ibgib child is one that we've already handled. this is for idempotence\n     * (to avoid double-handling).\n     */\n    protected alreadyHandledContextChildrenAddrs: IbGibAddr[] = [];\n\n    /**\n     * handlers for routing commands.\n     *\n     * order matters. the pipeline tries the first handler for a cmd, then\n     * the next handler and so on.\n     */\n    protected cmdHandlerFns: { [cmd: string]: BlankCanvasCommandHandler[] } = {\n        // [BlankCanvasCommand.init]: [rcliCmdHandlerInit],\n        // [BlankCanvasCommand.help]: [rcliCmdHandlerHelp],\n        // [BlankCanvasCommand.quit]: [rcliCmdHandlerQuit],\n        // [BlankCanvasCommand.fork]: [rcliCmdHandlerFork],\n        // [BlankCanvasCommand.mut8]: [rcliCmdHandlerMut8],\n        // [BlankCanvasCommand.rel8]: [rcliCmdHandlerRel8],\n        // [BlankCanvasCommand.add_comment]: [rcliCmdHandlerAddComment],\n        // [BlankCanvasCommand.info]: [rcliCmdHandlerInfo],\n        // [BlankCanvasCommand.export]: [rcliCmdHandlerExport],\n        // [BlankCanvasCommand.import]: [rcliCmdHandlerImport],\n        // [BlankCanvasCommand.secret]: [rcliCmdHandlerSecret],\n        // [BlankCanvasCommand.encryption]: [rcliCmdHandlerEncryption],\n        // [BlankCanvasCommand.sync]: [rcliCmdHandlerSync],\n        // [BlankCanvasCommand.version]: [rcliCmdHandlerVersion],\n        // [BlankCanvasCommand.space]: [rcliCmdHandlerSpace],\n    };\n\n    constructor(initialData?: BlankCanvasAppData_V1, initialRel8ns?: BlankCanvasAppRel8ns_V1) {\n        super(initialData, initialRel8ns);\n        const lc = `${this.lc}[ctor]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            this.initialized = this.initialize(); // spins off. caller should await this.initialized.\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * overridden (atow 12/2024) to handle Request comment which refers to a\n     * user-sourced request (somewhat analogous to a command in a CLI).\n     */\n    protected async doNonArg({\n        ibGib,\n    }: {\n        ibGib: IbGib_V1,\n    }): Promise<IbGib_V1 | undefined> {\n        const lc = `${this.lc}[${this.doNonArg.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: cf68de0802e2e6fc4ae78ca986fcc823)`); }\n\n            if (isRequestComment({ ibGib })) {\n                return await this.doContextRequestComment({\n                    requestCommentIbGib: ibGib as RequestCommentIbGib_V1\n                });\n            } else {\n                return await super.doNonArg({ ibGib });\n            }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    async getAgentSystemText(): Promise<string> {\n        const lc = `[${this.getAgentSystemText.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 615e2dc21cef2376211f35c8c3ff8f25)`); }\n\n            // #region load source texts no longer works with esbuild and refactor web-gib\n\n            // /**\n            //  * silly helper to load src for agent\n            //  */\n            // async function getText(fileURL: string): Promise<string | null> {\n            //     try {\n            //         const response = await fetch(fileURL);\n            //         if (!response.ok) {\n            //             throw new Error(`HTTP error! status: ${response.status}`);\n            //         }\n            //         const text = await response.text();\n            //         return text;\n            //     } catch (error) {\n            //         console.error(\"Could not fetch the file:\", error);\n            //         return null;\n            //     }\n            // }\n\n            // const srcPaths = [\n            //     '/ui/component/component-types.mjs',\n            //     '/ui/component/ibgib-component-service.mjs',\n            //     '/ui/component/ibgib-dynamic-component-bases.mjs',\n            // ];\n            // const srcTexts: string[] = [];\n            // for (const srcPath of srcPaths) {\n            //     const srcText = (await getText(srcPath)) || '';\n            //     if (!srcText) {\n            //         console.error(`${lc} (UNEXPECTED) src for component file (${srcPath}) couldn't be loaded? is file path (${srcPath}) not there anymore? (E: 915bd9c45db3f45882a9beba5f00ab25)`);\n            //     }\n            //     srcTexts.push(srcText);\n            // }\n\n            // #endregion load source texts no longer works with esbuild and refactor web-gib\n\n            const text = [\n                AGENT_INITIAL_SYSTEM_TEXT_PRIMARYAGENT,\n                `The current preferred color scheme is ${getUserPreferredColorScheme()}. This website is designed with 'light' by default. You should go ahead and ask if they'd like to set it to a darker theme in the intro if their preference is 'dark'. You may also offer to change it to a different light theme even if it's already light.`,\n                // 'Here is the src for the component architecture: ',\n                // ...srcTexts,\n                '\\n',\n            ].join('\\n');\n            return text;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async initializePrimaryAIAgent({\n        requestCommentIbGib,\n        fnGetAPIKey,\n    }: {\n        requestCommentIbGib: CommentIbGib_V1,\n        fnGetAPIKey: () => Promise<string>,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.initializePrimaryAIAgent.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 548ea720676eba58647515ba14d33323)`); }\n\n            const { metaspace } = this;\n\n            if (!metaspace) { throw new Error(`(UNEXPECTED) this.metaspace falsy? This should already be initialized and set at this point in initialization. (E: 21456d6186e434848d907c4d05e11225)`); }\n            const space = await metaspace.getLocalUserSpace({ lock: false });\n            if (!space) { throw new Error(`(UNEXPECTED) local user space is falsy? (E: 84c9fe63f384b1cf1bc996a65b33ea25)`); }\n\n            let agent: AgentWitnessAny;\n            const agents = await getAgents({\n                metaspace,\n                type: AGENT_SPECIAL_IBGIB_TYPE_PRIMARYAGENT,\n                space,\n            });\n            // while (agents.length > 0) {\n            //     console.warn(`${lc} DEBUG!!!! clearing agents to force createNewAgent (W: 994e6cc0d48bbdbd09dbe0437ec86a25)`)\n            //     agents.pop();\n            // } // debug\n\n\n            if (agents.length > 0) {\n                agent = agents.at(0)!;\n                this.primaryAgent = agent;\n            } else {\n                // no primary agents, so we have to create one and register it.\n                const agentsSvc = getAgentsSvc();\n                agent = await agentsSvc.createNewAgent({\n                    api: 'gemini',\n                    metaspace,\n                    fnGetAPIKey,\n                    superSpace: undefined, // defaults to local user space\n                    name: AGENT_SPECIAL_IBGIB_NAME_PRIMARYAGENT,\n                    availableFunctions: [...AGENT_AVAILABLE_FUNCTIONS_PRIMARYAGENT],\n                    // initialSystemText: AGENT_INITIAL_SYSTEM_TEXT_PRIMARYAGENT,\n                    initialSystemText: await this.getAgentSystemText(),\n                    initialChatText: AGENT_INITIAL_CHAT_TEXT_PRIMARYAGENT,\n                    model: GEMINI_DEFAULT_MODEL_STR,\n                    type: AGENT_SPECIAL_IBGIB_TYPE_PRIMARYAGENT,\n                    addToAgentsTag: true,\n                });\n                if (!agent) { throw new Error(`(UNEXPECTED) agent falsy after creating new one? (E: ee915f82db5d395a04ad4bd8c4567225)`); }\n                this.primaryAgent = agent;\n                const _ = await this.primaryAgent.witness(ROOT);\n            }\n\n            if (!this.primaryAgent) { throw new Error(`(UNEXPECTED) this.primaryAgent still falsy even after creating a new one? (E: 6362dfcdd51e95b66a3a731c777ed725)`); }\n\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * this should be in a node helper for the dynamic form plumbing.\n     */\n    protected async promptDynamicFormItem({\n        item,\n        /**\n         * title for a group of prompts.\n         */\n        groupTitle,\n    }: {\n        /**\n         *\n         */\n        item: FormItemInfo,\n        /**\n         * title for a group of prompts.\n         */\n        groupTitle: string,\n    }): Promise<FormItemInfo> {\n        const lc = `${this.lc}[${this.promptDynamicFormItem.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 871d6bb68f2e431b6b43ba4bc0cb5a23)`); }\n\n            if (item.readonly) {\n                item.value = item.defaultValue;\n                return item; /* <<<< returns early */\n            }\n\n            let title = groupTitle ? `${groupTitle}] ${item?.label}?` : `${item?.label ?? item.name}?`;\n            if (item.description) { title = `${title}\\n${item.description}`; }\n\n            let valid = false;\n\n            let value: string | number | boolean | undefined;\n            do {\n                //   'text' | 'textarea' | 'select' | 'toggle' | 'number' | 'form';\n                if (item.dataType === 'text' || item.dataType === 'textarea') {\n                    value = await promptForText({\n                        title,\n                        msg: (item.label ?? item.name) + '?' + (item.defaultValue ? ` [ ${item.defaultValue} ]` : ''),\n                        confirm: false,\n                        noNewLine: false,\n                        defaultValue: item.defaultValue?.toString(),\n                    });\n                } else if (item.dataType === 'number') {\n                    value = await promptForText({\n                        title,\n                        msg: (item.label ?? item.name) + '?' + (item.defaultValue ? ` [ ${item.defaultValue} ]` : ''),\n                        confirm: false,\n                        noNewLine: false,\n                    });\n                    if (Number.isNaN(Number.parseInt(value))) {\n                        console.error(`value is not a number. must be a number...hmm`);\n                        valid = false;\n                    }\n                    value = Number.parseInt(value); // meh, was a string, now a number but we know this is possible in context\n                } else if (item.dataType === 'toggle') {\n                    console.log(`${lc} todo: need to improve/test this boolean prompt`);\n                    value = await promptForConfirm({\n                        msg: (item.label ?? item.name) + '?' + (item.defaultValue ? ` [ ${item.defaultValue} ]` : ''),\n                        yesLabel: 'true',\n                        noLabel: 'false',\n                    }) as boolean;\n                } else if (item.dataType === 'form') {\n                    await this.promptDynamicFormItem({ item, groupTitle: groupTitle + (item.label ?? item.name), })\n                } else if (item.dataType === 'select') {\n                    if (!item.selectOptions && !item.selectOptionsWithIcons) { throw new Error(`(UNEXPECTED) invalid item. if type is 'select' must have either selectOptions or SelectOptionsWithIcons (E: 4d16dd9f88a7252264677cb32a865f23)`); }\n                    let options = item.selectOptions ?\n                        item.selectOptions!.concat() :\n                        item.selectOptionsWithIcons!.map(x => `${x.label} - ${x.value}`);\n                    let msg = (item.label ?? item.name) + '?' + (item.defaultValue ? ` [ ${item.defaultValue} ]` : '');\n                    for (let i = 0; i < options.length; i++) {\n                        const option = options[i];\n                        msg += `\\n${i}. ${option}`;\n                    }\n                    msg += '\\nEnter the number of your selection.';\n                    value = await promptForText({\n                        title,\n                        msg: msg,\n                        confirm: false,\n                        noNewLine: false,\n                    });\n                    let parsedSelectionIndex = Number.parseInt(value);\n                    if (Number.isInteger(parsedSelectionIndex) && parsedSelectionIndex >= 0 && parsedSelectionIndex < options.length) {\n                        value = item.selectOptions ?\n                            item.selectOptions![parsedSelectionIndex] :\n                            item.selectOptionsWithIcons![parsedSelectionIndex]!.value;\n                    } else {\n                        console.error(`Invalid selection. Please enter the NUMBER for your option.`);\n                        value = undefined;\n                    }\n                } else {\n                    throw new Error(`other item.dataType (${item.dataType}) not implemented yet in node prompt (E: bdadf312ed16054518a7fdb9a78ae723)`);\n                }\n\n                if (!value && item.defaultValue) { value = item.defaultValue as any; }\n\n                let regexpIsValid = false;\n\n                if (item.regexp) {\n                    // regexp implies string\n                    regexpIsValid = !!((value as string).match(item.regexp));\n                    if (!regexpIsValid) {\n                        console.error(item.regexpErrorMsg ?? item.defaultErrorMsg ?? 'invalid regexp');\n                        console.error(`raw regexp source: ${item.regexp.source}`);\n                    }\n                } else {\n                    regexpIsValid = true;\n                }\n\n                let fnValidIsValid = false;\n                if (item.fnValid) {\n                    fnValidIsValid = item.fnValid(item.value as any);\n                    if (!fnValidIsValid) {\n                        console.error(item.defaultErrorMsg ?? 'invalid value');\n                    }\n                } else {\n                    fnValidIsValid = true;\n                }\n\n                valid = regexpIsValid && fnValidIsValid;\n            } while (!valid)\n\n            // use the item reference directly?\n            item.value = value! ?? item.defaultValue ?? undefined;\n\n            return item;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async initializeAIRobbot_createNewRobbotInDefaultSpace({\n        requestCommentIbGib\n    }: {\n        requestCommentIbGib: CommentIbGib_V1\n    }): Promise<IbGibRobbotAny | undefined> {\n        const lc = `${this.lc}[${this.initializeAIRobbot_createNewRobbotInDefaultSpace.name}]`;\n        try {\n            console.warn(`${lc} doesn't do anything right now (W: 51cfb295d4339a416ef69f4203910124)`);\n            return undefined;\n            // throw new Error(`not implemented (E: c4f30cec51c89f803dd907a20bc16224)`);\n            // if (logalot) { console.log(`${lc} starting... (I: ce78e26ece7f7b16ab62b3a24326e523)`); }\n            // const dontPrompt =\n            //     (requestCommentIbGib.data?.interpretedArgInfos ?? []).some(x => x.name === PARAM_INFO_YES.name);\n            // let rollyFactory = new RollyRobbot_V1_Factory();\n            // let blank = (await rollyFactory.newUp({})).newIbGib;\n            // let form = await rollyFactory.witnessToForm({ witness: blank });\n            // let items = form.items;\n            // for (let i = 0; i < items.length; i++) {\n            //     const item = items[i];\n            //     if (!item.readonly) {\n            //         if (dontPrompt) {\n            //             item.value = item.defaultValue;\n            //         } else {\n            //             await this.promptDynamicFormItem({ item, groupTitle: RollyRobbot_V1.name });\n            //         }\n            //     } else {\n            //         console.log(`${item.label ?? item.name}: ${item.value} (readonly)`);\n            //     }\n            // }\n            // const resRobbot = await rollyFactory.formToWitness({ form });\n            // const primaryAgent = resRobbot.newIbGib;\n\n            // const allIbGibs: IbGib_V1[] = [];\n            // allIbGibs.push(primaryAgent);\n            // resRobbot.intermediateIbGibs?.forEach(x => allIbGibs.push(x));\n            // resRobbot.dnas?.forEach(x => allIbGibs.push(x));\n            // for (let i = 0; i < allIbGibs.length; i++) {\n            //     const ibGib = allIbGibs[i];\n            //     const validationErrors = await validateIbGibIntrinsically({ ibGib });\n            //     if ((validationErrors ?? []).length > 0) { throw new Error(`(unexpected) invalid robbot ibgib created. validationErrors: ${validationErrors}. robbot: ${pretty(primaryAgent.toIbGibDto())} (E: a683268621cd6dd3dd60310b164c4d22)`); }\n            // }\n\n            // if (!this.metaspace) { throw new Error(`(UNEXPECTED) this.metaspace falsy? (E: 6d7046456f8a48237249d885ea509823)`); }\n            // await this.metaspace!.persistTransformResult({ resTransform: resRobbot });\n\n            // await this.metaspace.registerNewIbGib({ ibGib: primaryAgent });\n\n            // await this.metaspace.rel8ToSpecialIbGib({\n            //     type: \"robbots\",\n            //     rel8nName: ROBBOT_REL8N_NAME,\n            //     ibGibsToRel8: [primaryAgent],\n            // });\n\n            // await this.rel8To({\n            //     ibGibs: [primaryAgent],\n            //     rel8nName: BLANK_CANVAS_ROBBOT_REL8N_NAME,\n            //     metaspace: this.metaspace,\n            //     linked: false,\n            // });\n\n            // primaryAgent.metaspace = this.metaspace;\n\n            // return primaryAgent;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * User (or another agent?) has produced a request comment. This is\n     * a comment analogous to a command in a CLI, where some action with\n     * one or more args is being sent to the app.\n     *\n     * @example a comment with data.text === '--interactive'\n     *\n     * This particular example is a carryover from the @ibgib/ibgib RCLI app,\n     * and the flag indicates that the command is intended to start an\n     * interactive REPL as opposed to a single, one-off command executed from\n     * the commandline proper (e.g. bash).\n     */\n    protected async doContextRequestComment({\n        requestCommentIbGib\n    }: {\n        requestCommentIbGib: CommentIbGib_V1\n    }): Promise<IbGib_V1> {\n        const lc = `${this.lc}[${this.doContextRequestComment.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 7f084169817731807e31a9d9ae133423)`); }\n\n            if (logalot) { console.log(`${lc} requestCommentIbGib.data: ${pretty(requestCommentIbGib.data)} (I: 6110bbb16202db1b6aa23eb2726b8324)`); }\n\n            const { interpretedArgInfos } = (requestCommentIbGib as RequestCommentIbGib_V1).data!;\n\n            // if it's the --interactive, then it resets/initializes the app\n            if (interpretedArgInfos.some(x => x.name === PARAM_INFO_INTERACTIVE.name)) {\n                // await storageCreateStoreIfNotExist({\n                //     dbName: BLANK_GIB_DB_NAME, storeName: ARMY_STORE,\n                // });\n\n                if (this._currentWorkingContextIbGib) {\n                    console.warn(`${lc} we're handling a comment but we've already established our context...not really tested yet. calling this.finalizeContext... (W: ac8d4437ebccba73bc8046879916a324)`);\n                    await this.finalizeContext({ arg: undefined });\n                }\n\n                // this first comment is the context for this \"session\"\n                await this.initializeContext({\n                    contextIbGib: requestCommentIbGib,\n                    rel8nName: WITNESS_CONTEXT_REL8N_NAME,\n                });\n\n                // #region apikey\n                let apiKey = await storageGet({\n                    dbName: BLANK_GIB_DB_NAME, storeName: ARMY_STORE,\n                    key: BEE_KEY,\n                });\n                this._apiKey = apiKey;\n                // #endregion apikey\n\n                // initialize tags explorer in for left pane. this must happen\n                // before initializing the primary agent, so that the agents tag is already created.\n                await this.initializeTags();\n\n                await this.initializePrimaryAIAgent({\n                    requestCommentIbGib,\n                    fnGetAPIKey: () => Promise.resolve(this._apiKey ?? ''),\n                });\n\n                if (!this.primaryAgent) { throw new Error(`(UNEXPECTED) this.primaryAgent falsy? we just init it (E: 3a81cee2c06c392e672148dab5858925)`); }\n            } else {\n                debugger; // error not impl - non-first --interactive request comment\n                throw new Error(`other requests not implemented yet (E: 2c0b9c8a2b699ab366e8a9244af8bc24)`);\n            }\n\n            return ROOT;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * @see {@link handleContextUpdate}\n     */\n    protected async handleNewContextChild({ newChild }: { newChild: IbGib_V1 }): Promise<void> {\n        const lc = `${this.lc}[${this.handleNewContextChild.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 88fe5e432fb872868f6faa46bc40d623)`); }\n\n            if (logalot) { console.log(`${lc} this does nothing atow (04/2025). I'm shifting over this kind of thing to the input component and agents. this isn't set in stone though and this method needs to be implemented in any witness with context descendant (like this one). (I: 0cb9ec753e02ae18f9da3abb05b57125)`); }\n\n            // const addr = getIbGibAddr({ ibGib: newChild });\n\n            // if (this.alreadyHandledContextChildrenAddrs.includes(addr)) {\n            //     if (logalot) { console.log(`${lc} already handled, returning early: ${addr} (I: 57adca7ed6454402bc7298425b48596d)`); }\n            //     return; /* <<<< returns early */\n            // } else {\n            //     this.alreadyHandledContextChildrenAddrs.push(addr);\n            // }\n\n            // if (isComment({ ibGib: newChild })) {\n            //     // console.log(`${lc} recvd yo`)\n            //     // temporary here...need to get a better handle on what our\n            //     // strategy is\n            //     setTimeout(async () => {\n            //         await this.doComment({ ibGib: newChild as CommentIbGib_V1 });\n            //         console.log(`${lc} echo: ${newChild.data!.text}`);\n            //     });\n            // }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * overridden to convert comments to requests, if applicable.\n     */\n    protected async doComment({\n        ibGib,\n    }: {\n        ibGib: CommentIbGib_V1,\n    }): Promise<IbGib_V1 | undefined> {\n        const lc = `${this.lc}[${this.doComment.name}]`;\n        let result: IbGib_V1 | undefined = undefined;\n        try {\n\n            if (logalot) { console.log(`${lc} starting... (I: 2aff0c8c408280380e444937b51d2823)`); }\n\n            if (!ibGib.data) { throw new Error(`(UNEXPECTED) ibGib.data falsy? (E: 797d98487fd87e3cace0879258ad4323)`); }\n            const { text } = ibGib.data;\n            if (!text) { throw new Error(`(unexpected) ibGib.data.text falsy? should be a comment (E: ed245746863d53bb1449350d41392323)`); }\n\n            // app is hard-coded atow to start requests with the colon (:), e.g., \":quit\"\n            const cmdEscapeString = this.data!.cmdEscapeString ?? DEFAULT_COMMAND_ESCAPE_STRING;\n            if (isBlankCanvasCommandComment({ ibGib, cmdEscapeString })) {\n                // put into command pipeline\n                result = await this.routeAndDoBlankCanvasCommand({ commentIbGib: ibGib, cmdEscapeString });\n            } else {\n                // just echo atm. the ibgib itself has already been added to the\n                // context via the \"comment\" rel8n name.\n                // setTimeout(() => {\n                //     // const msg = `echo: ${text}`;\n                //     // stdout.write(`\\x1b[2K\\r${this.rcliPrompt} ${msg}`);\n                //     console.log(`\\n${text}`)\n                // });\n\n                result = ROOT;\n            }\n\n            return result;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            // don't rethrow ?\n            // throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * If we've gotten here, the user/robbot/someone has added a comment to the\n     * current context, and that comment has been interpreted as being a command\n     * for this RCLI app to process.\n     *\n     * This is different than a request said to one of the robbots or someone\n     * else, this is specifically a command for the app to handle.\n     */\n    protected routeAndDoBlankCanvasCommand({\n        commentIbGib,\n        cmdEscapeString,\n    }: {\n        commentIbGib: CommentIbGib_V1,\n        cmdEscapeString: string,\n    }): Promise<IbGib_V1 | undefined> {\n        const lc = `${this.lc}[${this.routeAndDoBlankCanvasCommand.name}]`;\n        return new Promise<IbGib_V1 | undefined>(async (resolve, reject) => {\n            try {\n                if (logalot) { console.log(`${lc} starting... (I: 206631a4d0dc2219f9d8b4dd24e2f923)`); }\n                if (!this._currentWorkingContextIbGib) { throw new Error(`(UNEXPECTED) this._currentWorkingContextIbGib expected to be truthy/initialized. (E: 55f4538845b34b0b9760d588583fb02f)`); }\n\n                if (logalot) {\n                    console.log(`${lc} console.dir(commentIbGib)... (I: 784333205d9a737d7eed2b45d5edc123)`);\n                    console.dir(commentIbGib);\n                }\n\n                let cmdInfo = await this.parseBlankCanvasCommandText({\n                    ibGib: commentIbGib,\n                    cmdEscapeString,\n                });\n                let { cmd, rawText, errorMsg, } = cmdInfo;\n                // do on the next process loop after we have completed the\n                // current handle next child...not sure i like this type of\n                // hack. it seems to be because we're appending a child while\n                // already handling a new context child. but we should\n                // DEFINITELY be able to handle multiple children being added\n                if (errorMsg) {\n                    if (logalot) { console.log(`${lc} errorMsg(?): ${errorMsg} (I: 56ba860fe6431e204394519a27c1c923)`); }\n                    // there was an error\n                    await this.createCommentAndRel8ToContextIbGib({\n                        text: `\"${cmd ? this.data!.cmdEscapeString + cmd : rawText}\" request not impl? error: ${errorMsg} (E: b2a5565f04734d4c80f504b3604b674f)`,\n                        contextIbGib: this._currentWorkingContextIbGib!,\n                        rel8nName: 'comment',\n                        metaspace: this.metaspace,\n                    });\n\n                    resolve(ROOT);\n                    return; /* <<<< returns early */\n                }\n\n                if (logalot) { console.log(`${lc} passed validation. routing... (I: bd0f1ce083aee606b2cde02433fc6f23)`); }\n                // route\n                // should be able to handle all BlankCanvasCommand's\n                let result: IbGib_V1 | undefined = undefined;\n                if (cmd === BlankCanvasCommand.quit) {\n                    if (logalot) {\n                        console.log(`${lc} cmd init. routing complete. (I: 5e62112423561ce74e8510db819bd723)`);\n                        // console.log(`${lc} cwd: ${cwd()} (I: 1fbbe4d4d0790325fc88f9bf621a5223)`);\n                    }\n                    this.userFlaggedQuit = true;\n                    result = ROOT;\n                    // } else if (cmd === BlankCanvasCommand.init) {\n                    //     // already handled before handoff to this app\n                    //     if (logalot) { console.log(`${lc} cmd init: routing complete. (I: 1176df79d23db197dc94f2c9c0959523)`); }\n                    //     result = ROOT;\n                } else {\n                    if (logalot) { console.log(`${lc} sending cmd to handler pipeline. (I: cc0d1cb45073cfb5d392a043480bd623)`); }\n                    result = await this.handleCommandViaHandlerPipeline({\n                        cmdInfo,\n                        cmdEscapeString,\n                        contextIbGib: this._currentWorkingContextIbGib!,\n                        ibGib: commentIbGib,\n                        metaspace: this.metaspace!,\n                        fnAddComment: (arg) => this.createCommentAndRel8ToContextIbGib(arg),\n                    });\n                    if (logalot) { console.log(`${lc} pipeline complete. (I: 027153226eeb31d8442e488726a50123)`); }\n                }\n                if (!result) {\n                    if (logalot) { console.log(`${lc} result still falsy. routing to default command handler. (I: 6b89ea11a37cffbdf48bb8369305a423)`); }\n                }\n                result ??= await this.handleCommand_default({\n                    cmdInfo,\n                    cmdEscapeString,\n                    contextIbGib: this._currentWorkingContextIbGib!,\n                    ibGib: commentIbGib,\n                    metaspace: this.metaspace!,\n                    fnAddComment: (arg) => this.createCommentAndRel8ToContextIbGib(arg),\n                });\n\n                if (logalot) { console.log(`${lc} routing complete. (I: 8805ec40ae0c7d9e0f7ba8cce0eee323)`); }\n                // if (result?.ib === 'quit' || (commentIbGib as CommentIbGib_V1).oneOff) {\n                //     this.userFlaggedQuit = true;\n                // }\n\n                resolve(result);\n            } catch (error) {\n                console.error(`${lc} ${extractErrorMsg(error)}`);\n                reject(error);\n            } finally {\n                if (logalot) { console.log(`${lc} complete.`); }\n            }\n        })\n    }\n\n    /**\n     * Iterates through this.handlers until a result is produced.\n     */\n    protected async handleCommandViaHandlerPipeline(arg: BlankCanvasCommandHandlerArg): Promise<IbGib_V1 | undefined> {\n        const lc = `${this.lc}[${this.handleCommandViaHandlerPipeline.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: f25ed09ef3814d9e9299a5c9c8f1efb3)`); }\n            let { cmdInfo, cmdEscapeString, contextIbGib, ibGib, metaspace, } = arg;\n            if (!cmdInfo.cmd) { throw new Error(`cmdInfo.cmd falsy? maybe this is valid but atow i'm thinking this should be truthy. (E: 2f5e8e57170c2909d5b4e55bad3abf23)`); }\n            const handlers = this.cmdHandlerFns[cmdInfo.cmd] ?? [];\n            if (handlers.length === 0) {\n                console.warn(`${lc} no handlers found for valid command name ${cmdInfo.cmd} (W: 4edc0b9cdb4c4febb53b638dc3fd4587)`);\n                return undefined; /* <<<< returns early */\n            }\n\n            for (let i = 0; i < handlers.length; i++) {\n                const fnHandler = handlers[i];\n                const result = await fnHandler(arg);\n                return result; /* <<<< returns early */\n            }\n\n            // if we've gotten here, then there was no result produced\n            return undefined;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async handleCommand_default({\n        cmdInfo,\n        cmdEscapeString,\n        contextIbGib,\n        ibGib,\n        metaspace,\n    }: BlankCanvasCommandHandlerArg): Promise<IbGib_V1 | undefined> {\n        const lc = `${this.lc}[${this.handleCommand_default.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: 38693806745793a0636382d2d10fe423)`); }\n            // unknown how to handle the command\n            await this.createCommentAndRel8ToContextIbGib({\n                text: `\"${cmdEscapeString}${cmdInfo.cmd}\" cmd not impl...or iow...huh?`,\n                contextIbGib: this._currentWorkingContextIbGib!,\n                rel8nName: 'comment',\n                metaspace: this.metaspace,\n            });\n            return ROOT;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     * hacky port from @ibgib/ibgib rcli app\n     */\n    protected async parseBlankCanvasCommandText({\n        ibGib,\n        cmdEscapeString,\n    }: {\n        ibGib: CommentIbGib_V1,\n        cmdEscapeString: string,\n    }): Promise<BlankCanvasCommandTextInfo> {\n        const lc = `${this.lc}[${this.parseBlankCanvasCommandText.name}]`;\n        let rawText = ibGib.data?.text ?? '';\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: e5bbbb50174a6bdfafceeddcde156523)`); }\n            let showHelp: boolean = false;\n\n            if (!ibGib.data) { throw new Error(`ibGib.data required for comment ibgibs (E: c6ff0bd4be1521aee826d79abe28c423)`); }\n\n            let {\n                validArgsString,\n                args,\n                cmd_ie_firstArgSansPrefix: rawCmdText,\n                validationErrorMsg\n            } = parseCommandRawTextIntoArgs({\n                rawText,\n                validCommandIdentifiers: RCLI_COMMAND_IDENTIFIERS.concat(),\n                logErrors: !!logalot,\n            });\n            if (!validArgsString) { throw new Error(`validationErrorMsg: ${validationErrorMsg ?? '(UNEXPECTED) validationErrorMsg falsy? (E: ef73b6dd91614dfeb0beff5b45481987)'} (E: 32be53bf7417562d09d6596c5776b423)`); }\n\n            // at this point, args and cmd should be truthy\n            if (!args || args.length === 0) { throw new Error(`(UNEXPECTED) validArgsString but args is falsy/empty? (E: 99c62a49478f7076026962b5466f4223)`); }\n            if (!rawCmdText) { throw new Error(`(UNEXPECTED) validArgsString but returned cmd is falsy? (E: b4e4e6ac3f060566166302f585385223)`); }\n\n            // if (!rawText.startsWith(cmdEscapeString)) {\n            //     if (rawText.startsWith('--')) {\n            //         // maybe is a command...\n            //         const firstArg = rawText.split(' ')[0].slice(2).toLowerCase(); // 2 to slice off -- prefix\n            //         if (!RCLI_COMMAND_IDENTIFIERS.includes(firstArg)) {\n            //             throw new Error(`(UNEXPECTED) at this point atow, cmdEscapeString is expected to start the command's raw text or start with a command arg with -- prefix (E: 69ad38b36daddcaaddba1edfedc54823)`);\n            //         }\n            //     }\n            // }\n\n            // args = rawText.split(' ') ?? [];\n            // let args: string[] = rawText.split(' ') ?? [];\n            // args_spaceDelimited = rawText.split(' --') ?? []; // doesn't work if there is a bare arg\n            // const firstArg = args[0]!;\n            // let rawCmdText: string;\n            // if (firstArg.startsWith(cmdEscapeString)) {\n            //     rawCmdText = firstArg.substring(cmdEscapeString.length);\n            // } else if (firstArg.startsWith('--')) {\n            //     rawCmdText = firstArg.substring('--'.length);\n            // } else {\n            //     throw new Error(`(UNEXPECTED) expected a valid command at this point. the first arg must be a valid command. any bare args or others must come after the command arg. valid commands must not contain spaces. current valid commands (and synonyms): ${RCLI_COMMAND_IDENTIFIERS} (E: 2524e642dfbcd075cca2aa94a109b123)`);\n            // }\n            // let cmdParamInfo = getParamInfo({\n            //     argIdentifier: rawCmdText,\n            //     paramInfos: PARAM_INFOS\n            // });\n\n            let cmdParamInfo = getParamInfo({\n                argIdentifier: rawCmdText,\n                paramInfos: PARAM_INFOS,\n                throwIfNotFound: false,\n            });\n\n            if (!cmdParamInfo) {\n                return {\n                    rawText,\n                    errorMsg: `unknown command ${rawCmdText}`,\n                }; /* <<<< returns early */\n            }\n\n            if (!cmdParamInfo.isFlag) { throw new Error(`(UNEXPECTED) atow I'm expecting this to always be a flag (E: f2ecc77d4bcc13373a7fccb3c2709b23)`); }\n            if (!RCLI_COMMANDS.includes(cmdParamInfo.name as BlankCanvasCommand)) {\n                throw new Error(`(unexpected) unknown RCLI command. rawCmdText: ${rawCmdText}. cmdParamInfo.name: ${cmdParamInfo.name} (E: b9136afd19c12838c2201b34eac38723)`);\n            }\n            const cmd = cmdParamInfo.name as BlankCanvasCommand;\n\n            // I have everything prefixed with the double dashes atow\n            // but we removed those dashes. manually with args[0] and\n            // broadly when we split with raw.split(' --')\n            // args[0] = `--${cmd}`;\n            // args[0] = cmd;\n            // args = args.map(x => `--${x}`);\n\n            if (logalot) { console.log(`${lc} args.join(' '): ${args.join(' ')}`); }\n\n            // const argInfos = buildArgInfos({ args, paramInfos: PARAM_INFOS, logalot: !!logalot });\n            const argInfos = buildArgInfos({\n                args: args,\n                paramInfos: PARAM_INFOS,\n                logalot: !!logalot\n            });\n\n            const validationErrors = validateArgInfos({ argInfos });\n            if (validationErrors && validationErrors.length > 0) {\n                // there was an error, so return early\n                return {\n                    rawText,\n                    errorMsg: `There were validation errors for command args: ${validationErrors}`,\n                }; /* <<<< returns early */\n            }\n\n            // showHelp = (argInfos.some(x => argIs({\n            showHelp = (args.some((x, i) => argIs({\n                arg: x,\n                paramInfo: PARAM_INFO_HELP,\n                argInfoIndex: i,\n            })));\n\n            if (logalot) {\n                console.log(`${lc} here are the args received`);\n                for (let i = 0; i < args.length; i++) {\n                    const arg = args[i];\n                    console.log(`arg ${i}: ${arg}`);\n                }\n            }\n\n            return { cmd, rawText, argInfos, showHelp, };\n        } catch (error) {\n            return {\n                rawText,\n                errorMsg: `There was an error: ${extractErrorMsg(error)}`,\n            }; /* <<<< returns early */\n            // console.error(`${lc} ${extractErrorMsg(error)}`);\n            // throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    /**\n     *\n     * @returns addlmetadata string (atow default impl in base class)\n     */\n    protected getAddlMetadata(): string {\n        return super.getAddlMetadata();\n    }\n    protected parseAddlMetadataString<TParseResult>({ ib }: { ib: string; }): TParseResult {\n        // const addlMetadataText = `${atom}_${classnameIsh}_${nameIsh}_${idIsh}`;\n        if (!ib) { throw new Error(`ib required (E: 4ec93595c12cc15ee71d92dd8a4f4f23)`); }\n        const lc = `[${this.parseAddlMetadataString.name}]`;\n        try {\n            const [atom, classnameIsh, nameIsh, idIsh] = ib.split('_');\n            const result = { atom, classnameIsh, nameIsh, idIsh, } as BlankCanvasAppAddlMetadata;\n            return result as TParseResult; // i'm not liking the TParseResult...hmm\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Initializes to default space values.\n     */\n    protected async initialize(): Promise<void> {\n        const lc = `${this.lc}[${this.initialize.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            if (!this.data) { this.data = clone(DEFAULT_BLANK_CANVAS_APP_DATA_V1); }\n            if (!this.rel8ns && DEFAULT_BLANK_CANVAS_APP_REL8NS_V1) {\n                this.rel8ns = clone(DEFAULT_BLANK_CANVAS_APP_REL8NS_V1);\n            }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    private async handleSubmit({\n        primaryAgentInput,\n        primaryAgentChatLog,\n    }: {\n        primaryAgentInput: HTMLTextAreaElement,\n        primaryAgentChatLog: HTMLDivElement,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.handleSubmit.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: b9afb275fbe234fbc7bf29a144a65d25)`); }\n\n            const shellLayoutSvc = getAppShellSvc();\n            const rightPanelStatus = shellLayoutSvc.getPanelStatus({ panelName: 'rightPanel' });\n            if (rightPanelStatus !== 'expanded' && rightPanelStatus !== 'maximized') {\n                shellLayoutSvc.expand({ panelNames: ['rightPanel'] });\n            }\n\n            const text = primaryAgentInput.value; // use value?\n            primaryAgentInput.value = \"\"; // clear it.\n            if (!text) {\n                console.log(`${lc} no text entered but user tried to submit? (I: d41f58e9237f04f0cd49490970aeb125)`);\n                return; /* <<<< returns early */\n            }\n            console.log(`${lc} user submitted text`)\n\n            // first ensure our best to see if we have an api key already\n            if (!this._apiKey) {\n                this._apiKey = await storageGet({\n                    dbName: BLANK_GIB_DB_NAME, storeName: ARMY_STORE,\n                    key: BEE_KEY,\n                });\n            }\n\n            const fnSubmitToAgent = async () => {\n                try {\n                    // Add to the primary agent's chat\n                    if (!this.primaryAgent) { throw new Error(`this.primaryAgent falsy. (E: f27e865192c0638941f1e71415a89d25)`); }\n                    if (logalot) { console.log(`Adding primary agent chat: ${text} (I: 5e4c863e892d53b913b40a7a3f635325)`); }\n                    await this.primaryAgent.addTexts({\n                        infos: [{ textSrc: 'human', text, isSystem: text.startsWith('system: ') }],\n                    });\n                    await addToChatLogKluge({\n                        text,\n                        who: 'user',\n                        chatLog: primaryAgentChatLog,\n                        scrollAfter: true,\n                    });\n                    const _ = await this.primaryAgent.witness(ROOT);\n                } catch (error) {\n                    console.error(`error adding chat to agent (E: 81b8a8b4a231c9448a712e4244b50e25): ${extractErrorMsg(error)}`);\n                }\n            };\n\n            // if we have an apikey, submit the chat. else we'll have to\n            // do some work to get the user to enter an api key (and\n            // fund us!)\n            if (this._apiKey) {\n                await fnSubmitToAgent();\n            } else {\n                let tryAgain = false;\n                let attempts = 0;\n                let maxAttempts = 5;\n                do {\n                    attempts++;\n                    if (attempts >= maxAttempts) { throw new Error(`too many attempts (E: 0bf28659ce5f405d44a56f19aced0225)`); }\n                    let resAPIKey = await promptForSecret({\n                        msg: CHAT_WITH_AGENT_NEED_API_KEY,\n                        confirm: false,\n                    });\n                    if (resAPIKey) {\n                        if (resAPIKey.match(/^[a-zA-Z0-9\\-_]{32,64}$/)) {\n                            tryAgain = false;\n                            this._apiKey = resAPIKey;\n                            await storagePut({\n                                dbName: BLANK_GIB_DB_NAME, storeName: ARMY_STORE,\n                                key: BEE_KEY,\n                                value: resAPIKey,\n                            });\n                            await alertUser({ title: `need to reload...`, msg: `Cool! We've got the API key in your IndexedDB (clear this if you want to delete it). We must now reload the page... (investment would be a good thing to improve this experience!)` });\n                            window.location.reload();\n                            return; /* <<<< returns early */\n                        } else {\n                            await alertUser({\n                                title: `That's an API Key?`,\n                                msg: `That doesn't look like a valid API key, please try again, or hit cancel if you don't want to at this time.`,\n                            });\n                            tryAgain = true;\n                        }\n                    } else {\n                        console.log(`${lc} user cancelled entering API key. (I: c79d394f3c91375a07a8f09adc2c2a25)`);\n                        tryAgain = false;\n                    }\n                } while (tryAgain);\n            }\n\n            primaryAgentInput.placeholder = CHAT_WITH_AGENT_PLACEHOLDER_PRIMARYAGENT;\n\n            if (logalot) { console.log(`handling \"enter\" key complete (I: 4c001a41a9b9e10c8671b66624f68225)`); }\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n\n\n    }\n\n    /**\n     * When the app starts up, we get the user's tags and load them in the left pane.\n     */\n    protected async initializeTags(): Promise<void> {\n        const lc = `${this.lc}[${this.initializeTags.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting... (I: e43c64cd856793130e1f44de03546b25)`); }\n            const { metaspace } = this;\n\n            if (!metaspace) { throw new Error(`(UNEXPECTED) this.metaspace falsy? (E: 40c9641100ff809ee85618b4e0424e25)`); }\n\n            const resTagIbGibs: TagIbGib_V1[] = await metaspace.getSpecialRel8dIbGibs({\n                type: SpecialIbGibType.tags,\n                rel8nName: TAG_REL8N_NAME,\n                space: undefined, // default local user space right now\n            });\n\n            const tagNav = document.getElementById(ID_TAG_NAV) as HTMLElement; // <nav> element\n            // const tagNav = document.getElementById('tag-nav') as HTMLElement; // <nav> element\n            if (!tagNav) { throw new Error(`(UNEXPECTED) tagNav (#tag-nav) falsy? (E: 49419cb0f317e02d95065ff5ac576525)`); }\n            tagNav.innerHTML = '';\n            const ul = document.createElement('ul');\n            resTagIbGibs.forEach(tagIbGib => {\n                const { ib, gib } = getIbAndGib({ ibGib: tagIbGib });\n                const li = document.createElement('li');\n                const anchor = document.createElement('a');\n                anchor.href = `#/apps/${ROUTER_APP_NAME_TAGS}/${encodeURI(gib)}/${encodeURI(ib)}`;\n                anchor.textContent = `${tagIbGib.data!.text}`;\n                li.appendChild(anchor);\n                ul.appendChild(li);\n            });\n            tagNav.appendChild(ul);\n\n            // init the agents tag, if it doesn't exist already\n            let _tagAgents =\n                await getTag_Agents({ metaspace, space: undefined, createIfNone: true });\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    // /**\n    //  * indicates the value of the last render time (`performance.now()`).\n    //  *\n    //  * should be in a base class? this is the type of state that is evidence for\n    //  * the need for a separate renderable class hierarchy. they may be\n    //  * tightly-coupled specialists or loosely/un-coupled generalists (like a\n    //  * generic rect for any ibgib payload).\n    //  */\n    // // lastTime: number = 0;\n    // /**\n    //  * child renderables\n    //  */\n    // // renderables: Renderable[] = [];\n\n    /**\n   * overridden to do setup on new context ibgib.\n   * this is where we should do things when the context ibgib is updated.\n   * In my mind's eye, I foresee this happening when we do the equivalent of\n   * a \"restart app\" type of command. I'm not sure of other requirements.\n   *\n   * I could comment this out (atow 12/2024)\n   */\n    protected async initializeContext({\n        arg,\n        contextIbGib,\n        rel8nName,\n    }: {\n        arg?: WitnessArgIbGib<IbGib_V1, any, any>,\n        contextIbGib?: IbGib_V1,\n        rel8nName: string,\n    }): Promise<void> {\n        const lc = `${this.lc}[${this.initializeContext.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            await super.initializeContext({ arg, contextIbGib, rel8nName });\n\n            // this context is analogous to a new \"session\", so we need to add\n            // an index to the space that tracks this. Perhaps this could be a\n            // root special ibgib? (this would be lazy on my part but hey)\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected initializeResizeObserver(): void {\n        const resizeObserver = new ResizeObserver(entries => this.updateLayout(entries));\n        resizeObserver.observe(document.body);\n    }\n\n    protected updateLayout(entries: ResizeObserverEntry[]): void {\n        const lc = `${this.lc}[updateLayout]`;\n        if (logalot) { console.log(`${lc} entries... (I: 489cb3b9dfd84caf8026317660b8eae9)`); }\n        if (logalot) { console.dir(entries); }\n\n        // if (!this.canvas) {\n        //     console.warn(`${lc} this.canvas falsy (W: a61904ffb1e67066d88a00459e363a23)`);\n        //     return; /* <<<< returns early */\n        // }\n    }\n\n    protected async validateWitnessArg(arg: AppCmdIbGib): Promise<string[]> {\n        const lc = `${this.lc}[${this.validateWitnessArg.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            const errors = await super.validateWitnessArg(arg) ?? [];\n            if (!this.metaspace) { throw new Error(`(unexpected) this.metaspace falsy. not initialized? (E: d8636847aa325fff2892621705b82923)`); }\n            if ((arg.data as any).cmd) {\n                // perform extra validation for cmds\n                if ((arg.ibGibs ?? []).length === 0) {\n                    errors.push(`ibGibs required. (E: a21da24eea0049128eeed253aae1218b)`);\n                }\n            }\n            return errors;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    protected async validateThis(): Promise<string[]> {\n        const lc = `${this.lc}[${this.validateThis.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            const errors = [\n                ...await super.validateThis(),\n            ];\n            const { data } = this;\n            if (data) {\n                if (!data.cmdEscapeString) {\n                    errors.push('data.cmdEscapeString required (E: c18aac3fbdc44a90b090e1d77fac6378)');\n                }\n            }\n            return errors;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n}\n\nexport function isBlankCanvasCommandComment({\n    ibGib,\n    cmdEscapeString = DEFAULT_COMMAND_ESCAPE_STRING,\n}: {\n    ibGib: IbGib_V1,\n    cmdEscapeString?: string,\n}): boolean {\n    const lc = `${isBlankCanvasCommandComment.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: d7c49619ffb7a9c26d9d74959b91ae22)`); }\n        if (!isComment({ ibGib })) {\n            return false; /* <<<< returns early */\n        }\n        let { ib } = ibGib;\n        if (!ib) {\n            throw new Error(`ib or ibGib.ib required (E: d92c26b15fc143977955a167b8b67522)`);\n        }\n        cmdEscapeString ||= DEFAULT_COMMAND_ESCAPE_STRING;\n\n        let text = ibGib.data!.text!;\n        // atow naively looks at start of text. todo: change this to either use a templating engine leveraging lex-gib or natural language processing ai\n\n        // it's either a command that starts with a cmd escape string, or it starts with\n        // the double-dash lines and the name is a boolean flag that is registered as one of\n        // the command identifiers\n        if (text.toLowerCase().startsWith(cmdEscapeString.toLowerCase())) {\n            // yes command\n            return true;\n        } else if (text.startsWith('--')) {\n            // maybe is a command...\n            let firstArg = text.split(' ')[0].slice(2).toLowerCase(); // 2 to slice off -- prefix\n            return RCLI_COMMAND_IDENTIFIERS.includes(firstArg);\n        } else {\n            // definitely not a command\n            return false\n        }\n    }\n    catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    }\n    finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * factory for random app.\n *\n * @see {@link DynamicFormFactoryBase}\n */\nexport class BlankCanvasApp_V1_Factory\n    extends DynamicFormFactoryBase<BlankCanvasAppData_V1, BlankCanvasAppRel8ns_V1, BlankCanvasApp_V1> {\n\n    protected lc: string = `[${BlankCanvasApp_V1_Factory.name}]`;\n\n    getName(): string { return BlankCanvasApp_V1.name; }\n\n    async newUp({\n        data,\n        rel8ns,\n    }: {\n        data?: BlankCanvasAppData_V1,\n        rel8ns?: BlankCanvasAppRel8ns_V1,\n    }): Promise<TransformResult<BlankCanvasApp_V1>> {\n        const lc = `${this.lc}[${this.newUp.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            data ??= clone(DEFAULT_BLANK_CANVAS_APP_DATA_V1);\n            data = data!;\n            rel8ns = rel8ns ?? DEFAULT_BLANK_CANVAS_APP_REL8NS_V1 ? clone(DEFAULT_BLANK_CANVAS_APP_REL8NS_V1) : undefined;\n            data.uuid ||= await getUUID();\n            let { classname } = data;\n\n            const ib = getAppIb({ appData: data, classname });\n\n            const resApp = await factory.firstGen({\n                ib,\n                parentIbGib: factory.primitive({ ib: `app ${classname}` }),\n                data,\n                rel8ns,\n                dna: true,\n                linkedRel8ns: [Rel8n.ancestor, Rel8n.past],\n                nCounter: true,\n                tjp: { timestamp: true },\n            }) as TransformResult<BlankCanvasApp_V1>;\n\n            // replace the newIbGib which is just ib,gib,data,rel8ns with loaded\n            // witness class (that has the witness function on it)\n            const appDto = resApp.newIbGib;\n            let appIbGib = new BlankCanvasApp_V1(undefined, undefined);\n            await appIbGib.loadIbGibDto(appDto);\n            resApp.newIbGib = appIbGib;\n            if (logalot) { console.log(`${lc} appDto: ${pretty(appDto)} (I: ef64d11af48148725913e2fb8c766fd9)`); }\n\n            return resApp as TransformResult<BlankCanvasApp_V1>;\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    async witnessToForm({ witness }: { witness: BlankCanvasApp_V1; }): Promise<DynamicForm> {\n        const lc = `${this.lc}[${this.witnessToForm.name}]`;\n        try {\n            if (logalot) { console.log(`${lc} starting...`); }\n            let { data } = witness;\n            if (!data) { throw new Error(`(UNEXPECTED) witness.data falsy? (E: cc7eb55454585b16044879f207e719ea)`); }\n            // We do the AppFormBuilder specific functions first, because of\n            if (logalot) { console.log(`${lc} data: ${pretty(data)} (I: b2a0e79526d4dfcb9ae38261231b39cf)`); }\n            const idPool = await getIdPool({ n: 100 });\n            // type inference in TS! eesh...\n            const form = new BlankCanvasAppFormBuilder()\n                .with({ idPool })\n                .name({ of: data.name, required: false, })\n                .description({ of: data.description ?? DEFAULT_DESCRIPTION_BLANK_CANVAS_APP })\n                .and<BlankCanvasAppFormBuilder>()\n                .and<AppFormBuilder>()\n                .icon({ iconsList: ['alert'], of: data.icon ?? 'alert', required: true })\n                .and<DynamicFormBuilder>()\n                .uuid({ of: data.uuid, required: true })\n                .classname({ of: data.classname! })\n                .and<WitnessFormBuilder>()\n                .commonWitnessFields({ data })\n                .outputForm({\n                    formName: 'form',\n                    label: 'blank-canvas',\n                });\n            return Promise.resolve(form);\n        } catch (error) {\n            console.error(`${lc} ${extractErrorMsg(error)}`);\n            throw error;\n        } finally {\n            if (logalot) { console.log(`${lc} complete.`); }\n        }\n    }\n\n    async formToWitness({ form }: { form: DynamicForm; }): Promise<TransformResult<BlankCanvasApp_V1>> {\n        // let app = new BlankCanvasApp_V1(null, null);\n        let data: BlankCanvasAppData_V1 = clone(DEFAULT_BLANK_CANVAS_APP_DATA_V1);\n        this.patchDataFromItems({ data, items: form.items, pathDelimiter: DEFAULT_DATA_PATH_DELIMITER });\n        let resApp = await this.newUp({ data });\n        return resApp;\n    }\n\n}\n", "import { APIFunctionInfo } from \"@ibgib/web-gib/dist/api/api-types.mjs\";\nimport { updateCSSVariablesFunctionInfo } from '@ibgib/web-gib/dist/api/commands/ui/update-css-variables.mjs';\n\nexport const UIAgentFunctionInfos: APIFunctionInfo<any>[] = [\n    updateCSSVariablesFunctionInfo,\n];\n", "import { extractErrorMsg, pretty } from \"@ibgib/helper-gib/dist/helpers/utils-helper.mjs\";\nimport { APIFunctionInfo } from \"@ibgib/web-gib/dist/api/api-types.mjs\";\nimport { COMMAND_BASE_SCHEMA_PROPERTIES } from \"@ibgib/web-gib/dist/api/commands/command-constants.mjs\";\nimport { getCommandService } from \"@ibgib/web-gib/dist/api/commands/command-service-v1.mjs\";\nimport { CommandDataBase } from \"@ibgib/web-gib/dist/api/commands/command-types.mjs\";\nimport { FUNCTION_CALL_EXAMPLES_HEADER } from \"@ibgib/web-gib/dist/api/api-constants.mjs\";\n\nimport { GLOBAL_LOG_A_LOT } from \"../../../constants.mjs\";\nimport { GEMINI_SCHEMA_WEB1_PAGE } from \"../../../components/web1/web1-constants.mjs\";\n\nconst logalot = GLOBAL_LOG_A_LOT;\n\n// #region constants\nconst EXAMPLE_INPUT_FETCH_HOME: Partial<FetchWeb1PageOpts> = {\n    page: 'home',\n    notesToSelf: 'Example of a fetchWeb1Page function call to go to the home page. This is only an example to show the shape of the function call.',\n    repromptWithResult: true,\n};\n\nconst EXAMPLES = [\n    // `\\`\\`\\`typescript\\n${FUNCTION_CALL_EXAMPLES_HEADER}\\n${pretty(EXAMPLE_INPUT_FETCH_HOME)}\\n\\`\\`\\``,\n    FUNCTION_CALL_EXAMPLES_HEADER,\n    pretty(EXAMPLE_INPUT_FETCH_HOME),\n].join('\\n');\n// #endregion constants\n\n\n/**\n * @interface CommandResultBase - Base interface for command results.\n *\n * ## notes\n *\n * I'm adding this after already having created several existing commands in\n * order to include an errorMsg. I want commands to return info about errors and\n * not re-throw. I am not integrating this with all existing commands at this\n * time though, so there will be some irregularity.\n *\n * I did go ahead and change the code in the command service to return\n * `{errorMsg}` if an exception is thrown.\n */\nexport interface CommandResultBase {\n    /**\n     * IIF the command errors out, this will be populated.\n     */\n    errorMsg?: string;\n}\n\n/**\n * @interface FetchWeb1PageOpts - Options for the fetchWeb1Page command.\n * @extends CommandDataBase\n */\nexport interface FetchWeb1PageOpts extends CommandDataBase<'agent', ['fetchWeb1Page']> {\n    /**\n     * e.g. \"home\", \"funding\", \"faq\", etc.\n     */\n    page: string;\n}\n\nexport interface FetchWeb1PageResult extends CommandResultBase {\n    htmlTemplate: string;\n    /**\n     * Optional additional info about html\n     */\n    htmlDescription?: string;\n    // cssContents: string;\n}\n\n/**\n * @interface FetchWeb1PageCommandData - Command data for the fetchWeb1Page command.\n * @extends CommandDataBase\n */\nexport interface FetchWeb1PageCommandData extends CommandDataBase<'agent', ['fetchWeb1Page']> {\n    /**\n     * e.g. \"home\", \"funding\", \"faq\", etc.\n     */\n    page: string;\n}\n\n/**\n * Wrapper function to enqueue the fetchWeb1Page command.\n * @param {FetchWeb1PageOpts} opts - Options for telling the user something.\n * @returns {Promise<void>} A promise that resolves when the command is enqueued.\n */\nfunction fetchWeb1PageViaCmd(opts: FetchWeb1PageOpts): Promise<FetchWeb1PageResult> {\n    const commandService = getCommandService();\n    const command: FetchWeb1PageCommandData = {\n        cmd: 'agent',\n        cmdModifiers: ['fetchWeb1Page'],\n        page: opts.page,\n        repromptWithResult: opts?.repromptWithResult,\n        notesToSelf: opts?.notesToSelf,\n    };\n    return new Promise<FetchWeb1PageResult>((resolve, reject) => {\n        commandService.enqueueCommand({ command, resolve, reject });\n    });\n}\n\n/**\n * Implementation function for the fetchWeb1Page command (atow, does nothing other than resolve).\n * @param {FetchWeb1PageOpts} opts - Options for telling the user something.\n * @returns {Promise<void>} A promise that resolves when the command is executed (immediately).\n */\nasync function fetchWeb1PageImpl(opts: FetchWeb1PageOpts): Promise<FetchWeb1PageResult> {\n    const lc = `[${fetchWeb1PageImpl.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: genuuid)`); }\n\n        const { page } = opts;\n\n        if (page === \"links\") {\n\n            console.warn(`${lc} doing custom \"links\" web1 page response. (W: 4f9db37ee1e7497e94cec948cc975825)`);\n\n            const pageHtmlPath = `/apps/web1/gib/link-gib/dist/index.html`;\n            const htmlTemplate = await fetch(pageHtmlPath).then(res => res.text());\n\n            const linksPath = `/apps/web1/gib/link-gib/dist/links.mjs`;\n            const linksSrc = await fetch(linksPath).then(res => res.text());\n\n            const htmlDescription = `For the web 1.0 links page, I use an older site of mine embedded in an iframe. So the htmlTemplate here is the html for that embedded site's index.html. But that really is driven by LinkEntry[] which are in code. Here is the data for those entries... (NOTE: You do not need to run this code. Just read the information in the link entries):\\n${linksSrc}`;\n\n            return {\n                htmlTemplate,\n                htmlDescription,\n            }\n        } else {\n            const pageHtmlPath = `/components/web1/${page}/${page}.html`;\n            const htmlTemplate = await fetch(pageHtmlPath).then(res => res.text());\n            if (htmlTemplate === undefined) { throw new Error(`htmlTemplate is undefined for path (${pageHtmlPath}) (E: a78ce17f4321318c8b920b5c1e7e7a25)`); }\n\n            return {\n                htmlTemplate,\n                htmlDescription: `This is the html for the page. Remember to just keep it very terse: one or two *brief* sentences. If there is anything the user wants, they will ask for it later. Let the page itself do the talking.`\n            }\n        }\n    } catch (error) {\n        const errorMsg = `${lc} ${extractErrorMsg(error)}`;\n        console.error(errorMsg);\n        throw new Error(errorMsg);\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n\n/**\n * API function info for the fetchWeb1Page command.\n */\nexport const fetchWeb1PageFunctionInfo: APIFunctionInfo<typeof fetchWeb1PageViaCmd> = {\n    nameOrId: 'fetchWeb1Page',\n    fnViaCmd: fetchWeb1PageViaCmd,\n    functionImpl: fetchWeb1PageImpl,\n    cmd: 'agent',\n    cmdModifiers: ['fetchWeb1Page'],\n    schema: {\n        name: 'fetchWeb1Page',\n        description: `Use this function to get the HTML of a web 1.0 page. So if a user asks about a certain web 1.0 page, you can use this to retrieve the contents. The one page that doesn't really work is the \"links\" page which is actually an iframe. This stems from this page being an older page of mine. Just say it contains \\n\\n${EXAMPLES}`,\n        parameters: {\n            type: 'object',\n            properties: {\n                ...COMMAND_BASE_SCHEMA_PROPERTIES,\n                page: GEMINI_SCHEMA_WEB1_PAGE,\n            },\n            required: ['page'],\n        },\n    },\n};\n", "import { APIFunctionInfo } from \"@ibgib/web-gib/dist/api/api-types.mjs\";\n\nimport { minigameBuilderEditStimuliFunctionInfo } from \"./minigame-builder-edit-stimuli.mjs\";\nimport { minigameBuilderStartFunctionInfo } from \"./minigame-builder-start.mjs\";\nimport { minigameBuilderValidateAndReadyFunctionInfo } from \"./minigame-builder-validate-and-ready.mjs\";\n\nexport const MinigameFunctionInfos: APIFunctionInfo<any>[] = [\n    minigameBuilderStartFunctionInfo,\n    minigameBuilderEditStimuliFunctionInfo,\n    minigameBuilderValidateAndReadyFunctionInfo,\n];\n", "/**\n * @module function-infos.web.mts\n *\n * Web app-specific function infos, as opposed to extension or other function\n * infos.\n *\n * funky structure because AllFunctionInfos started as just a global constant,\n * but when broke out extension, we needed to separate web extension function\n * infos from web app function infos.\n */\n\nimport { extractErrorMsg } from \"@ibgib/helper-gib/dist/helpers/utils-helper.mjs\";\nimport { APIFunctionInfo } from \"@ibgib/web-gib/dist/api/api-types.mjs\";\nimport { registerDeprecatedFunctionInfoName, registerFunctionInfos } from \"@ibgib/web-gib/dist/api/api-index.mjs\";\nimport { IbGibAPIFunctionInfos } from \"@ibgib/web-gib/dist/api/commands/ibgib/ibgib-index.mjs\";\nimport { ChatAPIFunctionInfos } from \"@ibgib/web-gib/dist/api/commands/chat/chat-index.mjs\";\nimport { TextAPIFunctionInfos } from \"@ibgib/web-gib/dist/api/commands/text/text-index.mjs\";\n\nimport { GLOBAL_LOG_A_LOT } from \"../constants.mjs\";\nimport { RenderAgentFunctionInfos } from \"./commands/renderable/renderable-index.mjs\";\nimport { UIAgentFunctionInfos } from \"./commands/ui/ui-index.mjs\";\nimport { fetchWeb1PageFunctionInfo } from \"./commands/website/fetch-web1-page.mjs\";\nimport { MinigameFunctionInfos } from \"./commands/minigame/minigame-index.mjs\";\n\nconst logalot = GLOBAL_LOG_A_LOT;\n\n/**\n * Map of all available API functions for agents.\n *\n * NOTE: Any and all functions should be added to this.\n */\n// export const AllFunctionInfos: { [nameOrId: string]: APIFunctionInfo<any> } = {\n//     ...RenderAgentFunctionInfos.reduce((acc, info) => ({ ...acc, [info.nameOrId]: info }), {}),\n// }\n\nconst AllFunctionInfos_Web: Map<string, APIFunctionInfo<any>> = new Map([\n    ...ChatAPIFunctionInfos,\n    ...TextAPIFunctionInfos,\n\n    fetchWeb1PageFunctionInfo,\n\n    ...RenderAgentFunctionInfos,\n    ...UIAgentFunctionInfos,\n    ...IbGibAPIFunctionInfos,\n    ...MinigameFunctionInfos,\n].map(x => [x.nameOrId, x]));\n\nconst DeprecatedFunctionInfoNames_Web: string[] = [\n    'minigameBuilderAddStimuli',\n    // 'minigameBuilderEditStimuli', // debug only...this is a valid function and this needs to be removed from this list. i'm just trying to cause the prune action to happen for debugging.\n];\n\n/**\n * This should be called early on when initializing the web app.\n */\nexport function registerDeprecatedFunctionNamesAndFunctionInfos_Web(): void {\n    const lc = `[${registerDeprecatedFunctionNamesAndFunctionInfos_Web.name}]`;\n    try {\n        if (logalot) { console.log(`${lc} starting... (I: 31efff44c2be8ac45dac33d8824c4c25)`); }\n\n        for (const nameOrId of DeprecatedFunctionInfoNames_Web) {\n            registerDeprecatedFunctionInfoName({ nameOrId });\n        }\n\n        registerFunctionInfos({ functionInfos: AllFunctionInfos_Web });\n    } catch (error) {\n        console.error(`${lc} ${extractErrorMsg(error)}`);\n        throw error;\n    } finally {\n        if (logalot) { console.log(`${lc} complete.`); }\n    }\n}\n", "/**\n * @module bootstrap does the startup code for ibgib-specific things, like\n * initializing the metaspace and starting the blank-gib app.\n */\n\nimport { bootstrapIbGibApp } from \"@ibgib/web-gib/dist/app-bootstrap/bootstrap.mjs\";\n\nimport {\n    APP_CONFIG, GLOBAL_LOG_A_LOT,\n    TAG_AGENT_TEXT, TAG_AGENT_ICON, TAG_AGENT_DESCRIPTION,\n    BLANK_GIB_INDEXEDDB_LOCAL_SPACE_NAME_PREFIX\n} from \"./constants.mjs\";\nimport { getIbGibGlobalThis_BlankGib } from \"./helpers.web.mjs\";\nimport { BlankCanvasApp_V1 } from \"./witness/app/blank-canvas/blank-canvas-app-v1.mjs\";\nimport { PARAM_INFOS } from \"./witness/app/blank-canvas/blank-canvas-constants.mjs\";\nimport { DEFAULT_BLANK_CANVAS_APP_DATA_V1 } from \"./witness/app/blank-canvas/blank-canvas-types.mjs\";\nimport { AUTO_GENERATED_VERSION } from \"./AUTO-GENERATED-version.mjs\";\nimport { registerDeprecatedFunctionNamesAndFunctionInfos_Web } from \"./api/function-infos.web.mjs\";\nimport { getAppShellSvc } from \"./ui/shell/app-shell-service.mjs\";\n\nconsole.log(`[blank gib bootstrap] version: ${AUTO_GENERATED_VERSION}`);\n\n/**\n * Idempotent bootstrap function for the blank-gib app.\n * Checks the ibgib globalThis to prevent double-initialization.\n */\nexport async function bootstrapBlankCanvasApp() {\n\n    await bootstrapIbGibApp({\n        config: APP_CONFIG,\n        getGlobalThis: getIbGibGlobalThis_BlankGib,\n        AppClass: BlankCanvasApp_V1,\n        defaultAppData: DEFAULT_BLANK_CANVAS_APP_DATA_V1,\n        paramInfos: PARAM_INFOS,\n        registerAgentFunctionInfos: registerDeprecatedFunctionNamesAndFunctionInfos_Web,\n        ensureTags: [\n            { text: TAG_AGENT_TEXT, icon: TAG_AGENT_ICON, description: TAG_AGENT_DESCRIPTION }\n        ],\n        localSpaceNamePrefix: BLANK_GIB_INDEXEDDB_LOCAL_SPACE_NAME_PREFIX,\n        onReady: async (app) => {\n            if (GLOBAL_LOG_A_LOT) { console.log(`[bootstrapBlankCanvasApp] Engine ready. app: ${app?.ib}`); }\n            getAppShellSvc().onEngineReady();\n        },\n    });\n}\n"],
  "mappings": "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",
  "names": ["logalot", "getValueFromRawString", "paramInfo", "valueString", "lc", "castedValue", "argValueInt", "error", "extractErrorMsg", "__name", "getParamInfo", "argIdentifier", "paramInfos", "throwIfNotFound", "lc", "filteredParamInfos", "p", "clone", "error", "extractErrorMsg", "__name", "parseRawArg", "rawArg", "logalot", "fnGetQuoteType", "s", "fnStripQuotes", "rawArgQuoteMaybe", "regexp", "regExpMatch", "_entireArg", "prefix", "identifier", "possiblyQuotedValue", "valueQuoteMaybe", "bareArg", "argIs", "arg", "paramInfo", "argInfoIndex", "rawArgInfo", "PARAM_INFO_BARE", "x", "buildArgInfos", "args", "bareArgParamInfo", "localLogalot", "nonPositionalBareArgFound", "argIndex", "valueString", "argInfo", "isNameValuePair", "valueInfo", "getValueFromRawString", "pretty", "StatusCode", "OuterSpaceOptionsCmdModifier", "IbGibSpaceOptionsCmdModifier", "SyncSpaceOptionsCmdModifier", "EncryptionMethod", "VALID_ENCRYPTION_METHODS", "As", "Ssml", "_Ssml", "__name", "paras", "addParaTags", "agg", "p", "ssml", "text", "pronunciation", "alphabet", "level", "rate", "pitch", "volume", "lc", "attrs", "rateText", "pitchText", "pitchNum", "volumeText", "volumeNum", "speechCon", "effect", "s", "srcUrl", "strength", "ms", "alias", "partOfSpeech", "interpret", "format", "As", "error", "logalot", "LexCapitalize", "LexLineConcat", "Lex", "_Lex", "__name", "data", "defaultLanguage", "requestLanguage", "defaultLineConcat", "defaultDelim", "defaultCapitalize", "defaultKeywordMode", "defaultPropsMode", "id", "language", "specifier", "keywords", "keywordMode", "lineIndex", "lineConcat", "lineConcatDelim", "capitalize", "vars", "ssmlVars", "props", "propsMode", "fnDatumPredicate", "lc", "logalot", "lexData", "lexDatum", "textLines", "text", "ssmlLines", "ssml", "error", "results", "ids", "i", "matchingDatums", "d", "opts", "resultAs", "useLineIndex", "Ssml", "lines", "replaceVarsSingleLine", "line", "varNames", "l", "varName", "regex", "replaceRefsSingleLine", "match", "template", "idAndOptions", "options", "replacementResult", "replacement", "replaceAt", "s", "upperText", "upperSsml", "iFirstLetter", "lowerText", "lowerSsml", "firstLine", "lineType", "concatSsmlP", "pTag", "lastChar", "sTag", "result", "kw", "kwDatum", "kwArg", "dKeywords", "x", "propsFilter", "propName", "propFn", "dPropValue", "propsFn", "totalWeight", "agg", "item", "randomNumber", "runningWeight", "AtomicId", "SemanticId", "toLexDatums_Semantics", "semanticId", "texts", "t", "__name", "toLexDatums_Atomics", "atomicId", "DEFAULT_HUMAN_LEX_DATA_ENGLISH_SEMANTICS", "DEFAULT_HUMAN_LEX_DATA_ENGLISH_ATOMICS", "DEFAULT_HUMAN_LEX_DATA_ENGLISH", "DEFAULT_HUMAN_LEX_DATA", "clone", "DEFAULT_USER_LEX_DATA", "DEFAULT_USER_LEX", "Lex", "DEFAULT_ROBBOT_LEX_DATA", "Ssml", "logalot", "validateCommonRobbotData", "robbotData", "lc", "logalot", "errors", "name", "uuid", "classname", "outputPrefix", "outputSuffix", "ROBBOT_NAME_REGEXP", "UUID_REGEXP", "ROBBOT_PREFIX_SUFFIX_REGEXP", "error", "__name", "validateCommonRobbotIbGib", "robbotIbGib", "intrinsicErrors", "validateIbGibIntrinsically", "ibErrors", "robbotClassname", "robbotName", "robbotId", "parseRobbotIb", "dataErrors", "result", "parseRobbotIb", "robbotIb", "lc", "pieces", "error", "__name", "createNewRobbot", "fnPromptRobbot", "ibgibs", "space", "logalot", "resRobbot", "newRobbot", "delay", "allIbGibs", "x", "i", "ibGib", "validationErrors", "validateIbGibIntrinsically", "pretty", "persistTransformResult", "zeroSpace", "fnBroadcast", "fnUpdateBootstrap", "registerNewIbGib", "rel8ToSpecialIbGib", "ROBBOT_REL8N_NAME", "SECRET_REL8N_NAME", "logalot", "getSrcLocalSpaceId", "participants", "lc", "logalot", "participants_src", "x", "error", "extractErrorMsg", "__name", "logalot", "MetaspaceBase", "_MetaspaceBase", "__name", "lock", "localSpaceId", "lc", "bootstrapIbGib", "getValidatedBootstrapIbGib", "getLocalSpace", "spaceDto", "error", "localSpaces", "BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY", "localSpaceIds", "i", "localSpace", "id", "ids", "getUUID", "newupSubject", "cacheSvc", "GLOBAL_TIMER_NAME", "metaspaceFactory", "spaceName", "getFnAlert", "getFnPrompt", "getFnPromptPassword", "timerName", "ROOT", "SpecialIbGibType", "zeroSpace", "getGib", "bootstrapAddr", "BOOTSTRAP_IBGIB_ADDR", "execInSpaceWithLocking", "DEFAULT_SECONDS_VALID_LOCAL", "opts", "fnLocalSpaceFactory", "allowCancel", "createBootstrap", "newLocalSpace", "updateBootstrapIbGib", "argPutUserSpace", "getSpaceArgMetadata", "getIbGibAddr", "resZeroSpace", "resPutUserSpaceInUserSpace", "text", "icon", "description", "space", "createTagIbGibAndSundry", "x", "ibGib_Context", "rel8nName_Context", "addr", "trash", "archive", "key", "getConfigAddr", "newSpace", "info", "setConfigAddr", "delay", "roots", "currentRootAddr", "resCurrentRoot", "root", "setCurrentRoot", "ibGib", "linked", "rel8nName", "rel8ToCurrentRoot", "type", "ibGibsToRel8", "ibGibsToUnRel8", "addrsToUnRel8", "severPast", "deletePreviousSpecialIbGib", "rel8ToSpecialIbGib", "ibGibAddr", "registerNewIbGib", "tjpIbGib", "useCache", "isPrimitive", "spaceId", "parseSpaceIb", "latestSpace", "latestIbGib", "tjpAddr", "latestAddr", "resLatestIbGib", "resTransform", "force", "persistTransformResult", "addrs", "isDna", "getFromSpace", "ibGibs", "putInSpace", "deleteFromSpace", "getDependencyGraph", "tjp", "resGetLatest", "getLatestAddrs", "latestAddrsMap", "keys", "emsg", "pretty", "naive", "getTjpIbGib", "initialize", "dontWarnIfNotExist", "getSpecialIbGib", "value", "getSpecialRel8dIbGibs", "secretIbGibs", "fnPromptPassword", "dontPrompt", "checkCacheFirst", "cacheAfter", "erroredDueToPromptTimeout", "tries", "secretsCacheKey", "cachedPassword", "secretInfos", "secretIbGib", "secretInfo", "separator", "secretInfosMsgBlock", "title", "msg", "password", "plaintext", "encryptionIbGib", "confirm", "persist", "ibRoot", "publicIbMetadata", "publicMetadata", "encryptionInfo", "EncryptionMethod", "resEncrypt", "encrypt", "data", "constantIbGib", "CIPHERTEXT_ATOM", "ciphertextIbGib", "encryptionAddr", "resEncryption", "defaultIndexingMode", "DEFAULT_ALPHABET_INDEXING_MODE_BLOCKMODE", "DEFAULT_ALPHABET_INDEXING_MODE_LEGACY", "resDecrypt", "decrypt", "DEFAULT_ENCRYPTION_INITIAL_RECURSIONS", "DEFAULT_ENCRYPTION_RECURSIONS_PER_HASH", "DEFAULT_ENCRYPTION_SALT_STRATEGY", "DEFAULT_ENCRYPTION_HASH_ALGORITHM", "cacheKey", "entry", "secretPassword", "tempMetaPassword", "salt", "encryptedPassword", "fnPromptSecret", "fnPromptEncryption", "fnPromptOuterSpace", "createdSecret", "createdEncryption", "createdOuterspace", "alert", "SECRET_REL8N_NAME", "encryptionIbGibs", "ENCRYPTION_REL8N_NAME", "outerspaceIbGibs", "SYNC_SPACE_REL8N_NAME", "outerspaceIbGib", "createIfNone", "fnPromptRobbot", "appRobbots_MaybeOutOfDate", "ROBBOT_REL8N_NAME", "appRobbots", "robbotIbGib", "robbotAddr", "resGet", "errors", "validateCommonRobbotIbGib", "createNewRobbot", "fnPromptApp", "appApps_MaybeOutOfDate", "APP_REL8N_NAME", "appApps", "appIbGib", "appAddr", "createNewApp", "dependencyGraphIbGibs", "syncSpaceIbGibs", "sagaId", "syncStatus$", "syncTimelogName", "fnObs", "status", "StatusCode", "_", "localUserSpace", "participants", "s", "multiSpaceOpId", "allSagaInfos", "startSyncPromises", "syncSpace", "sagaInfo", "toUnsubscribe", "subscriptions", "sub", "err", "syncSagaInfos_NotComplete", "allIbGibsToSync", "syncAddrs_All", "syncAddrs_All_WithTjps", "hasTjp", "syncAddrs_All_AreTjps", "GIB", "syncAddrs_All_WithoutTjps", "syncSagaInfo", "syncIbGibs_All", "syncAddrs_All_Tjps", "syncAddrs_All_NonTjps", "argStartSync", "resStartSync", "infos", "getSrcLocalSpaceId", "statusCode", "registerLatestInTimelines", "ibGibsToRegister", "timelines", "getTimelinesGroupedByTjp", "timeline", "latestIbGibInTimeline", "newLatestIbGibs", "warnIfMultipleLocalTimelines", "result", "ibGibsWithTjp_Ungrouped", "GIB_DELIMITER", "ibGibsWithTjp_GroupedByTjpGib", "groupBy", "getGibInfo", "tjpGibs", "group", "nCounts", "ibGibFrame", "n", "count", "latestIbGibInGroup", "a", "b", "tjpIbGibs", "wonkyTjpAddrs", "tjpAddrs", "notAlreadySyncingTjpAddrs", "autosyncsIbGib", "alreadySyncing", "AUTOSYNC_ALWAYS_REL8N_NAME", "notAlreadySyncingTjps", "tjpAddrsToRemove", "uniqueTjpAddrsToRemove", "tjpsToRemove", "IBGIB_BASE_DIR", "IBGIB_ENCODING", "IBGIB_BASE_SUBPATH", "IBGIB_SPACE_SUBPATH_DEFAULT", "IBGIB_SPACE_NAME_DEFAULT", "IBGIB_IBGIBS_SUBPATH", "IBGIB_META_SUBPATH", "IBGIB_BIN_SUBPATH", "IBGIB_DNA_SUBPATH", "IBGIB_LONG_SUBPATH", "DEFAULT_FILESYSTEM_SPACE_DESCRIPTION", "DEFAULT_LONG_PATH_LENGTH", "DEFAULT_PATH_SEPARATOR", "ARBITRARY_IB_SUBSTRING_LENGTH_FOR_MITIGATE_LONG_PATH", "getFnPrompt", "title", "msg", "lc", "answer", "promptForText", "error", "extractErrorMsg", "__name", "logalot", "SpaceBase_V1", "_SpaceBase_V1", "WitnessBase_V1", "__name", "initialData", "initialRel8ns", "arg", "lc", "cmd", "cmdModifiers", "IbGibSpaceOptionsCmd", "opts", "graph", "getDependencyGraph", "ibGibs", "resultData", "getIbGibAddr", "error", "extractErrorMsg", "errors", "ibGibAddrs", "ibGibAddrsLength", "ibGibsLength", "ibGibAddrsCopy", "i", "ibGib", "intrinsicErrors", "validateIbGibIntrinsically", "addr", "x", "xAddr", "xIndex", "argData", "ibMetadata", "noTimestamp", "argy_", "result", "resulty_", "getSpaceResultMetadata", "logalot", "DEFAULT_FILESYSTEM_SPACE_DATA_V1", "ZERO_SPACE_ID", "IBGIB_SPACE_NAME_DEFAULT", "IBGIB_BASE_DIR", "IBGIB_ENCODING", "IBGIB_BASE_SUBPATH", "IBGIB_SPACE_SUBPATH_DEFAULT", "IBGIB_IBGIBS_SUBPATH", "IBGIB_META_SUBPATH", "IBGIB_BIN_SUBPATH", "IBGIB_DNA_SUBPATH", "IBGIB_LONG_SUBPATH", "DEFAULT_LONG_PATH_LENGTH", "DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS", "DEFAULT_FILESYSTEM_SPACE_DESCRIPTION", "FilesystemSpace_V1", "_FilesystemSpace_V1", "SpaceBase_V1", "__name", "initialData", "initialRel8ns", "clone", "DEFAULT_FILESYSTEM_SPACE_DATA_V1", "arg", "lc", "errors", "error", "extractErrorMsg", "logalot", "IBGIB_BASE_DIR", "IBGIB_ENCODING", "IBGIB_BASE_SUBPATH", "IBGIB_SPACE_SUBPATH_DEFAULT", "IBGIB_IBGIBS_SUBPATH", "IBGIB_META_SUBPATH", "IBGIB_BIN_SUBPATH", "IBGIB_DNA_SUBPATH", "getSpaceIb", "getGib", "addr", "isPrimitive", "getIbAndGib", "ibGib", "cached", "resultIbGibs", "resultData", "getIbGibAddr", "notFoundIbGibAddrs", "ibGibAddrs", "isDna", "binAddrs", "isBinary", "ibGibAddrsNonBin", "i", "getResult", "binHash", "binExt", "getBinHashAndExt", "emsg", "result", "warnings", "addrsErrored", "force", "ibGibs", "addrsAlreadyHave", "putResult", "addrsDeleted", "deleteResult", "warningMsg", "latestAddrs", "addrsNotFound", "latestAddr", "pretty", "ibGibAddr", "ib", "gib", "gibInfo", "getGibInfo", "tjpGib", "metaStoneAddrs", "metaStoneAddrsAndIbInfos_descending", "xAddr", "metaStoneIb", "parseMetaStoneIb", "a", "b", "_aAddr", "aInfo", "_bAddr", "bInfo", "latestMetaStoneAddr", "latestMetaStoneInfo", "latestMetaStoneIbGib", "validateCommonMetaStoneIbGib", "META_STONE_TARGET_REL8N_NAME", "ROOT", "argPersist", "argy_", "x", "resPut", "keyPermissionRequested", "viaTargetAddr", "viaTargetTjpGib", "viaMetaStoneAddr", "pathSeparator", "DEFAULT_PATH_SEPARATOR", "baseSubPath", "spaceSubPath", "ibgibsSubPath", "isBin", "ensureMetaStonePaths", "pretendItsALongPath", "addrIsForAMetaStone", "data", "resPath", "addrIsAMetaStone", "isMetaStone", "gibPieces", "GIB_DELIMITER", "targetTjpGib", "punctiliarHash", "mitigateLongPaths", "longPathLength", "ext", "filenameAsIbPlusExt", "filenameAsAddrPlusExt", "ameliorateLongPathMsg", "shorterFilenamePlusExt", "resAdjustedFilenameExtSubpath", "longSubPath", "IBGIB_LONG_SUBPATH", "firstFourOfIbHash", "hash", "ibSubstring", "ARBITRARY_IB_SUBSTRING_LENGTH_FOR_MITIGATE_LONG_PATH", "DEFAULT_WEB_FILESYSTEM_SPACE_DATA_V1", "ZERO_SPACE_ID", "IBGIB_SPACE_NAME_DEFAULT", "getGlobalDbName", "IBGIB_ENCODING", "IBGIB_BASE_SUBPATH", "IBGIB_SPACE_SUBPATH_DEFAULT", "IBGIB_IBGIBS_SUBPATH", "IBGIB_META_SUBPATH", "IBGIB_BIN_SUBPATH", "IBGIB_DNA_SUBPATH", "IBGIB_LONG_SUBPATH", "DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS", "DEFAULT_FILESYSTEM_SPACE_DESCRIPTION", "FileEncoding", "FILE_ENCODINGS", "B2TFS_DEFAULT_ENCODINGS_TO_TRY", "logalot", "GLOBAL_LOG_A_LOT", "pathUtils", "PathUtilsHelper", "tryRead", "path", "directory", "encoding", "lc", "fullPath", "resRead", "resRead_uncasted", "readFile", "uint8ArrayToString", "error", "extractErrorMsg", "__name", "tryRead_bin", "encodingsToTry", "unique", "FILE_ENCODINGS", "dataBuffer", "dataString", "inputPath", "detectedEncoding", "getFileDataAndEncoding", "getFileDataAndEncoding", "inputPath", "encodingsToTry", "B2TFS_DEFAULT_ENCODINGS_TO_TRY", "lc", "logalot", "pretty", "resRead", "readFile", "FileEncoding", "resRead_str", "uint8ArrayToString", "error", "emsg", "extractErrorMsg", "__name", "parseFullPath", "fullPath", "pieces", "dbName", "getGlobalDbName", "storeName", "key", "writeFile", "data", "encoding", "storagePut", "opts", "storageGet", "rm", "pathToRm", "storageRmRF", "readdir", "containingDir", "opts", "lc", "dbName", "storeName", "dirPath", "parseFullPath", "storageReaddir", "__name", "logalot", "GLOBAL_LOG_A_LOT", "pathUtils", "PathUtilsHelper", "WebFilesystemSpace_V1", "_WebFilesystemSpace_V1", "FilesystemSpace_V1", "__name", "initialData", "initialRel8ns", "clone", "DEFAULT_WEB_FILESYSTEM_SPACE_DATA_V1", "lc", "dto", "space", "arg", "errors", "error", "extractErrorMsg", "IBGIB_ENCODING", "IBGIB_BASE_DIR", "IBGIB_SPACE_SUBPATH_DEFAULT", "IBGIB_IBGIBS_SUBPATH", "IBGIB_META_SUBPATH", "IBGIB_BIN_SUBPATH", "IBGIB_DNA_SUBPATH", "IBGIB_LONG_SUBPATH", "getSpaceIb", "getGib", "ibGib", "isDna", "result", "thisData", "path", "data", "addr", "getIbGibAddr", "isBin", "isBinary", "fullPath", "encoding", "writeFile", "bareIbGib", "toDto", "errorMsg", "rm", "ib", "getIbAndGib", "addrIsBin", "addrMightBeDna", "x", "pathsToLook", "isMetaStone", "resRead", "binEncoding", "binHash", "parseBinIb", "gib", "tryPath", "tryRead_bin", "binIbGib", "tryRead", "paths", "ibGibAddr", "tjpGib", "fnFilterIb", "pathSansBaseDir", "containingDir", "getGibInfo", "fnFilter", "s", "META_STONE_ATOM", "filenames", "readdir", "dotExt", "dotExtLength", "metaStoneAddrs", "ibIsh", "gibPlusExt", "IBGIB_DELIMITER", "addrPlusExt", "metaStoneAddr", "i", "basicErrors", "validateIbGibAddr", "metaStoneErrors", "validateCommonMetaStoneIb", "fnCreateNewLocalSpace", "__name", "allowCancel", "spaceName", "logalot", "lc", "spaceNameIsValid", "resName", "getFnPrompt", "getUUID", "now", "timestamp", "getTimestamp", "timestampMs", "newLocalSpace", "WebFilesystemSpace_V1", "IBGIB_BASE_DIR", "IBGIB_BASE_SUBPATH", "IBGIB_BIN_SUBPATH", "IBGIB_DNA_SUBPATH", "IBGIB_IBGIBS_SUBPATH", "IBGIB_META_SUBPATH", "IBGIB_ENCODING", "PERSIST_OPTS_AND_RESULTS_IBGIBS_DEFAULT", "DEFAULT_LOCAL_SPACE_DESCRIPTION", "DEFAULT_LOCAL_SPACE_POLLING_INTERVAL_MS", "pretty", "getGib", "toDto", "GIB", "error", "extractErrorMsg", "fnDtoToSpace_webFilesystem", "spaceDto", "logalot", "GLOBAL_LOG_A_LOT", "NAIVE_SPACE_CACHE", "ZERO_SPACE_CACHE_ADDR", "STORES_CONFIRMED", "Metaspace_Webspace", "_Metaspace_Webspace", "MetaspaceBase", "__name", "lc", "zeroSpace", "cacheSvc", "GLOBAL_TIMER_NAME", "metaspaceFactory", "opts", "createdSpace", "fnCreateNewLocalSpace", "storeNameForSpace", "storageCreateStoreIfNotExist", "getGlobalDbName", "spaceAddr", "getIbGibAddr", "spaceDto", "resSpace", "fnDtoToSpace_webFilesystem", "WebFilesystemSpace_V1", "error", "extractErrorMsg", "args", "lock", "localSpaceId", "space", "validateIbGibIntrinsically", "execInSpaceWithLocking", "bootstrapIbGibApp", "opts", "lc", "logalot", "ibGibGlobalThis", "resolve", "reject", "args", "paramInfos", "paramInfosErrors", "validateParamInfos", "argInfos", "buildArgInfos", "validationErrors", "execFromArgs", "error", "getApp", "__name", "extractErrorMsg", "metaspace", "initMetaspace", "ibgibGlobalThis_core", "getIbGibGlobalThis_IbGib", "ibgibGlobalThis", "ensureTagsExist", "resRequestCommentIbGib", "createRequestCommentIbGib_Common", "proxy", "LiveProxyIbGib", "execInteractive", "Metaspace_Webspace", "localSpaceNameKey", "existingLocalSpaceName", "storageGet", "prefix", "spaceName", "generateLocalSpaceName", "title", "msg", "alertUser", "promptForText", "promptForSecret", "name", "pickRandom_Letters", "SPACE_NAME_REGEXP", "localUserSpace", "app", "defaultGetOrCreateApp", "AppClass", "defaultAppData", "onBeforeCreate", "onAppLoaded", "space", "appsIbGib", "SpecialIbGibType", "appAddrs", "APP_REL8N_NAME", "addr", "ib", "getIbAndGib", "getInfoFromAppIb", "appAddr", "isNew", "createAndSaveNewApp", "getIbGibAddr", "list", "a", "idx", "retry", "response", "parsed", "resGet", "getFromSpace", "witness", "createNewApp", "data", "clone", "getUUID", "rel8ns", "classname", "getAppIb", "Factory_V1", "Rel8n", "tags", "tagIbGibs", "TAG_REL8N_NAME", "tag", "x", "interpretedArgInfos", "text", "getTimestamp", "errors", "identifiers", "p", "AppSpaceRel8n", "AppCmd", "logalot", "isPic", "ibGib", "lc", "logalot", "ib", "data", "rel8ns", "ancestors", "error", "__name", "logalot", "AppBase_V1", "_AppBase_V1", "WitnessWithContextBase_V1", "__name", "initialData", "initialRel8ns", "arg", "lc", "result", "isArg", "error", "extractErrorMsg", "ibGib", "isCommand", "getErrorIbGib", "AppCmd", "isComment", "isPic", "validateCommonAppData", "argData", "ibMetadata", "noTimestamp", "ibGibs", "argy_", "resultData", "resulty_", "DEFAULT_UUID_BLANK_CANVAS_APP", "DEFAULT_NAME_BLANK_CANVAS_APP", "DEFAULT_DESCRIPTION_BLANK_CANVAS_APP", "DEFAULT_BLANK_CANVAS_APP_DATA_V1", "DEFAULT_COMMAND_ESCAPE_STRING", "DEFAULT_BLANK_CANVAS_APP_REL8NS_V1", "logalot", "GLOBAL_LOG_A_LOT", "validateArgInfos", "argInfos", "lc", "validationErrorIfAny", "logalot", "error", "extractErrorMsg", "__name", "getPrompt", "id", "promptTemplate", "DEFAULT_PROMPT_TEMPLATE", "result", "stripQuotes", "str", "lc", "logalot", "s", "key", "value", "error", "extractErrorMsg", "__name", "logalot", "GLOBAL_LOG_A_LOT", "isRequestComment", "ibGib", "lc", "logalot", "isComment", "data", "castedData", "error", "extractErrorMsg", "__name", "parseCommandRawTextIntoArgs", "rawText", "validCommandIdentifiers", "logErrors", "mutatingNaiveSpaceDelimited", "doubleDashPrefix", "commandPrefix", "DEFAULT_COMMAND_ESCAPE_STRING", "rawFirstArg", "cmd_ie_firstArgSansPrefix", "doubleDashFound", "resArgs", "tmpArgWhileBuilding", "i", "textPiece", "stripQuotes", "subPieces", "left", "right", "emsg", "addToChatLogKluge", "text", "who", "chatLog", "scrollAfter", "lc", "logalot", "primaryAgentChatLog", "ID_PRIMARY_AGENT_CHAT_LOG", "chatEntry", "textParagraphs", "pElement", "error", "extractErrorMsg", "__name", "AGENT_SPECIAL_IBGIB_NAME_PRIMARYAGENT", "AGENT_GOAL_PRIMARYAGENT", "AGENT_GOAL_COMMON", "AGENT_UI_CSS_INSTRUCTIONS", "AGENT_INITIAL_SYSTEM_TEXT_PRIMARYAGENT", "AGENT_SYSTEM_PROMPT_COMMON_INSTRUCTIONS", "AGENT_WEBSITE_DESCRIPTION", "AGENT_INITIAL_CHAT_TEXT_PRIMARYAGENT", "logalot", "GLOBAL_LOG_A_LOT", "BlankCanvasApp_V1", "_BlankCanvasApp_V1", "AppBase_V1", "__name", "getPrompt", "initialData", "initialRel8ns", "lc", "error", "extractErrorMsg", "ibGib", "isRequestComment", "AGENT_INITIAL_SYSTEM_TEXT_PRIMARYAGENT", "getUserPreferredColorScheme", "requestCommentIbGib", "fnGetAPIKey", "metaspace", "space", "agent", "agents", "getAgents", "AGENT_SPECIAL_IBGIB_TYPE_PRIMARYAGENT", "getAgentsSvc", "AGENT_SPECIAL_IBGIB_NAME_PRIMARYAGENT", "AGENT_AVAILABLE_FUNCTIONS_PRIMARYAGENT", "AGENT_INITIAL_CHAT_TEXT_PRIMARYAGENT", "GEMINI_DEFAULT_MODEL_STR", "_", "ROOT", "item", "groupTitle", "title", "valid", "value", "promptForText", "promptForConfirm", "options", "x", "msg", "i", "option", "parsedSelectionIndex", "regexpIsValid", "fnValidIsValid", "pretty", "interpretedArgInfos", "PARAM_INFO_INTERACTIVE", "WITNESS_CONTEXT_REL8N_NAME", "apiKey", "storageGet", "BLANK_GIB_DB_NAME", "ARMY_STORE", "BEE_KEY", "newChild", "result", "text", "cmdEscapeString", "DEFAULT_COMMAND_ESCAPE_STRING", "isBlankCanvasCommandComment", "commentIbGib", "resolve", "reject", "cmdInfo", "cmd", "rawText", "errorMsg", "BlankCanvasCommand", "arg", "contextIbGib", "handlers", "fnHandler", "showHelp", "validArgsString", "args", "rawCmdText", "validationErrorMsg", "parseCommandRawTextIntoArgs", "RCLI_COMMAND_IDENTIFIERS", "cmdParamInfo", "getParamInfo", "PARAM_INFOS", "RCLI_COMMANDS", "argInfos", "buildArgInfos", "validationErrors", "validateArgInfos", "argIs", "PARAM_INFO_HELP", "ib", "atom", "classnameIsh", "nameIsh", "idIsh", "clone", "DEFAULT_BLANK_CANVAS_APP_DATA_V1", "DEFAULT_BLANK_CANVAS_APP_REL8NS_V1", "primaryAgentInput", "primaryAgentChatLog", "shellLayoutSvc", "getAppShellSvc", "rightPanelStatus", "fnSubmitToAgent", "addToChatLogKluge", "tryAgain", "attempts", "maxAttempts", "resAPIKey", "promptForSecret", "CHAT_WITH_AGENT_NEED_API_KEY", "storagePut", "alertUser", "CHAT_WITH_AGENT_PLACEHOLDER_PRIMARYAGENT", "resTagIbGibs", "SpecialIbGibType", "TAG_REL8N_NAME", "tagNav", "ID_TAG_NAV", "ul", "tagIbGib", "gib", "getIbAndGib", "li", "anchor", "ROUTER_APP_NAME_TAGS", "_tagAgents", "getTag_Agents", "rel8nName", "entries", "errors", "data", "isComment", "firstArg", "UIAgentFunctionInfos", "updateCSSVariablesFunctionInfo", "logalot", "GLOBAL_LOG_A_LOT", "EXAMPLE_INPUT_FETCH_HOME", "EXAMPLES", "FUNCTION_CALL_EXAMPLES_HEADER", "pretty", "fetchWeb1PageViaCmd", "opts", "commandService", "getCommandService", "command", "resolve", "reject", "__name", "fetchWeb1PageImpl", "lc", "page", "htmlTemplate", "res", "htmlDescription", "pageHtmlPath", "error", "errorMsg", "extractErrorMsg", "fetchWeb1PageFunctionInfo", "COMMAND_BASE_SCHEMA_PROPERTIES", "GEMINI_SCHEMA_WEB1_PAGE", "MinigameFunctionInfos", "minigameBuilderStartFunctionInfo", "minigameBuilderEditStimuliFunctionInfo", "minigameBuilderValidateAndReadyFunctionInfo", "logalot", "GLOBAL_LOG_A_LOT", "AllFunctionInfos_Web", "ChatAPIFunctionInfos", "TextAPIFunctionInfos", "fetchWeb1PageFunctionInfo", "RenderAgentFunctionInfos", "UIAgentFunctionInfos", "IbGibAPIFunctionInfos", "MinigameFunctionInfos", "x", "DeprecatedFunctionInfoNames_Web", "registerDeprecatedFunctionNamesAndFunctionInfos_Web", "lc", "nameOrId", "registerDeprecatedFunctionInfoName", "registerFunctionInfos", "error", "extractErrorMsg", "__name", "AUTO_GENERATED_VERSION", "bootstrapBlankCanvasApp", "bootstrapIbGibApp", "APP_CONFIG", "getIbGibGlobalThis_BlankGib", "BlankCanvasApp_V1", "DEFAULT_BLANK_CANVAS_APP_DATA_V1", "PARAM_INFOS", "registerDeprecatedFunctionNamesAndFunctionInfos_Web", "TAG_AGENT_TEXT", "TAG_AGENT_ICON", "TAG_AGENT_DESCRIPTION", "BLANK_GIB_INDEXEDDB_LOCAL_SPACE_NAME_PREFIX", "__name", "app", "GLOBAL_LOG_A_LOT", "getAppShellSvc"]
}
