@willbooster/shared-lib 10.5.0 → 10.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/error.cjs +1 -1
- package/dist/error.cjs.map +1 -1
- package/dist/error.js +1 -1
- package/dist/error.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/prompt.cjs +12 -0
- package/dist/prompt.cjs.map +1 -0
- package/dist/prompt.d.ts +8 -0
- package/dist/prompt.js +12 -0
- package/dist/prompt.js.map +1 -0
- package/dist/text.cjs +4 -0
- package/dist/text.cjs.map +1 -0
- package/dist/text.d.ts +9 -0
- package/dist/text.js +4 -0
- package/dist/text.js.map +1 -0
- package/package.json +9 -8
package/dist/error.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";const e=require("./sleep.cjs");function t(e){
|
|
1
|
+
"use strict";const e=require("./sleep.cjs");function t(e){return e instanceof Error?e:Error(typeof e==`string`?e:n(()=>JSON.stringify(e))??n(()=>String(e)))}function n(e){try{return e()}catch{}}function r(e){try{return e()}catch(e){if(typeof e==`object`&&e&&`code`in e&&e.code===`ENOENT`)return;throw e}}async function i(e){try{return await e()}catch{}}async function a(e){try{return await e()}catch(e){if(typeof e==`object`&&e&&`code`in e&&e.code===`ENOENT`)return;throw e}}async function o(t,{beforeRetry:n,handleError:r,retryCount:i=3,retryLogger:a,shouldRetry:o,sleepMilliseconds:s=0,updateSleepMilliseconds:c}={}){let l=0;for(;;)try{return await t(l)}catch(t){if(await r?.(t),l++,l>=i||o&&!o(t))throw t;s>0&&await e.sleep(s),c&&(s=c(s)),a?.(`Retry due to: ${t}
|
|
2
2
|
${t instanceof Error?`---
|
|
3
3
|
`+(t.stack??``):``}`),await n?.(t)}}exports.errorify=t,exports.ignoreEnoent=r,exports.ignoreEnoentAsync=a,exports.ignoreError=n,exports.ignoreErrorAsync=i,exports.withRetry=o;
|
|
4
4
|
//# sourceMappingURL=error.cjs.map
|
package/dist/error.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.cjs","names":["sleep"],"sources":["../src/error.ts"],"sourcesContent":["import { sleep } from './sleep.js';\n\n/**\n * Convert an object to an error.\n * @param obj The object to convert.\n */\nexport function errorify(obj: unknown): Error {\n if (obj instanceof Error) return obj;\n if (typeof obj === 'string') return new Error(obj);\n
|
|
1
|
+
{"version":3,"file":"error.cjs","names":["sleep"],"sources":["../src/error.ts"],"sourcesContent":["import { sleep } from './sleep.js';\n\n/**\n * Convert an object to an error.\n * @param obj The object to convert.\n */\nexport function errorify(obj: unknown): Error {\n if (obj instanceof Error) return obj;\n if (typeof obj === 'string') return new Error(obj);\n // `JSON.stringify` answers `undefined` for `undefined`, a symbol and a function, and throws\n // on a bigint or a cycle; `new Error(undefined)` has an empty message, which would drop the\n // only diagnostic a caller has about such a thrown value. Neither representation may throw\n // out of here: this runs in a catch block, where it would replace the error it converts.\n return new Error(ignoreError(() => JSON.stringify(obj)) ?? ignoreError(() => String(obj)));\n}\n\nexport function ignoreError<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch {\n // do nothing\n }\n}\n\nexport function ignoreEnoent<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch (error) {\n if (typeof error === 'object' && error && 'code' in error && error.code === 'ENOENT') {\n return;\n }\n throw error;\n }\n}\n\nexport async function ignoreErrorAsync<T>(fn: () => Promise<T>): Promise<T | undefined> {\n try {\n return await fn();\n } catch {\n // do nothing\n }\n}\n\nexport async function ignoreEnoentAsync<T>(fn: () => Promise<T>): Promise<T | undefined> {\n try {\n return await fn();\n } catch (error) {\n if (typeof error === 'object' && error && 'code' in error && error.code === 'ENOENT') {\n return;\n }\n throw error;\n }\n}\n\nexport interface RetryOptions {\n beforeRetry?: (error: unknown) => Promise<void>;\n handleError?: (error: unknown) => Promise<void>;\n /**\n * The maximum number of total attempts, including the initial attempt.\n * For example, `retryCount: 3` runs the function at most 3 times: 1 initial attempt and up to 2 retries.\n */\n retryCount?: number;\n retryLogger?: (message: string) => void;\n shouldRetry?: (error: unknown) => boolean;\n sleepMilliseconds?: number;\n updateSleepMilliseconds?: (sleepMilliseconds: number) => number;\n}\n\n/**\n * Retry the given function.\n * @param func The function to retry.\n * @param beforeRetry The function to call immediately before retrying.\n * @param handleError The function to call when an error occurs.\n * @param retryCount The maximum number of total attempts, including the initial attempt.\n * @param retryLogger The function to log retrying.\n * @param sleepMilliseconds The number of milliseconds to sleep before retrying.\n * @param updateSleepMilliseconds The function to update sleep milliseconds after each retry.\n */\nexport async function withRetry<T>(\n func: (failedCount: number) => T | Promise<T>,\n {\n beforeRetry,\n handleError,\n retryCount = 3,\n retryLogger,\n shouldRetry,\n sleepMilliseconds = 0,\n updateSleepMilliseconds,\n }: RetryOptions = {}\n): Promise<T> {\n let failedCount = 0;\n for (;;) {\n try {\n return await func(failedCount);\n } catch (error) {\n await handleError?.(error);\n failedCount++;\n if (failedCount >= retryCount) {\n throw error;\n }\n if (shouldRetry && !shouldRetry(error)) {\n throw error;\n }\n if (sleepMilliseconds > 0) {\n await sleep(sleepMilliseconds);\n }\n if (updateSleepMilliseconds) {\n sleepMilliseconds = updateSleepMilliseconds(sleepMilliseconds);\n }\n retryLogger?.(`Retry due to: ${error}\n${error instanceof Error ? '---\\n' + (error.stack ?? '') : ''}`);\n await beforeRetry?.(error);\n }\n }\n}\n"],"mappings":"4CAMA,SAAgB,EAAS,EAAqB,CAO5C,OANI,aAAe,MAAc,EACO,MAApC,OAAO,GAAQ,SAA2B,EAK7B,MAAkB,KAAK,UAAU,CAAG,CAAC,GAAK,MAAkB,OAAO,CAAG,CAAC,CALvC,CAMnD,CAEA,SAAgB,EAAe,EAA4B,CACzD,GAAI,CACF,OAAO,EAAG,CACZ,MAAQ,CAER,CACF,CAEA,SAAgB,EAAgB,EAA4B,CAC1D,GAAI,CACF,OAAO,EAAG,CACZ,OAAS,EAAO,CACd,GAAI,OAAO,GAAU,UAAY,GAAS,SAAU,GAAS,EAAM,OAAS,SAC1E,OAEF,MAAM,CACR,CACF,CAEA,eAAsB,EAAoB,EAA8C,CACtF,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,MAAQ,CAER,CACF,CAEA,eAAsB,EAAqB,EAA8C,CACvF,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,OAAS,EAAO,CACd,GAAI,OAAO,GAAU,UAAY,GAAS,SAAU,GAAS,EAAM,OAAS,SAC1E,OAEF,MAAM,CACR,CACF,CA0BA,eAAsB,EACpB,EACA,CACE,cACA,cACA,aAAa,EACb,cACA,cACA,oBAAoB,EACpB,2BACgB,CAAC,EACP,CACZ,IAAI,EAAc,EAClB,OACE,GAAI,CACF,OAAO,MAAM,EAAK,CAAW,CAC/B,OAAS,EAAO,CAMd,GALA,MAAM,IAAc,CAAK,EACzB,IACI,GAAe,GAGf,GAAe,CAAC,EAAY,CAAK,EACnC,MAAM,EAEJ,EAAoB,GACtB,MAAMA,EAAAA,MAAM,CAAiB,EAE3B,IACF,EAAoB,EAAwB,CAAiB,GAE/D,IAAc,iBAAiB,EAAM;EACzC,aAAiB,MAAQ;GAAW,EAAM,OAAS,IAAM,IAAI,EACzD,MAAM,IAAc,CAAK,CAC3B,CAEJ"}
|
package/dist/error.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{sleep as e}from"./sleep.js";function t(e){
|
|
1
|
+
import{sleep as e}from"./sleep.js";function t(e){return e instanceof Error?e:Error(typeof e==`string`?e:n(()=>JSON.stringify(e))??n(()=>String(e)))}function n(e){try{return e()}catch{}}function r(e){try{return e()}catch(e){if(typeof e==`object`&&e&&`code`in e&&e.code===`ENOENT`)return;throw e}}async function i(e){try{return await e()}catch{}}async function a(e){try{return await e()}catch(e){if(typeof e==`object`&&e&&`code`in e&&e.code===`ENOENT`)return;throw e}}async function o(t,{beforeRetry:n,handleError:r,retryCount:i=3,retryLogger:a,shouldRetry:o,sleepMilliseconds:s=0,updateSleepMilliseconds:c}={}){let l=0;for(;;)try{return await t(l)}catch(t){if(await r?.(t),l++,l>=i||o&&!o(t))throw t;s>0&&await e(s),c&&(s=c(s)),a?.(`Retry due to: ${t}
|
|
2
2
|
${t instanceof Error?`---
|
|
3
3
|
`+(t.stack??``):``}`),await n?.(t)}}export{t as errorify,r as ignoreEnoent,a as ignoreEnoentAsync,n as ignoreError,i as ignoreErrorAsync,o as withRetry};
|
|
4
4
|
//# sourceMappingURL=error.js.map
|
package/dist/error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","names":[],"sources":["../src/error.ts"],"sourcesContent":["import { sleep } from './sleep.js';\n\n/**\n * Convert an object to an error.\n * @param obj The object to convert.\n */\nexport function errorify(obj: unknown): Error {\n if (obj instanceof Error) return obj;\n if (typeof obj === 'string') return new Error(obj);\n
|
|
1
|
+
{"version":3,"file":"error.js","names":[],"sources":["../src/error.ts"],"sourcesContent":["import { sleep } from './sleep.js';\n\n/**\n * Convert an object to an error.\n * @param obj The object to convert.\n */\nexport function errorify(obj: unknown): Error {\n if (obj instanceof Error) return obj;\n if (typeof obj === 'string') return new Error(obj);\n // `JSON.stringify` answers `undefined` for `undefined`, a symbol and a function, and throws\n // on a bigint or a cycle; `new Error(undefined)` has an empty message, which would drop the\n // only diagnostic a caller has about such a thrown value. Neither representation may throw\n // out of here: this runs in a catch block, where it would replace the error it converts.\n return new Error(ignoreError(() => JSON.stringify(obj)) ?? ignoreError(() => String(obj)));\n}\n\nexport function ignoreError<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch {\n // do nothing\n }\n}\n\nexport function ignoreEnoent<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch (error) {\n if (typeof error === 'object' && error && 'code' in error && error.code === 'ENOENT') {\n return;\n }\n throw error;\n }\n}\n\nexport async function ignoreErrorAsync<T>(fn: () => Promise<T>): Promise<T | undefined> {\n try {\n return await fn();\n } catch {\n // do nothing\n }\n}\n\nexport async function ignoreEnoentAsync<T>(fn: () => Promise<T>): Promise<T | undefined> {\n try {\n return await fn();\n } catch (error) {\n if (typeof error === 'object' && error && 'code' in error && error.code === 'ENOENT') {\n return;\n }\n throw error;\n }\n}\n\nexport interface RetryOptions {\n beforeRetry?: (error: unknown) => Promise<void>;\n handleError?: (error: unknown) => Promise<void>;\n /**\n * The maximum number of total attempts, including the initial attempt.\n * For example, `retryCount: 3` runs the function at most 3 times: 1 initial attempt and up to 2 retries.\n */\n retryCount?: number;\n retryLogger?: (message: string) => void;\n shouldRetry?: (error: unknown) => boolean;\n sleepMilliseconds?: number;\n updateSleepMilliseconds?: (sleepMilliseconds: number) => number;\n}\n\n/**\n * Retry the given function.\n * @param func The function to retry.\n * @param beforeRetry The function to call immediately before retrying.\n * @param handleError The function to call when an error occurs.\n * @param retryCount The maximum number of total attempts, including the initial attempt.\n * @param retryLogger The function to log retrying.\n * @param sleepMilliseconds The number of milliseconds to sleep before retrying.\n * @param updateSleepMilliseconds The function to update sleep milliseconds after each retry.\n */\nexport async function withRetry<T>(\n func: (failedCount: number) => T | Promise<T>,\n {\n beforeRetry,\n handleError,\n retryCount = 3,\n retryLogger,\n shouldRetry,\n sleepMilliseconds = 0,\n updateSleepMilliseconds,\n }: RetryOptions = {}\n): Promise<T> {\n let failedCount = 0;\n for (;;) {\n try {\n return await func(failedCount);\n } catch (error) {\n await handleError?.(error);\n failedCount++;\n if (failedCount >= retryCount) {\n throw error;\n }\n if (shouldRetry && !shouldRetry(error)) {\n throw error;\n }\n if (sleepMilliseconds > 0) {\n await sleep(sleepMilliseconds);\n }\n if (updateSleepMilliseconds) {\n sleepMilliseconds = updateSleepMilliseconds(sleepMilliseconds);\n }\n retryLogger?.(`Retry due to: ${error}\n${error instanceof Error ? '---\\n' + (error.stack ?? '') : ''}`);\n await beforeRetry?.(error);\n }\n }\n}\n"],"mappings":"mCAMA,SAAgB,EAAS,EAAqB,CAO5C,OANI,aAAe,MAAc,EACO,MAApC,OAAO,GAAQ,SAA2B,EAK7B,MAAkB,KAAK,UAAU,CAAG,CAAC,GAAK,MAAkB,OAAO,CAAG,CAAC,CALvC,CAMnD,CAEA,SAAgB,EAAe,EAA4B,CACzD,GAAI,CACF,OAAO,EAAG,CACZ,MAAQ,CAER,CACF,CAEA,SAAgB,EAAgB,EAA4B,CAC1D,GAAI,CACF,OAAO,EAAG,CACZ,OAAS,EAAO,CACd,GAAI,OAAO,GAAU,UAAY,GAAS,SAAU,GAAS,EAAM,OAAS,SAC1E,OAEF,MAAM,CACR,CACF,CAEA,eAAsB,EAAoB,EAA8C,CACtF,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,MAAQ,CAER,CACF,CAEA,eAAsB,EAAqB,EAA8C,CACvF,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,OAAS,EAAO,CACd,GAAI,OAAO,GAAU,UAAY,GAAS,SAAU,GAAS,EAAM,OAAS,SAC1E,OAEF,MAAM,CACR,CACF,CA0BA,eAAsB,EACpB,EACA,CACE,cACA,cACA,aAAa,EACb,cACA,cACA,oBAAoB,EACpB,2BACgB,CAAC,EACP,CACZ,IAAI,EAAc,EAClB,OACE,GAAI,CACF,OAAO,MAAM,EAAK,CAAW,CAC/B,OAAS,EAAO,CAMd,GALA,MAAM,IAAc,CAAK,EACzB,IACI,GAAe,GAGf,GAAe,CAAC,EAAY,CAAK,EACnC,MAAM,EAEJ,EAAoB,GACtB,MAAM,EAAM,CAAiB,EAE3B,IACF,EAAoB,EAAwB,CAAiB,GAE/D,IAAc,iBAAiB,EAAM;EACzC,aAAiB,MAAQ;GAAW,EAAM,OAAS,IAAM,IAAI,EACzD,MAAM,IAAc,CAAK,CAC3B,CAEJ"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./appEnv.cjs"),t=require("./assert.cjs"),n=require("./githubTemplates.cjs"),r=require("./sleep.cjs"),i=require("./error.cjs"),a=require("./humanize.cjs"),o=require("./mail.cjs"),s=require("./parseCommandLineArgs.cjs"),c=require("./
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./appEnv.cjs"),t=require("./assert.cjs"),n=require("./githubTemplates.cjs"),r=require("./sleep.cjs"),i=require("./error.cjs"),a=require("./humanize.cjs"),o=require("./mail.cjs"),s=require("./parseCommandLineArgs.cjs"),c=require("./text.cjs"),l=require("./prompt.cjs"),u=require("./shuffle.cjs"),d=require("./sqlite.cjs"),f=require("./testingRules.cjs"),p=require("./zenkaku.cjs");exports.BUG_ISSUE_SECTIONS=n.BUG_ISSUE_SECTIONS,exports.CHANGE_ISSUE_SECTIONS=n.CHANGE_ISSUE_SECTIONS,exports.ISSUE_TEMPLATE_RULES=n.ISSUE_TEMPLATE_RULES,exports.PULL_REQUEST_BODY_RULES=n.PULL_REQUEST_BODY_RULES,exports.PULL_REQUEST_REQUIREMENTS_RULES=n.PULL_REQUEST_REQUIREMENTS_RULES,exports.PULL_REQUEST_SECTIONS=n.PULL_REQUEST_SECTIONS,exports.TEST_WRITING_RULES=f.TEST_WRITING_RULES,exports.ensureTruthy=t.ensureTruthy,exports.errorify=i.errorify,exports.escapeRegExp=c.escapeRegExp,exports.getAppEnv=e.getAppEnv,exports.getConnectionLevelSqlitePragmas=d.getConnectionLevelSqlitePragmas,exports.getPersistentSqlitePragmas=d.getPersistentSqlitePragmas,exports.humanizeNumber=a.humanizeNumber,exports.ignoreEnoent=i.ignoreEnoent,exports.ignoreEnoentAsync=i.ignoreEnoentAsync,exports.ignoreError=i.ignoreError,exports.ignoreErrorAsync=i.ignoreErrorAsync,exports.mailTemplates=o.mailTemplates,exports.parseCommandLineArgs=s.parseCommandLineArgs,exports.quoteForShell=c.quoteForShell,exports.renderSectionChecklist=n.renderSectionChecklist,exports.renderSectionTemplate=n.renderSectionTemplate,exports.serializeForPrompt=l.serializeForPrompt,exports.shuffle=u.shuffle,exports.sleep=r.sleep,exports.toTildeCodeBlock=c.toTildeCodeBlock,exports.withRetry=i.withRetry,exports.zenkakuAlphanumericalsToHankaku=p.zenkakuAlphanumericalsToHankaku;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,9 +5,11 @@ export { errorify, ignoreError, ignoreEnoent, ignoreErrorAsync, ignoreEnoentAsyn
|
|
|
5
5
|
export { humanizeNumber } from './humanize.js';
|
|
6
6
|
export { mailTemplates } from './mail.js';
|
|
7
7
|
export { parseCommandLineArgs } from './parseCommandLineArgs.js';
|
|
8
|
+
export { serializeForPrompt } from './prompt.js';
|
|
8
9
|
export { shuffle } from './shuffle.js';
|
|
9
10
|
export { sleep } from './sleep.js';
|
|
10
11
|
export { getConnectionLevelSqlitePragmas, getPersistentSqlitePragmas } from './sqlite.js';
|
|
12
|
+
export { escapeRegExp, quoteForShell, toTildeCodeBlock } from './text.js';
|
|
11
13
|
export { TEST_WRITING_RULES } from './testingRules.js';
|
|
12
14
|
export { zenkakuAlphanumericalsToHankaku } from './zenkaku.js';
|
|
13
15
|
export type { AppEnv } from './appEnv.js';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getAppEnv as e}from"./appEnv.js";import{ensureTruthy as t}from"./assert.js";import{BUG_ISSUE_SECTIONS as n,CHANGE_ISSUE_SECTIONS as r,ISSUE_TEMPLATE_RULES as i,PULL_REQUEST_BODY_RULES as a,PULL_REQUEST_REQUIREMENTS_RULES as o,PULL_REQUEST_SECTIONS as s,renderSectionChecklist as c,renderSectionTemplate as l}from"./githubTemplates.js";import{sleep as u}from"./sleep.js";import{errorify as d,ignoreEnoent as f,ignoreEnoentAsync as p,ignoreError as m,ignoreErrorAsync as h,withRetry as g}from"./error.js";import{humanizeNumber as _}from"./humanize.js";import{mailTemplates as v}from"./mail.js";import{parseCommandLineArgs as y}from"./parseCommandLineArgs.js";import{
|
|
1
|
+
import{getAppEnv as e}from"./appEnv.js";import{ensureTruthy as t}from"./assert.js";import{BUG_ISSUE_SECTIONS as n,CHANGE_ISSUE_SECTIONS as r,ISSUE_TEMPLATE_RULES as i,PULL_REQUEST_BODY_RULES as a,PULL_REQUEST_REQUIREMENTS_RULES as o,PULL_REQUEST_SECTIONS as s,renderSectionChecklist as c,renderSectionTemplate as l}from"./githubTemplates.js";import{sleep as u}from"./sleep.js";import{errorify as d,ignoreEnoent as f,ignoreEnoentAsync as p,ignoreError as m,ignoreErrorAsync as h,withRetry as g}from"./error.js";import{humanizeNumber as _}from"./humanize.js";import{mailTemplates as v}from"./mail.js";import{parseCommandLineArgs as y}from"./parseCommandLineArgs.js";import{escapeRegExp as b,quoteForShell as x,toTildeCodeBlock as S}from"./text.js";import{serializeForPrompt as C}from"./prompt.js";import{shuffle as w}from"./shuffle.js";import{getConnectionLevelSqlitePragmas as T,getPersistentSqlitePragmas as E}from"./sqlite.js";import{TEST_WRITING_RULES as D}from"./testingRules.js";import{zenkakuAlphanumericalsToHankaku as O}from"./zenkaku.js";export{n as BUG_ISSUE_SECTIONS,r as CHANGE_ISSUE_SECTIONS,i as ISSUE_TEMPLATE_RULES,a as PULL_REQUEST_BODY_RULES,o as PULL_REQUEST_REQUIREMENTS_RULES,s as PULL_REQUEST_SECTIONS,D as TEST_WRITING_RULES,t as ensureTruthy,d as errorify,b as escapeRegExp,e as getAppEnv,T as getConnectionLevelSqlitePragmas,E as getPersistentSqlitePragmas,_ as humanizeNumber,f as ignoreEnoent,p as ignoreEnoentAsync,m as ignoreError,h as ignoreErrorAsync,v as mailTemplates,y as parseCommandLineArgs,x as quoteForShell,c as renderSectionChecklist,l as renderSectionTemplate,C as serializeForPrompt,w as shuffle,u as sleep,S as toTildeCodeBlock,g as withRetry,O as zenkakuAlphanumericalsToHankaku};
|
package/dist/prompt.cjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";const e=require("./text.cjs"),t=/^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN|[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*))?$/u,n=/^(?:[\t ,[\]{}#&*!|>'"%@`]|[?-](?:[ \t]|$))/u,r=/:[ \t]|[ \t]#/u,i=/[\t :]$/u,a={"0000":String.raw`\0`,"0007":String.raw`\a`,"000b":String.raw`\v`,"001b":String.raw`\e`};function o(t){return e.toTildeCodeBlock(`${s(l(t),{indent:``})}\n`,`yaml`)}function s(e,t){switch(typeof e){case`undefined`:return`null`;case`boolean`:return String(e);case`number`:return d(e);case`bigint`:return String(e);case`string`:return f(e,t);case`object`:{if(e===null)return`null`;let n=`\n${t.indent}`,r=``;if(Array.isArray(e)){if(e.length===0)return`[]`;let i={indent:t.indent+` `};for(let t of e)r+=`${r?n:``}- ${s(l(t),i)}`;return r}if(e instanceof Map){for(let[i,a]of e)a!==void 0&&(r+=`${r?n:``}${c(i,a,t)}`);return r||`{}`}let i=e;for(let e of Object.keys(i)){let a=i[e];a!==void 0&&(r+=`${r?n:``}${c(e,a,t)}`)}return r||`{}`}default:throw TypeError(`Cannot serialize a ${typeof e} value for a prompt`)}}function c(e,t,n){let r=n.indent+` `,i=l(e),a=l(t),o=s(i,{indent:r,implicitKey:!0}),c=s(a,{indent:r});return u(i)||o.length>1024?`? ${o}\n${n.indent}: ${c}`:`${o}:${u(a)&&c!==`[]`&&c!==`{}`?`\n${r}`:` `}${c}`}function l(e){let t=typeof e?.toJSON==`function`?e.toJSON():e;return typeof t!=`object`||!t||Array.isArray(t)||t instanceof Map?t:t instanceof String||t instanceof Number||t instanceof Boolean||t instanceof BigInt?t.valueOf():t instanceof Error?{name:t.name,message:t.message,...Object.fromEntries(Object.entries(t)),...`cause`in t&&{cause:t.cause},...t instanceof AggregateError&&{errors:t.errors}}:t instanceof RegExp?String(t):Symbol.iterator in t?[...t]:t}function u(e){return typeof e==`object`&&!!e}function d(e){return Number.isNaN(e)?`.nan`:Number.isFinite(e)?Object.is(e,-0)?`-0`:JSON.stringify(e):e<0?`-.inf`:`.inf`}function f(e,t){return/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u{D800}-\u{DFFF}]/u.test(e)?_(e,t):p(e,t)}function p(e,a){let{implicitKey:o,indent:s}=a;if(e.includes(`
|
|
2
|
+
`))return o?h(e,a):m(e,a);if(n.test(e)||i.test(e.slice(-1))||r.test(e))return h(e,a);if(v(e)){if(s===``)return m(e,a);if(o&&s===` `)return h(e,a)}return t.test(e)?h(e,a):e}function m(e,t){let n=e.length;for(;n>0&&b(e.codePointAt(n-1));)n--;let r=e.slice(n);if(r.includes(`
|
|
3
|
+
`)&&!r.endsWith(`
|
|
4
|
+
`))return h(e,t);let i=t.indent||(v(e)?` `:``),a=r.indexOf(`
|
|
5
|
+
`),o=a===-1?`-`:e===r||a!==r.length-1?`+`:``;r&&=(e=e.slice(0,-r.length),r.endsWith(`
|
|
6
|
+
`)&&(r=r.slice(0,-1)),r.replaceAll(/(?:^|(?<!\n))\n+(?!\n|$)/gu,`$&${i}`));let s=/^[\n ]*/u.exec(e)?.[0]??``,c=s.includes(` `),l=e.slice(0,s.lastIndexOf(`
|
|
7
|
+
`)+1);return l&&=(e=e.slice(l.length),l.replaceAll(/\n+/gu,`$&${i}`)),`|${(c?i?`2`:`1`:``)+o}\n${i}${l}${y(e,i)}${r}`}function h(e,t){return e.includes(`"`)&&!e.includes(`'`)?g(e,t):_(e,t)}function g(e,t){return e.includes(`
|
|
8
|
+
`)?_(e,t):`'${e.replaceAll(`'`,`''`)}'`}function _(e,t){let n=JSON.stringify(e),r=t.indent||(v(e)?` `:``),i=``,o=0;for(let e=0;e<n.length;e++){let s=n[e];if(s===` `&&n[e+1]===`\\`&&n[e+2]===`n`&&(i+=`${n.slice(o,e)}\\ `,e++,o=e,s=`\\`),s===`\\`){if(n[e+1]===`u`){let t=n.slice(e+2,e+6);i+=n.slice(o,e)+(a[t]??(t.startsWith(`00`)?`\\x${t.slice(2)}`:n.slice(e,e+6))),e+=5,o=e+1}else if(n[e+1]===`n`&&!t.implicitKey&&n[e+2]!==`"`&&n.length>=40){for(i+=`${n.slice(o,e)}\n\n`;n[e+2]===`\\`&&n[e+3]===`n`&&n[e+4]!==`"`;)i+=`
|
|
9
|
+
`,e+=2;i+=r,n[e+2]===` `&&(i+=`\\`),e++,o=e+1}else e++}}return o?i+n.slice(o):n}function v(e){return/^(?:%|---|\.\.\.)/mu.test(e)}function y(e,t){let n=e.split(`
|
|
10
|
+
`),r=n[0]??``;for(let e=1;e<n.length;e++){let i=n[e];r+=i?`\n${t}${i}`:`
|
|
11
|
+
`}return r}function b(e){return e===10||e===9||e===32}exports.serializeForPrompt=o;
|
|
12
|
+
//# sourceMappingURL=prompt.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.cjs","names":["toTildeCodeBlock"],"sources":["../src/prompt.ts"],"sourcesContent":["import { toTildeCodeBlock } from './text.js';\n\nconst INDENT_STEP = ' ';\nconst MAX_IMPLICIT_KEY_LENGTH = 1024;\nconst MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH = 40;\n\n/** Strings matching this would be read back as a non-string scalar (null, bool, int, or float), so they must be quoted. */\nconst NON_STRING_SCALAR =\n /^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\\.(?:inf|Inf|INF)|\\.nan|\\.NaN|\\.NAN|[-+]?(?:\\.[0-9]+|[0-9]+(?:\\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\\.[0-9]+|[0-9]+\\.[0-9]*))?$/u;\n\n// A single-line string must be quoted if it matches any of these. Checking the start, the middle, and the end separately\n// is much faster on long strings than one regex whose anchored alternatives are retried at every position.\nconst UNSAFE_PLAIN_START = /^(?:[\\t ,[\\]{}#&*!|>'\"%@`]|[?-](?:[ \\t]|$))/u;\nconst UNSAFE_PLAIN_MIDDLE = /:[ \\t]|[ \\t]#/u;\nconst UNSAFE_PLAIN_END = /[\\t :]$/u;\n\nconst SHORT_UNICODE_ESCAPES: Record<string, string> = {\n '0000': String.raw`\\0`,\n '0007': String.raw`\\a`,\n '000b': String.raw`\\v`,\n '001b': String.raw`\\e`,\n};\n\ninterface Context {\n indent: string;\n implicitKey?: boolean;\n}\n\n/**\n * Serializes data into a code block to embed in an LLM prompt, so that the LLM can read its contents.\n * Accepts JSON data (honoring `toJSON` such as that of `Date`) as well as `undefined`, `NaN`, `Infinity`, bigints,\n * `Map`s (including non-string keys), `Set`s and other iterables, `Error`s (with their name, message, cause, and own properties),\n * and `RegExp`s. Symbols and functions without `toJSON` throw. The output is not meant to be deserialized back into the original value.\n * The format inside the code block is an implementation detail and may change.\n */\nexport function serializeForPrompt(value: unknown): string {\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '' })}\\n`, 'yaml');\n}\n\n// The functions below reproduce `stringify(value, { lineWidth: 0, aliasDuplicateObjects: false, blockQuote: 'literal' })`\n// of the `yaml` package, except that `toSerializable` makes `Error`s and `RegExp`s readable instead of `{}`.\n\nfunction stringifyValue(value: unknown, ctx: Context): string {\n switch (typeof value) {\n case 'undefined': {\n return 'null';\n }\n case 'boolean': {\n return String(value);\n }\n case 'number': {\n return stringifyNumber(value);\n }\n case 'bigint': {\n return String(value);\n }\n case 'string': {\n return stringifyString(value, ctx);\n }\n case 'object': {\n if (value === null) return 'null';\n const separator = `\\n${ctx.indent}`;\n let str = '';\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n const itemCtx = { indent: ctx.indent + INDENT_STEP };\n for (const item of value as unknown[]) {\n str += `${str ? separator : ''}- ${stringifyValue(toSerializable(item), itemCtx)}`;\n }\n return str;\n }\n if (value instanceof Map) {\n for (const [key, item] of value) {\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n }\n const record = value as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n const item = record[key];\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n }\n default: {\n throw new TypeError(`Cannot serialize a ${typeof value} value for a prompt`);\n }\n }\n}\n\nfunction stringifyPair(rawKey: unknown, rawValue: unknown, ctx: Context): string {\n const indent = ctx.indent + INDENT_STEP;\n const key = toSerializable(rawKey);\n const value = toSerializable(rawValue);\n const keyStr = stringifyValue(key, { indent, implicitKey: true });\n const valueStr = stringifyValue(value, { indent });\n if (isCollection(key) || keyStr.length > MAX_IMPLICIT_KEY_LENGTH) return `? ${keyStr}\\n${ctx.indent}: ${valueStr}`;\n const isBlockCollection = isCollection(value) && valueStr !== '[]' && valueStr !== '{}';\n return `${keyStr}:${isBlockCollection ? `\\n${indent}` : ' '}${valueStr}`;\n}\n\nfunction toSerializable(rawValue: unknown): unknown {\n // Like `yaml`, call `toJSON` only once, but classify its result.\n const value =\n typeof (rawValue as { toJSON?: unknown } | null | undefined)?.toJSON === 'function'\n ? (rawValue as { toJSON: () => unknown }).toJSON()\n : rawValue;\n if (typeof value !== 'object' || value === null || Array.isArray(value) || value instanceof Map) return value;\n // oxlint-disable-next-line unicorn/no-instanceof-builtins -- boxed primitives have no typeof check; `yaml` unwraps them the same way.\n if (value instanceof String || value instanceof Number || value instanceof Boolean || value instanceof BigInt) {\n return value.valueOf();\n }\n if (value instanceof Error) {\n // `name` and `message` usually live on the prototype, and `cause` and `errors` are not enumerable.\n return {\n name: value.name,\n message: value.message,\n ...Object.fromEntries(Object.entries(value)),\n ...('cause' in value && { cause: value.cause }),\n ...(value instanceof AggregateError && { errors: value.errors }),\n };\n }\n if (value instanceof RegExp) return String(value);\n return Symbol.iterator in value ? [...(value as Iterable<unknown>)] : value;\n}\n\nfunction isCollection(value: unknown): value is object {\n return typeof value === 'object' && value !== null;\n}\n\nfunction stringifyNumber(value: number): string {\n if (Number.isNaN(value)) return '.nan';\n if (!Number.isFinite(value)) return value < 0 ? '-.inf' : '.inf';\n return Object.is(value, -0) ? '-0' : JSON.stringify(value);\n}\n\nfunction stringifyString(value: string, ctx: Context): string {\n // oxlint-disable-next-line no-control-regex -- control characters and lone surrogates can only be written escaped.\n return /[\\u0000-\\u0008\\u000B-\\u001F\\u007F-\\u009F\\u{D800}-\\u{DFFF}]/u.test(value)\n ? doubleQuotedString(value, ctx)\n : plainString(value, ctx);\n}\n\nfunction plainString(value: string, ctx: Context): string {\n const { implicitKey, indent } = ctx;\n if (value.includes('\\n')) return implicitKey ? quotedString(value, ctx) : blockString(value, ctx);\n if (UNSAFE_PLAIN_START.test(value) || UNSAFE_PLAIN_END.test(value.slice(-1)) || UNSAFE_PLAIN_MIDDLE.test(value)) {\n return quotedString(value, ctx);\n }\n if (containsDocumentMarker(value)) {\n if (indent === '') return blockString(value, ctx);\n if (implicitKey && indent === INDENT_STEP) return quotedString(value, ctx);\n }\n return NON_STRING_SCALAR.test(value) ? quotedString(value, ctx) : value;\n}\n\nfunction blockString(value: string, ctx: Context): string {\n let endStart = value.length;\n while (endStart > 0 && isBlockEndWhitespace(value.codePointAt(endStart - 1))) endStart--;\n let end = value.slice(endStart);\n // A block scalar cannot end with a whitespace-only line.\n if (end.includes('\\n') && !end.endsWith('\\n')) return quotedString(value, ctx);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n\n const endNewlinePos = end.indexOf('\\n');\n const chomp = endNewlinePos === -1 ? '-' : value === end || endNewlinePos !== end.length - 1 ? '+' : '';\n if (end) {\n value = value.slice(0, -end.length);\n if (end.endsWith('\\n')) end = end.slice(0, -1);\n end = end.replaceAll(/(?:^|(?<!\\n))\\n+(?!\\n|$)/gu, `$&${indent}`);\n }\n\n const leadingWhitespace = /^[\\n ]*/u.exec(value)?.[0] ?? '';\n const startsWithSpace = leadingWhitespace.includes(' ');\n let start = value.slice(0, leadingWhitespace.lastIndexOf('\\n') + 1);\n if (start) {\n value = value.slice(start.length);\n start = start.replaceAll(/\\n+/gu, `$&${indent}`);\n }\n\n const header = (startsWithSpace ? (indent ? '2' : '1') : '') + chomp;\n return `|${header}\\n${indent}${start}${indentLines(value, indent)}${end}`;\n}\n\nfunction quotedString(value: string, ctx: Context): string {\n return value.includes('\"') && !value.includes(\"'\") ? singleQuotedString(value, ctx) : doubleQuotedString(value, ctx);\n}\n\nfunction singleQuotedString(value: string, ctx: Context): string {\n // Every multi-line value reaching here would contain a space or tab next to a newline or be an implicit key,\n // both of which need double quotes.\n if (value.includes('\\n')) return doubleQuotedString(value, ctx);\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction doubleQuotedString(value: string, ctx: Context): string {\n const json = JSON.stringify(value);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n let str = '';\n let start = 0;\n for (let i = 0; i < json.length; i++) {\n let ch = json[i];\n if (ch === ' ' && json[i + 1] === '\\\\' && json[i + 2] === 'n') {\n // A space before a line break would be folded away unless escaped.\n str += `${json.slice(start, i)}\\\\ `;\n i++;\n start = i;\n ch = '\\\\';\n }\n if (ch !== '\\\\') continue;\n if (json[i + 1] === 'u') {\n const code = json.slice(i + 2, i + 6);\n str +=\n json.slice(start, i) +\n (SHORT_UNICODE_ESCAPES[code] ?? (code.startsWith('00') ? `\\\\x${code.slice(2)}` : json.slice(i, i + 6)));\n i += 5;\n start = i + 1;\n } else if (\n json[i + 1] === 'n' &&\n !ctx.implicitKey &&\n json[i + 2] !== '\"' &&\n json.length >= MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH\n ) {\n // Folding turns the first of the written line breaks back into a space, hence the extra one.\n str += `${json.slice(start, i)}\\n\\n`;\n while (json[i + 2] === '\\\\' && json[i + 3] === 'n' && json[i + 4] !== '\"') {\n str += '\\n';\n i += 2;\n }\n str += indent;\n // A space after a line break would be folded away unless escaped.\n if (json[i + 2] === ' ') str += '\\\\';\n i++;\n start = i + 1;\n } else {\n i++;\n }\n }\n return start ? str + json.slice(start) : json;\n}\n\nfunction containsDocumentMarker(value: string): boolean {\n return /^(?:%|---|\\.\\.\\.)/mu.test(value);\n}\n\n/** Equivalent to `text.replaceAll(/\\n+/g, `$&${indent}`)` for text without leading or trailing newlines, but faster. */\nfunction indentLines(text: string, indent: string): string {\n const lines = text.split('\\n');\n let str = lines[0] ?? '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n str += line ? `\\n${indent}${line}` : '\\n';\n }\n return str;\n}\n\nfunction isBlockEndWhitespace(codePoint: number | undefined): boolean {\n return codePoint === 0x0A || codePoint === 0x09 || codePoint === 0x20;\n}\n"],"mappings":"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"}
|
package/dist/prompt.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serializes data into a code block to embed in an LLM prompt, so that the LLM can read its contents.
|
|
3
|
+
* Accepts JSON data (honoring `toJSON` such as that of `Date`) as well as `undefined`, `NaN`, `Infinity`, bigints,
|
|
4
|
+
* `Map`s (including non-string keys), `Set`s and other iterables, `Error`s (with their name, message, cause, and own properties),
|
|
5
|
+
* and `RegExp`s. Symbols and functions without `toJSON` throw. The output is not meant to be deserialized back into the original value.
|
|
6
|
+
* The format inside the code block is an implementation detail and may change.
|
|
7
|
+
*/
|
|
8
|
+
export declare function serializeForPrompt(value: unknown): string;
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import{toTildeCodeBlock as e}from"./text.js";const t=/^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN|[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*))?$/u,n=/^(?:[\t ,[\]{}#&*!|>'"%@`]|[?-](?:[ \t]|$))/u,r=/:[ \t]|[ \t]#/u,i=/[\t :]$/u,a={"0000":String.raw`\0`,"0007":String.raw`\a`,"000b":String.raw`\v`,"001b":String.raw`\e`};function o(t){return e(`${s(l(t),{indent:``})}\n`,`yaml`)}function s(e,t){switch(typeof e){case`undefined`:return`null`;case`boolean`:return String(e);case`number`:return d(e);case`bigint`:return String(e);case`string`:return f(e,t);case`object`:{if(e===null)return`null`;let n=`\n${t.indent}`,r=``;if(Array.isArray(e)){if(e.length===0)return`[]`;let i={indent:t.indent+` `};for(let t of e)r+=`${r?n:``}- ${s(l(t),i)}`;return r}if(e instanceof Map){for(let[i,a]of e)a!==void 0&&(r+=`${r?n:``}${c(i,a,t)}`);return r||`{}`}let i=e;for(let e of Object.keys(i)){let a=i[e];a!==void 0&&(r+=`${r?n:``}${c(e,a,t)}`)}return r||`{}`}default:throw TypeError(`Cannot serialize a ${typeof e} value for a prompt`)}}function c(e,t,n){let r=n.indent+` `,i=l(e),a=l(t),o=s(i,{indent:r,implicitKey:!0}),c=s(a,{indent:r});return u(i)||o.length>1024?`? ${o}\n${n.indent}: ${c}`:`${o}:${u(a)&&c!==`[]`&&c!==`{}`?`\n${r}`:` `}${c}`}function l(e){let t=typeof e?.toJSON==`function`?e.toJSON():e;return typeof t!=`object`||!t||Array.isArray(t)||t instanceof Map?t:t instanceof String||t instanceof Number||t instanceof Boolean||t instanceof BigInt?t.valueOf():t instanceof Error?{name:t.name,message:t.message,...Object.fromEntries(Object.entries(t)),...`cause`in t&&{cause:t.cause},...t instanceof AggregateError&&{errors:t.errors}}:t instanceof RegExp?String(t):Symbol.iterator in t?[...t]:t}function u(e){return typeof e==`object`&&!!e}function d(e){return Number.isNaN(e)?`.nan`:Number.isFinite(e)?Object.is(e,-0)?`-0`:JSON.stringify(e):e<0?`-.inf`:`.inf`}function f(e,t){return/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u{D800}-\u{DFFF}]/u.test(e)?_(e,t):p(e,t)}function p(e,a){let{implicitKey:o,indent:s}=a;if(e.includes(`
|
|
2
|
+
`))return o?h(e,a):m(e,a);if(n.test(e)||i.test(e.slice(-1))||r.test(e))return h(e,a);if(v(e)){if(s===``)return m(e,a);if(o&&s===` `)return h(e,a)}return t.test(e)?h(e,a):e}function m(e,t){let n=e.length;for(;n>0&&b(e.codePointAt(n-1));)n--;let r=e.slice(n);if(r.includes(`
|
|
3
|
+
`)&&!r.endsWith(`
|
|
4
|
+
`))return h(e,t);let i=t.indent||(v(e)?` `:``),a=r.indexOf(`
|
|
5
|
+
`),o=a===-1?`-`:e===r||a!==r.length-1?`+`:``;r&&=(e=e.slice(0,-r.length),r.endsWith(`
|
|
6
|
+
`)&&(r=r.slice(0,-1)),r.replaceAll(/(?:^|(?<!\n))\n+(?!\n|$)/gu,`$&${i}`));let s=/^[\n ]*/u.exec(e)?.[0]??``,c=s.includes(` `),l=e.slice(0,s.lastIndexOf(`
|
|
7
|
+
`)+1);return l&&=(e=e.slice(l.length),l.replaceAll(/\n+/gu,`$&${i}`)),`|${(c?i?`2`:`1`:``)+o}\n${i}${l}${y(e,i)}${r}`}function h(e,t){return e.includes(`"`)&&!e.includes(`'`)?g(e,t):_(e,t)}function g(e,t){return e.includes(`
|
|
8
|
+
`)?_(e,t):`'${e.replaceAll(`'`,`''`)}'`}function _(e,t){let n=JSON.stringify(e),r=t.indent||(v(e)?` `:``),i=``,o=0;for(let e=0;e<n.length;e++){let s=n[e];if(s===` `&&n[e+1]===`\\`&&n[e+2]===`n`&&(i+=`${n.slice(o,e)}\\ `,e++,o=e,s=`\\`),s===`\\`){if(n[e+1]===`u`){let t=n.slice(e+2,e+6);i+=n.slice(o,e)+(a[t]??(t.startsWith(`00`)?`\\x${t.slice(2)}`:n.slice(e,e+6))),e+=5,o=e+1}else if(n[e+1]===`n`&&!t.implicitKey&&n[e+2]!==`"`&&n.length>=40){for(i+=`${n.slice(o,e)}\n\n`;n[e+2]===`\\`&&n[e+3]===`n`&&n[e+4]!==`"`;)i+=`
|
|
9
|
+
`,e+=2;i+=r,n[e+2]===` `&&(i+=`\\`),e++,o=e+1}else e++}}return o?i+n.slice(o):n}function v(e){return/^(?:%|---|\.\.\.)/mu.test(e)}function y(e,t){let n=e.split(`
|
|
10
|
+
`),r=n[0]??``;for(let e=1;e<n.length;e++){let i=n[e];r+=i?`\n${t}${i}`:`
|
|
11
|
+
`}return r}function b(e){return e===10||e===9||e===32}export{o as serializeForPrompt};
|
|
12
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","names":[],"sources":["../src/prompt.ts"],"sourcesContent":["import { toTildeCodeBlock } from './text.js';\n\nconst INDENT_STEP = ' ';\nconst MAX_IMPLICIT_KEY_LENGTH = 1024;\nconst MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH = 40;\n\n/** Strings matching this would be read back as a non-string scalar (null, bool, int, or float), so they must be quoted. */\nconst NON_STRING_SCALAR =\n /^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\\.(?:inf|Inf|INF)|\\.nan|\\.NaN|\\.NAN|[-+]?(?:\\.[0-9]+|[0-9]+(?:\\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\\.[0-9]+|[0-9]+\\.[0-9]*))?$/u;\n\n// A single-line string must be quoted if it matches any of these. Checking the start, the middle, and the end separately\n// is much faster on long strings than one regex whose anchored alternatives are retried at every position.\nconst UNSAFE_PLAIN_START = /^(?:[\\t ,[\\]{}#&*!|>'\"%@`]|[?-](?:[ \\t]|$))/u;\nconst UNSAFE_PLAIN_MIDDLE = /:[ \\t]|[ \\t]#/u;\nconst UNSAFE_PLAIN_END = /[\\t :]$/u;\n\nconst SHORT_UNICODE_ESCAPES: Record<string, string> = {\n '0000': String.raw`\\0`,\n '0007': String.raw`\\a`,\n '000b': String.raw`\\v`,\n '001b': String.raw`\\e`,\n};\n\ninterface Context {\n indent: string;\n implicitKey?: boolean;\n}\n\n/**\n * Serializes data into a code block to embed in an LLM prompt, so that the LLM can read its contents.\n * Accepts JSON data (honoring `toJSON` such as that of `Date`) as well as `undefined`, `NaN`, `Infinity`, bigints,\n * `Map`s (including non-string keys), `Set`s and other iterables, `Error`s (with their name, message, cause, and own properties),\n * and `RegExp`s. Symbols and functions without `toJSON` throw. The output is not meant to be deserialized back into the original value.\n * The format inside the code block is an implementation detail and may change.\n */\nexport function serializeForPrompt(value: unknown): string {\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '' })}\\n`, 'yaml');\n}\n\n// The functions below reproduce `stringify(value, { lineWidth: 0, aliasDuplicateObjects: false, blockQuote: 'literal' })`\n// of the `yaml` package, except that `toSerializable` makes `Error`s and `RegExp`s readable instead of `{}`.\n\nfunction stringifyValue(value: unknown, ctx: Context): string {\n switch (typeof value) {\n case 'undefined': {\n return 'null';\n }\n case 'boolean': {\n return String(value);\n }\n case 'number': {\n return stringifyNumber(value);\n }\n case 'bigint': {\n return String(value);\n }\n case 'string': {\n return stringifyString(value, ctx);\n }\n case 'object': {\n if (value === null) return 'null';\n const separator = `\\n${ctx.indent}`;\n let str = '';\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n const itemCtx = { indent: ctx.indent + INDENT_STEP };\n for (const item of value as unknown[]) {\n str += `${str ? separator : ''}- ${stringifyValue(toSerializable(item), itemCtx)}`;\n }\n return str;\n }\n if (value instanceof Map) {\n for (const [key, item] of value) {\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n }\n const record = value as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n const item = record[key];\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n }\n default: {\n throw new TypeError(`Cannot serialize a ${typeof value} value for a prompt`);\n }\n }\n}\n\nfunction stringifyPair(rawKey: unknown, rawValue: unknown, ctx: Context): string {\n const indent = ctx.indent + INDENT_STEP;\n const key = toSerializable(rawKey);\n const value = toSerializable(rawValue);\n const keyStr = stringifyValue(key, { indent, implicitKey: true });\n const valueStr = stringifyValue(value, { indent });\n if (isCollection(key) || keyStr.length > MAX_IMPLICIT_KEY_LENGTH) return `? ${keyStr}\\n${ctx.indent}: ${valueStr}`;\n const isBlockCollection = isCollection(value) && valueStr !== '[]' && valueStr !== '{}';\n return `${keyStr}:${isBlockCollection ? `\\n${indent}` : ' '}${valueStr}`;\n}\n\nfunction toSerializable(rawValue: unknown): unknown {\n // Like `yaml`, call `toJSON` only once, but classify its result.\n const value =\n typeof (rawValue as { toJSON?: unknown } | null | undefined)?.toJSON === 'function'\n ? (rawValue as { toJSON: () => unknown }).toJSON()\n : rawValue;\n if (typeof value !== 'object' || value === null || Array.isArray(value) || value instanceof Map) return value;\n // oxlint-disable-next-line unicorn/no-instanceof-builtins -- boxed primitives have no typeof check; `yaml` unwraps them the same way.\n if (value instanceof String || value instanceof Number || value instanceof Boolean || value instanceof BigInt) {\n return value.valueOf();\n }\n if (value instanceof Error) {\n // `name` and `message` usually live on the prototype, and `cause` and `errors` are not enumerable.\n return {\n name: value.name,\n message: value.message,\n ...Object.fromEntries(Object.entries(value)),\n ...('cause' in value && { cause: value.cause }),\n ...(value instanceof AggregateError && { errors: value.errors }),\n };\n }\n if (value instanceof RegExp) return String(value);\n return Symbol.iterator in value ? [...(value as Iterable<unknown>)] : value;\n}\n\nfunction isCollection(value: unknown): value is object {\n return typeof value === 'object' && value !== null;\n}\n\nfunction stringifyNumber(value: number): string {\n if (Number.isNaN(value)) return '.nan';\n if (!Number.isFinite(value)) return value < 0 ? '-.inf' : '.inf';\n return Object.is(value, -0) ? '-0' : JSON.stringify(value);\n}\n\nfunction stringifyString(value: string, ctx: Context): string {\n // oxlint-disable-next-line no-control-regex -- control characters and lone surrogates can only be written escaped.\n return /[\\u0000-\\u0008\\u000B-\\u001F\\u007F-\\u009F\\u{D800}-\\u{DFFF}]/u.test(value)\n ? doubleQuotedString(value, ctx)\n : plainString(value, ctx);\n}\n\nfunction plainString(value: string, ctx: Context): string {\n const { implicitKey, indent } = ctx;\n if (value.includes('\\n')) return implicitKey ? quotedString(value, ctx) : blockString(value, ctx);\n if (UNSAFE_PLAIN_START.test(value) || UNSAFE_PLAIN_END.test(value.slice(-1)) || UNSAFE_PLAIN_MIDDLE.test(value)) {\n return quotedString(value, ctx);\n }\n if (containsDocumentMarker(value)) {\n if (indent === '') return blockString(value, ctx);\n if (implicitKey && indent === INDENT_STEP) return quotedString(value, ctx);\n }\n return NON_STRING_SCALAR.test(value) ? quotedString(value, ctx) : value;\n}\n\nfunction blockString(value: string, ctx: Context): string {\n let endStart = value.length;\n while (endStart > 0 && isBlockEndWhitespace(value.codePointAt(endStart - 1))) endStart--;\n let end = value.slice(endStart);\n // A block scalar cannot end with a whitespace-only line.\n if (end.includes('\\n') && !end.endsWith('\\n')) return quotedString(value, ctx);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n\n const endNewlinePos = end.indexOf('\\n');\n const chomp = endNewlinePos === -1 ? '-' : value === end || endNewlinePos !== end.length - 1 ? '+' : '';\n if (end) {\n value = value.slice(0, -end.length);\n if (end.endsWith('\\n')) end = end.slice(0, -1);\n end = end.replaceAll(/(?:^|(?<!\\n))\\n+(?!\\n|$)/gu, `$&${indent}`);\n }\n\n const leadingWhitespace = /^[\\n ]*/u.exec(value)?.[0] ?? '';\n const startsWithSpace = leadingWhitespace.includes(' ');\n let start = value.slice(0, leadingWhitespace.lastIndexOf('\\n') + 1);\n if (start) {\n value = value.slice(start.length);\n start = start.replaceAll(/\\n+/gu, `$&${indent}`);\n }\n\n const header = (startsWithSpace ? (indent ? '2' : '1') : '') + chomp;\n return `|${header}\\n${indent}${start}${indentLines(value, indent)}${end}`;\n}\n\nfunction quotedString(value: string, ctx: Context): string {\n return value.includes('\"') && !value.includes(\"'\") ? singleQuotedString(value, ctx) : doubleQuotedString(value, ctx);\n}\n\nfunction singleQuotedString(value: string, ctx: Context): string {\n // Every multi-line value reaching here would contain a space or tab next to a newline or be an implicit key,\n // both of which need double quotes.\n if (value.includes('\\n')) return doubleQuotedString(value, ctx);\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction doubleQuotedString(value: string, ctx: Context): string {\n const json = JSON.stringify(value);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n let str = '';\n let start = 0;\n for (let i = 0; i < json.length; i++) {\n let ch = json[i];\n if (ch === ' ' && json[i + 1] === '\\\\' && json[i + 2] === 'n') {\n // A space before a line break would be folded away unless escaped.\n str += `${json.slice(start, i)}\\\\ `;\n i++;\n start = i;\n ch = '\\\\';\n }\n if (ch !== '\\\\') continue;\n if (json[i + 1] === 'u') {\n const code = json.slice(i + 2, i + 6);\n str +=\n json.slice(start, i) +\n (SHORT_UNICODE_ESCAPES[code] ?? (code.startsWith('00') ? `\\\\x${code.slice(2)}` : json.slice(i, i + 6)));\n i += 5;\n start = i + 1;\n } else if (\n json[i + 1] === 'n' &&\n !ctx.implicitKey &&\n json[i + 2] !== '\"' &&\n json.length >= MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH\n ) {\n // Folding turns the first of the written line breaks back into a space, hence the extra one.\n str += `${json.slice(start, i)}\\n\\n`;\n while (json[i + 2] === '\\\\' && json[i + 3] === 'n' && json[i + 4] !== '\"') {\n str += '\\n';\n i += 2;\n }\n str += indent;\n // A space after a line break would be folded away unless escaped.\n if (json[i + 2] === ' ') str += '\\\\';\n i++;\n start = i + 1;\n } else {\n i++;\n }\n }\n return start ? str + json.slice(start) : json;\n}\n\nfunction containsDocumentMarker(value: string): boolean {\n return /^(?:%|---|\\.\\.\\.)/mu.test(value);\n}\n\n/** Equivalent to `text.replaceAll(/\\n+/g, `$&${indent}`)` for text without leading or trailing newlines, but faster. */\nfunction indentLines(text: string, indent: string): string {\n const lines = text.split('\\n');\n let str = lines[0] ?? '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n str += line ? `\\n${indent}${line}` : '\\n';\n }\n return str;\n}\n\nfunction isBlockEndWhitespace(codePoint: number | undefined): boolean {\n return codePoint === 0x0A || codePoint === 0x09 || codePoint === 0x20;\n}\n"],"mappings":"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"}
|
package/dist/text.cjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";function e(e){return e.replaceAll(/[$()*+.?[\\\]^{|}]/gu,String.raw`\$&`)}function t(e){return/^[\w./-]+$/u.test(e)?e:`'${e.replaceAll(`'`,String.raw`'\''`)}'`}function n(e,t=``){let n=2,r=e.indexOf(`~~~`);for(;r!==-1;){let t=r+3;for(;e[t]===`~`;)t++;n=Math.max(n,t-r),r=e.indexOf(`~~~`,t)}let i=`~`.repeat(n+1);return`${i}${t}\n${e}${e.endsWith(`
|
|
2
|
+
`)?``:`
|
|
3
|
+
`}${i}`}exports.escapeRegExp=e,exports.quoteForShell=t,exports.toTildeCodeBlock=n;
|
|
4
|
+
//# sourceMappingURL=text.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.cjs","names":[],"sources":["../src/text.ts"],"sourcesContent":["/** Escapes every RegExp metacharacter so the text matches itself literally. */\nexport function escapeRegExp(text: string): string {\n return text.replaceAll(/[$()*+.?[\\\\\\]^{|}]/gu, String.raw`\\$&`);\n}\n\n/** A POSIX shell word: safe characters pass through, anything else is single-quoted. */\nexport function quoteForShell(value: string): string {\n return /^[\\w./-]+$/u.test(value) ? value : `'${value.replaceAll(\"'\", String.raw`'\\''`)}'`;\n}\n\n/**\n * Wraps text in a Markdown code block fenced with tildes, which are rarer than backticks in Markdown content.\n * The fence is longer than any run of tildes in the text so that the text cannot close it.\n */\nexport function toTildeCodeBlock(text: string, language = ''): string {\n let longestRun = 2;\n let start = text.indexOf('~~~');\n while (start !== -1) {\n let end = start + 3;\n while (text[end] === '~') end++;\n longestRun = Math.max(longestRun, end - start);\n start = text.indexOf('~~~', end);\n }\n const fence = '~'.repeat(longestRun + 1);\n return `${fence}${language}\\n${text}${text.endsWith('\\n') ? '' : '\\n'}${fence}`;\n}\n"],"mappings":"aACA,SAAgB,EAAa,EAAsB,CACjD,OAAO,EAAK,WAAW,uBAAwB,OAAO,GAAG,KAAK,CAChE,CAGA,SAAgB,EAAc,EAAuB,CACnD,MAAO,cAAc,KAAK,CAAK,EAAI,EAAQ,IAAI,EAAM,WAAW,IAAK,OAAO,GAAG,MAAM,EAAE,EACzF,CAMA,SAAgB,EAAiB,EAAc,EAAW,GAAY,CACpE,IAAI,EAAa,EACb,EAAQ,EAAK,QAAQ,KAAK,EAC9B,KAAO,IAAU,IAAI,CACnB,IAAI,EAAM,EAAQ,EAClB,KAAO,EAAK,KAAS,KAAK,IAC1B,EAAa,KAAK,IAAI,EAAY,EAAM,CAAK,EAC7C,EAAQ,EAAK,QAAQ,MAAO,CAAG,CACjC,CACA,IAAM,EAAQ,IAAI,OAAO,EAAa,CAAC,EACvC,MAAO,GAAG,IAAQ,EAAS,IAAI,IAAO,EAAK,SAAS;CAAI,EAAI,GAAK;IAAO,GAC1E"}
|
package/dist/text.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Escapes every RegExp metacharacter so the text matches itself literally. */
|
|
2
|
+
export declare function escapeRegExp(text: string): string;
|
|
3
|
+
/** A POSIX shell word: safe characters pass through, anything else is single-quoted. */
|
|
4
|
+
export declare function quoteForShell(value: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Wraps text in a Markdown code block fenced with tildes, which are rarer than backticks in Markdown content.
|
|
7
|
+
* The fence is longer than any run of tildes in the text so that the text cannot close it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function toTildeCodeBlock(text: string, language?: string): string;
|
package/dist/text.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
function e(e){return e.replaceAll(/[$()*+.?[\\\]^{|}]/gu,String.raw`\$&`)}function t(e){return/^[\w./-]+$/u.test(e)?e:`'${e.replaceAll(`'`,String.raw`'\''`)}'`}function n(e,t=``){let n=2,r=e.indexOf(`~~~`);for(;r!==-1;){let t=r+3;for(;e[t]===`~`;)t++;n=Math.max(n,t-r),r=e.indexOf(`~~~`,t)}let i=`~`.repeat(n+1);return`${i}${t}\n${e}${e.endsWith(`
|
|
2
|
+
`)?``:`
|
|
3
|
+
`}${i}`}export{e as escapeRegExp,t as quoteForShell,n as toTildeCodeBlock};
|
|
4
|
+
//# sourceMappingURL=text.js.map
|
package/dist/text.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","names":[],"sources":["../src/text.ts"],"sourcesContent":["/** Escapes every RegExp metacharacter so the text matches itself literally. */\nexport function escapeRegExp(text: string): string {\n return text.replaceAll(/[$()*+.?[\\\\\\]^{|}]/gu, String.raw`\\$&`);\n}\n\n/** A POSIX shell word: safe characters pass through, anything else is single-quoted. */\nexport function quoteForShell(value: string): string {\n return /^[\\w./-]+$/u.test(value) ? value : `'${value.replaceAll(\"'\", String.raw`'\\''`)}'`;\n}\n\n/**\n * Wraps text in a Markdown code block fenced with tildes, which are rarer than backticks in Markdown content.\n * The fence is longer than any run of tildes in the text so that the text cannot close it.\n */\nexport function toTildeCodeBlock(text: string, language = ''): string {\n let longestRun = 2;\n let start = text.indexOf('~~~');\n while (start !== -1) {\n let end = start + 3;\n while (text[end] === '~') end++;\n longestRun = Math.max(longestRun, end - start);\n start = text.indexOf('~~~', end);\n }\n const fence = '~'.repeat(longestRun + 1);\n return `${fence}${language}\\n${text}${text.endsWith('\\n') ? '' : '\\n'}${fence}`;\n}\n"],"mappings":"AACA,SAAgB,EAAa,EAAsB,CACjD,OAAO,EAAK,WAAW,uBAAwB,OAAO,GAAG,KAAK,CAChE,CAGA,SAAgB,EAAc,EAAuB,CACnD,MAAO,cAAc,KAAK,CAAK,EAAI,EAAQ,IAAI,EAAM,WAAW,IAAK,OAAO,GAAG,MAAM,EAAE,EACzF,CAMA,SAAgB,EAAiB,EAAc,EAAW,GAAY,CACpE,IAAI,EAAa,EACb,EAAQ,EAAK,QAAQ,KAAK,EAC9B,KAAO,IAAU,IAAI,CACnB,IAAI,EAAM,EAAQ,EAClB,KAAO,EAAK,KAAS,KAAK,IAC1B,EAAa,KAAK,IAAI,EAAY,EAAM,CAAK,EAC7C,EAAQ,EAAK,QAAQ,MAAO,CAAG,CACjC,CACA,IAAM,EAAQ,IAAI,OAAO,EAAa,CAAC,EACvC,MAAO,GAAG,IAAQ,EAAS,IAAI,IAAO,EAAK,SAAS;CAAI,EAAI,GAAK;IAAO,GAC1E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@willbooster/shared-lib",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.7.0",
|
|
4
4
|
"description": "Shared library for WillBooster projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -45,18 +45,19 @@
|
|
|
45
45
|
"@tsconfig/bun": "1.0.11",
|
|
46
46
|
"@tsconfig/node-lts": "24.0.1",
|
|
47
47
|
"@tsconfig/node-ts": "23.6.4",
|
|
48
|
-
"@types/bun": "1.4.
|
|
49
|
-
"@types/node": "26.
|
|
48
|
+
"@types/bun": "1.4.2",
|
|
49
|
+
"@types/node": "26.5.1",
|
|
50
50
|
"@willbooster/oxfmt-config": "1.2.2",
|
|
51
51
|
"@willbooster/oxlint-config": "1.4.8",
|
|
52
|
-
"@willbooster/wb": "22.
|
|
53
|
-
"build-ts": "21.0.
|
|
54
|
-
"oxfmt": "0.
|
|
55
|
-
"oxlint": "1.
|
|
52
|
+
"@willbooster/wb": "22.4.0",
|
|
53
|
+
"build-ts": "21.0.14",
|
|
54
|
+
"oxfmt": "0.67.0",
|
|
55
|
+
"oxlint": "1.82.0",
|
|
56
56
|
"oxlint-tsgolint": "7.0.2001",
|
|
57
57
|
"sort-package-json": "4.0.0",
|
|
58
58
|
"typescript": "7.0.2",
|
|
59
|
-
"vitest": "
|
|
59
|
+
"vitest": "5.0.0",
|
|
60
|
+
"yaml": "2.9.0"
|
|
60
61
|
},
|
|
61
62
|
"publishConfig": {
|
|
62
63
|
"access": "public",
|