@agimon-ai/doompi-help 0.0.1-alpha.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +28 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +1 -0
  4. package/dist/adapters/helpStorage.cjs +2 -0
  5. package/dist/adapters/helpStorage.cjs.map +1 -0
  6. package/dist/adapters/helpStorage.mjs +2 -0
  7. package/dist/adapters/helpStorage.mjs.map +1 -0
  8. package/dist/adapters/llmsResolver.cjs +2 -0
  9. package/dist/adapters/llmsResolver.cjs.map +1 -0
  10. package/dist/adapters/llmsResolver.mjs +2 -0
  11. package/dist/adapters/llmsResolver.mjs.map +1 -0
  12. package/dist/adapters/pi/helpMode.cjs +2 -0
  13. package/dist/adapters/pi/helpMode.cjs.map +1 -0
  14. package/dist/adapters/pi/helpMode.mjs +2 -0
  15. package/dist/adapters/pi/helpMode.mjs.map +1 -0
  16. package/dist/container/index.cjs +2 -0
  17. package/dist/container/index.cjs.map +1 -0
  18. package/dist/container/index.d.cts +13 -0
  19. package/dist/container/index.d.cts.map +1 -0
  20. package/dist/container/index.d.mts +13 -0
  21. package/dist/container/index.d.mts.map +1 -0
  22. package/dist/container/index.mjs +2 -0
  23. package/dist/container/index.mjs.map +1 -0
  24. package/dist/extensions/doom.cjs +2 -0
  25. package/dist/extensions/doom.cjs.map +1 -0
  26. package/dist/extensions/doom.d.cts +8 -0
  27. package/dist/extensions/doom.d.cts.map +1 -0
  28. package/dist/extensions/doom.d.mts +8 -0
  29. package/dist/extensions/doom.d.mts.map +1 -0
  30. package/dist/extensions/doom.mjs +2 -0
  31. package/dist/extensions/doom.mjs.map +1 -0
  32. package/dist/index.cjs +1 -0
  33. package/dist/index.d.cts +2 -0
  34. package/dist/index.d.mts +2 -0
  35. package/dist/index.mjs +1 -0
  36. package/dist/services/helpActivation.cjs +2 -0
  37. package/dist/services/helpActivation.cjs.map +1 -0
  38. package/dist/services/helpActivation.d.cts +2 -0
  39. package/dist/services/helpActivation.d.mts +2 -0
  40. package/dist/services/helpActivation.mjs +2 -0
  41. package/dist/services/helpActivation.mjs.map +1 -0
  42. package/dist/services/llmsContent.cjs +2 -0
  43. package/dist/services/llmsContent.cjs.map +1 -0
  44. package/dist/services/llmsContent.mjs +2 -0
  45. package/dist/services/llmsContent.mjs.map +1 -0
  46. package/dist/types/help.d.cts +18 -0
  47. package/dist/types/help.d.cts.map +1 -0
  48. package/dist/types/help.d.mts +18 -0
  49. package/dist/types/help.d.mts.map +1 -0
  50. package/llms.txt +7 -0
  51. package/package.json +79 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vuong Ngo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # @agimon-ai/doompi-help
2
+
3
+ Activation-gated package guidance for DoomPi.
4
+
5
+ The runtime is assembled only in parent Doom Pi sessions and starts inactive. `SPC h e` and
6
+ the existing `minor_mode` client share the same activation service. Activation resolves a
7
+ contributor's bundled `llms.txt` first, then an immutable exact-version cache, and finally a
8
+ verified exact-version unpkg fallback. Deactivation removes generated Help skill wrappers
9
+ before the next prompt or catalog access; child sessions never load this package.
10
+
11
+ The package itself contributes `doompi-help`. Workflow and Config contribute
12
+ `workflow-help` and `doompi-config-help` from their own package indexes.
13
+
14
+ ## Development
15
+
16
+ ```bash
17
+ pnpm build
18
+ pnpm typecheck
19
+ pnpm test
20
+ pnpm lint
21
+ ```
22
+
23
+ The parent-only Doom extension entrypoint is `@agimon-ai/doompi-help/extensions/doom`.
24
+
25
+ ## Release order
26
+
27
+ Publish `@agimon-ai/doompi-extension-contracts` before `@agimon-ai/doompi-help`, then publish
28
+ the `@agimon-ai/doompi` runtime that consumes both. Do not hand-edit generated changelogs.
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));exports.__toESM=s;
@@ -0,0 +1,2 @@
1
+ const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../services/llmsContent.cjs");let n=require("node:crypto"),r=require("node:fs");r=e.__toESM(r,1);let i=require("node:os");i=e.__toESM(i,1);let a=require("node:path");a=e.__toESM(a,1);let o=require("node:url");const s=`llms.txt`,c=`.complete`,l=`metadata.json`,u=`SKILL.md`,d=/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u,f=/^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/u;function p(e){if(e.aborted)throw Error(`Help activation was cancelled.`)}function m(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function h(e,t){let n=a.default.relative(e,t);return n===``||!n.startsWith(`..${a.default.sep}`)&&n!==`..`&&!a.default.isAbsolute(n)}function g(e){let t;try{t=JSON.parse(r.default.readFileSync(e,`utf8`))}catch(t){throw Error(`Cannot read Help package manifest at ${e}: ${t instanceof Error?t.message:String(t)}`)}if(!m(t))throw Error(`Help package manifest at ${e} must contain an object.`);return t}function _(e,t){if(!f.test(t))throw Error(`Help source '${t}' must be a valid lowercase npm package name.`);let n;try{let t=new URL(e);if(t.protocol!==`file:`)throw Error(`Help module URL must use file:, received ${t.protocol}`);n=r.default.realpathSync((0,o.fileURLToPath)(t))}catch(t){throw Error(`Invalid Help contributor module URL '${e}': ${t instanceof Error?t.message:String(t)}`)}if(!r.default.lstatSync(n).isFile())throw Error(`Help contributor module is not a regular file: ${n}`);let i=a.default.dirname(n);for(;;){let e=a.default.join(i,`package.json`);if(r.default.existsSync(e)){let a=g(e),o=a.name,s=a.version;if(o!==t)throw Error(`Help source '${t}' does not match nearest package '${String(o)}'.`);if(typeof s!=`string`||!d.test(s))throw Error(`Help package '${t}' must declare an exact semantic version.`);let c=r.default.realpathSync(i);if(!h(c,n))throw Error(`Help contributor module escapes its resolved package root.`);return{source:t,version:s,packageRoot:c,modulePath:n}}let o=a.default.dirname(i);if(o===i)break;i=o}throw Error(`Cannot find a package manifest for Help contributor ${n}.`)}function v(e=i.default.homedir()){return a.default.join(e,`.pi`,`.doom`,`llms-cache`)}function y(e){return(0,n.createHash)(`sha256`).update(e).digest(`hex`)}function b(e,t){if(m(e)&&e.schemaVersion===1&&e.source===t.source&&e.version===t.version&&e.path===s&&typeof e.integrity==`string`&&typeof e.digest==`string`&&typeof e.referenceBase==`string`)return e}function x(e){try{let t=r.default.lstatSync(e);return t.isFile()&&!t.isSymbolicLink()}catch{return!1}}var S=class{root;constructor(e=v()){this.root=e}entryDirectory(e){let t=y(`${e.source}\0${e.version}\0${s}`);return a.default.join(this.root,t)}discard(e){r.default.rmSync(this.entryDirectory(e),{recursive:!0,force:!0})}read(e){let t=this.entryDirectory(e),n=a.default.join(t,c),i=a.default.join(t,s),o=a.default.join(t,l);if(!(!x(n)||!x(i)||!x(o)))try{let t=b(JSON.parse(r.default.readFileSync(o,`utf8`)),e);if(!t)return;let a=r.default.readFileSync(i);return y(a)!==t.digest||r.default.readFileSync(n,`utf8`).trim()!==t.digest?void 0:{bytes:a,filePath:i,integrity:t.integrity,digest:t.digest,referenceBase:t.referenceBase}}catch{return}}publish(e,t,i,o,u){p(u);let d=this.read(e);if(d)return d;let f=this.entryDirectory(e);r.default.mkdirSync(this.root,{mode:448,recursive:!0}),r.default.existsSync(f)&&r.default.rmSync(f,{recursive:!0,force:!0});let m=`${f}.${process.pid}.${(0,n.randomUUID)()}.tmp`,h=y(t),g={schemaVersion:1,source:e.source,version:e.version,path:s,integrity:i,digest:h,referenceBase:o};try{r.default.mkdirSync(m,{mode:448}),r.default.writeFileSync(a.default.join(m,s),t,{mode:384}),r.default.writeFileSync(a.default.join(m,l),`${JSON.stringify(g,null,2)}\n`,{mode:384}),p(u),r.default.writeFileSync(a.default.join(m,c),`${h}\n`,{mode:384});try{r.default.renameSync(m,f)}catch(t){let n=this.read(e);if(n)return n;throw t}return{bytes:Uint8Array.from(t),filePath:a.default.join(f,s),integrity:i,digest:h,referenceBase:o}}finally{r.default.rmSync(m,{recursive:!0,force:!0})}}},C=class{cacheRoot;constructor(e=v()){this.cacheRoot=e}async materialize(e,i,o){let s=[];for(let c of e.skills){p(o);let l=y(`${i.identity.source}\0${i.identity.version}\0${c.name}\0${c.description}\0${i.digest}`),d=a.default.join(this.cacheRoot,`wrappers`,l),f=a.default.join(d,u),m=t.renderHelpSkillWrapper(c,i);if(!x(f)||r.default.readFileSync(f,`utf8`)!==m){r.default.mkdirSync(a.default.dirname(d),{mode:448,recursive:!0}),r.default.existsSync(d)&&r.default.rmSync(d,{recursive:!0,force:!0});let e=`${d}.${process.pid}.${(0,n.randomUUID)()}.tmp`;try{r.default.mkdirSync(e,{mode:448}),r.default.writeFileSync(a.default.join(e,u),m,{mode:384}),p(o);try{r.default.renameSync(e,d)}catch(e){if(!x(f)||r.default.readFileSync(f,`utf8`)!==m)throw e}}finally{r.default.rmSync(e,{recursive:!0,force:!0})}}s.push({source:e.source,name:c.name,description:c.description,filePath:f,baseDir:d})}return s}};exports.DefaultHelpSkillMaterializer=C,exports.HelpIndexCache=S,exports.defaultHelpCacheRoot=v,exports.resolveHelpPackageIdentity=_,exports.sha256Hex=y;
2
+ //# sourceMappingURL=helpStorage.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpStorage.cjs","names":["path","fs","fileURLToPath","os","createHash","randomUUID","renderHelpSkillWrapper"],"sources":["../../src/adapters/helpStorage.ts"],"sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { DoomHelpContribution, DoomHelpSkill } from '@agimon-ai/doompi-extension-contracts/help';\nimport { renderHelpSkillWrapper } from '../services/llmsContent.ts';\nimport type { HelpPackageIdentity, HelpSkillMaterializer, ResolvedHelpIndex } from '../types/help.ts';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst HELP_INDEX_PATH = 'llms.txt';\nconst CACHE_SCHEMA_VERSION = 1;\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst COMPLETION_FILE = '.complete';\nconst CACHE_METADATA_FILE = 'metadata.json';\nconst WRAPPER_DIRECTORY = 'wrappers';\nconst SKILL_FILE = 'SKILL.md';\nconst EXACT_SEMVER_PATTERN =\n /^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/u;\nconst NPM_PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._~-]*\\/)?[a-z0-9][a-z0-9._~-]*$/u;\n\ninterface CacheMetadata {\n schemaVersion: typeof CACHE_SCHEMA_VERSION;\n source: string;\n version: string;\n path: typeof HELP_INDEX_PATH;\n integrity: string;\n digest: string;\n referenceBase: string;\n}\n\nexport interface CachedHelpIndex {\n bytes: Uint8Array;\n filePath: string;\n integrity: string;\n digest: string;\n referenceBase: string;\n}\n\nfunction assertNotAborted(signal: AbortSignal): void {\n if (signal.aborted) throw new Error('Help activation was cancelled.');\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isContained(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));\n}\n\nfunction readManifest(filePath: string): Record<string, unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(filePath, 'utf8')) as unknown;\n } catch (error) {\n throw new Error(\n `Cannot read Help package manifest at ${filePath}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!isRecord(parsed)) throw new Error(`Help package manifest at ${filePath} must contain an object.`);\n return parsed;\n}\n\nexport function resolveHelpPackageIdentity(moduleUrl: string, expectedSource: string): HelpPackageIdentity {\n if (!NPM_PACKAGE_NAME_PATTERN.test(expectedSource)) {\n throw new Error(`Help source '${expectedSource}' must be a valid lowercase npm package name.`);\n }\n let modulePath: string;\n try {\n const url = new URL(moduleUrl);\n if (url.protocol !== 'file:') throw new Error(`Help module URL must use file:, received ${url.protocol}`);\n modulePath = fs.realpathSync(fileURLToPath(url));\n } catch (error) {\n throw new Error(\n `Invalid Help contributor module URL '${moduleUrl}': ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!fs.lstatSync(modulePath).isFile())\n throw new Error(`Help contributor module is not a regular file: ${modulePath}`);\n\n let directory = path.dirname(modulePath);\n while (true) {\n const manifestPath = path.join(directory, PACKAGE_MANIFEST);\n if (fs.existsSync(manifestPath)) {\n const manifest = readManifest(manifestPath);\n const source = manifest.name;\n const version = manifest.version;\n if (source !== expectedSource) {\n throw new Error(`Help source '${expectedSource}' does not match nearest package '${String(source)}'.`);\n }\n if (typeof version !== 'string' || !EXACT_SEMVER_PATTERN.test(version)) {\n throw new Error(`Help package '${expectedSource}' must declare an exact semantic version.`);\n }\n const packageRoot = fs.realpathSync(directory);\n if (!isContained(packageRoot, modulePath))\n throw new Error('Help contributor module escapes its resolved package root.');\n return { source: expectedSource, version, packageRoot, modulePath };\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n throw new Error(`Cannot find a package manifest for Help contributor ${modulePath}.`);\n}\n\nexport function defaultHelpCacheRoot(homeDirectory = os.homedir()): string {\n return path.join(homeDirectory, '.pi', '.doom', 'llms-cache');\n}\n\nexport function sha256Hex(bytes: Uint8Array | string): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\nfunction parseCacheMetadata(value: unknown, identity: HelpPackageIdentity): CacheMetadata | undefined {\n if (!isRecord(value)) return undefined;\n if (\n value.schemaVersion !== CACHE_SCHEMA_VERSION ||\n value.source !== identity.source ||\n value.version !== identity.version ||\n value.path !== HELP_INDEX_PATH ||\n typeof value.integrity !== 'string' ||\n typeof value.digest !== 'string' ||\n typeof value.referenceBase !== 'string'\n ) {\n return undefined;\n }\n return value as unknown as CacheMetadata;\n}\n\nfunction regularFile(filePath: string): boolean {\n try {\n const metadata = fs.lstatSync(filePath);\n return metadata.isFile() && !metadata.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\nexport class HelpIndexCache {\n readonly root: string;\n\n constructor(root = defaultHelpCacheRoot()) {\n this.root = root;\n }\n\n entryDirectory(identity: HelpPackageIdentity): string {\n const key = sha256Hex(`${identity.source}\\0${identity.version}\\0${HELP_INDEX_PATH}`);\n return path.join(this.root, key);\n }\n\n discard(identity: HelpPackageIdentity): void {\n fs.rmSync(this.entryDirectory(identity), { recursive: true, force: true });\n }\n\n read(identity: HelpPackageIdentity): CachedHelpIndex | undefined {\n const directory = this.entryDirectory(identity);\n const completionPath = path.join(directory, COMPLETION_FILE);\n const indexPath = path.join(directory, HELP_INDEX_PATH);\n const metadataPath = path.join(directory, CACHE_METADATA_FILE);\n if (!regularFile(completionPath) || !regularFile(indexPath) || !regularFile(metadataPath)) return undefined;\n try {\n const metadata = parseCacheMetadata(JSON.parse(fs.readFileSync(metadataPath, 'utf8')) as unknown, identity);\n if (!metadata) return undefined;\n const bytes = fs.readFileSync(indexPath);\n if (sha256Hex(bytes) !== metadata.digest) return undefined;\n if (fs.readFileSync(completionPath, 'utf8').trim() !== metadata.digest) return undefined;\n return {\n bytes,\n filePath: indexPath,\n integrity: metadata.integrity,\n digest: metadata.digest,\n referenceBase: metadata.referenceBase,\n };\n } catch {\n return undefined;\n }\n }\n\n publish(\n identity: HelpPackageIdentity,\n bytes: Uint8Array,\n integrity: string,\n referenceBase: string,\n signal: AbortSignal,\n ): CachedHelpIndex {\n assertNotAborted(signal);\n const existing = this.read(identity);\n if (existing) return existing;\n const directory = this.entryDirectory(identity);\n fs.mkdirSync(this.root, { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n if (fs.existsSync(directory)) fs.rmSync(directory, { recursive: true, force: true });\n const temporary = `${directory}.${process.pid}.${randomUUID()}.tmp`;\n const digest = sha256Hex(bytes);\n const metadata: CacheMetadata = {\n schemaVersion: CACHE_SCHEMA_VERSION,\n source: identity.source,\n version: identity.version,\n path: HELP_INDEX_PATH,\n integrity,\n digest,\n referenceBase,\n };\n try {\n fs.mkdirSync(temporary, { mode: PRIVATE_DIRECTORY_MODE });\n fs.writeFileSync(path.join(temporary, HELP_INDEX_PATH), bytes, { mode: PRIVATE_FILE_MODE });\n fs.writeFileSync(path.join(temporary, CACHE_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}\\n`, {\n mode: PRIVATE_FILE_MODE,\n });\n assertNotAborted(signal);\n fs.writeFileSync(path.join(temporary, COMPLETION_FILE), `${digest}\\n`, { mode: PRIVATE_FILE_MODE });\n try {\n fs.renameSync(temporary, directory);\n } catch (error) {\n const winner = this.read(identity);\n if (winner) return winner;\n throw error;\n }\n return {\n bytes: Uint8Array.from(bytes),\n filePath: path.join(directory, HELP_INDEX_PATH),\n integrity,\n digest,\n referenceBase,\n };\n } finally {\n fs.rmSync(temporary, { recursive: true, force: true });\n }\n }\n}\n\nexport class DefaultHelpSkillMaterializer implements HelpSkillMaterializer {\n constructor(private readonly cacheRoot = defaultHelpCacheRoot()) {}\n\n async materialize(\n contribution: DoomHelpContribution,\n index: ResolvedHelpIndex,\n signal: AbortSignal,\n ): Promise<readonly DoomHelpSkill[]> {\n const skills: DoomHelpSkill[] = [];\n for (const descriptor of contribution.skills) {\n assertNotAborted(signal);\n const key = sha256Hex(\n `${index.identity.source}\\0${index.identity.version}\\0${descriptor.name}\\0${descriptor.description}\\0${index.digest}`,\n );\n const directory = path.join(this.cacheRoot, WRAPPER_DIRECTORY, key);\n const filePath = path.join(directory, SKILL_FILE);\n const content = renderHelpSkillWrapper(descriptor, index);\n if (!regularFile(filePath) || fs.readFileSync(filePath, 'utf8') !== content) {\n fs.mkdirSync(path.dirname(directory), { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n if (fs.existsSync(directory)) fs.rmSync(directory, { recursive: true, force: true });\n const temporary = `${directory}.${process.pid}.${randomUUID()}.tmp`;\n try {\n fs.mkdirSync(temporary, { mode: PRIVATE_DIRECTORY_MODE });\n fs.writeFileSync(path.join(temporary, SKILL_FILE), content, { mode: PRIVATE_FILE_MODE });\n assertNotAborted(signal);\n try {\n fs.renameSync(temporary, directory);\n } catch (error) {\n if (!regularFile(filePath) || fs.readFileSync(filePath, 'utf8') !== content) throw error;\n }\n } finally {\n fs.rmSync(temporary, { recursive: true, force: true });\n }\n }\n skills.push({\n source: contribution.source,\n name: descriptor.name,\n description: descriptor.description,\n filePath,\n baseDir: directory,\n });\n }\n return skills;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{renderHelpSkillWrapper as e}from"../services/llmsContent.mjs";import{createHash as t,randomUUID as n}from"node:crypto";import r from"node:fs";import i from"node:os";import a from"node:path";import{fileURLToPath as o}from"node:url";const s=`llms.txt`,c=`.complete`,l=`metadata.json`,u=`SKILL.md`,d=/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u,f=/^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/u;function p(e){if(e.aborted)throw Error(`Help activation was cancelled.`)}function m(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function h(e,t){let n=a.relative(e,t);return n===``||!n.startsWith(`..${a.sep}`)&&n!==`..`&&!a.isAbsolute(n)}function g(e){let t;try{t=JSON.parse(r.readFileSync(e,`utf8`))}catch(t){throw Error(`Cannot read Help package manifest at ${e}: ${t instanceof Error?t.message:String(t)}`)}if(!m(t))throw Error(`Help package manifest at ${e} must contain an object.`);return t}function _(e,t){if(!f.test(t))throw Error(`Help source '${t}' must be a valid lowercase npm package name.`);let n;try{let t=new URL(e);if(t.protocol!==`file:`)throw Error(`Help module URL must use file:, received ${t.protocol}`);n=r.realpathSync(o(t))}catch(t){throw Error(`Invalid Help contributor module URL '${e}': ${t instanceof Error?t.message:String(t)}`)}if(!r.lstatSync(n).isFile())throw Error(`Help contributor module is not a regular file: ${n}`);let i=a.dirname(n);for(;;){let e=a.join(i,`package.json`);if(r.existsSync(e)){let a=g(e),o=a.name,s=a.version;if(o!==t)throw Error(`Help source '${t}' does not match nearest package '${String(o)}'.`);if(typeof s!=`string`||!d.test(s))throw Error(`Help package '${t}' must declare an exact semantic version.`);let c=r.realpathSync(i);if(!h(c,n))throw Error(`Help contributor module escapes its resolved package root.`);return{source:t,version:s,packageRoot:c,modulePath:n}}let o=a.dirname(i);if(o===i)break;i=o}throw Error(`Cannot find a package manifest for Help contributor ${n}.`)}function v(e=i.homedir()){return a.join(e,`.pi`,`.doom`,`llms-cache`)}function y(e){return t(`sha256`).update(e).digest(`hex`)}function b(e,t){if(m(e)&&e.schemaVersion===1&&e.source===t.source&&e.version===t.version&&e.path===s&&typeof e.integrity==`string`&&typeof e.digest==`string`&&typeof e.referenceBase==`string`)return e}function x(e){try{let t=r.lstatSync(e);return t.isFile()&&!t.isSymbolicLink()}catch{return!1}}var S=class{root;constructor(e=v()){this.root=e}entryDirectory(e){let t=y(`${e.source}\0${e.version}\0${s}`);return a.join(this.root,t)}discard(e){r.rmSync(this.entryDirectory(e),{recursive:!0,force:!0})}read(e){let t=this.entryDirectory(e),n=a.join(t,c),i=a.join(t,s),o=a.join(t,l);if(!(!x(n)||!x(i)||!x(o)))try{let t=b(JSON.parse(r.readFileSync(o,`utf8`)),e);if(!t)return;let a=r.readFileSync(i);return y(a)!==t.digest||r.readFileSync(n,`utf8`).trim()!==t.digest?void 0:{bytes:a,filePath:i,integrity:t.integrity,digest:t.digest,referenceBase:t.referenceBase}}catch{return}}publish(e,t,i,o,u){p(u);let d=this.read(e);if(d)return d;let f=this.entryDirectory(e);r.mkdirSync(this.root,{mode:448,recursive:!0}),r.existsSync(f)&&r.rmSync(f,{recursive:!0,force:!0});let m=`${f}.${process.pid}.${n()}.tmp`,h=y(t),g={schemaVersion:1,source:e.source,version:e.version,path:s,integrity:i,digest:h,referenceBase:o};try{r.mkdirSync(m,{mode:448}),r.writeFileSync(a.join(m,s),t,{mode:384}),r.writeFileSync(a.join(m,l),`${JSON.stringify(g,null,2)}\n`,{mode:384}),p(u),r.writeFileSync(a.join(m,c),`${h}\n`,{mode:384});try{r.renameSync(m,f)}catch(t){let n=this.read(e);if(n)return n;throw t}return{bytes:Uint8Array.from(t),filePath:a.join(f,s),integrity:i,digest:h,referenceBase:o}}finally{r.rmSync(m,{recursive:!0,force:!0})}}},C=class{cacheRoot;constructor(e=v()){this.cacheRoot=e}async materialize(t,i,o){let s=[];for(let c of t.skills){p(o);let l=y(`${i.identity.source}\0${i.identity.version}\0${c.name}\0${c.description}\0${i.digest}`),d=a.join(this.cacheRoot,`wrappers`,l),f=a.join(d,u),m=e(c,i);if(!x(f)||r.readFileSync(f,`utf8`)!==m){r.mkdirSync(a.dirname(d),{mode:448,recursive:!0}),r.existsSync(d)&&r.rmSync(d,{recursive:!0,force:!0});let e=`${d}.${process.pid}.${n()}.tmp`;try{r.mkdirSync(e,{mode:448}),r.writeFileSync(a.join(e,u),m,{mode:384}),p(o);try{r.renameSync(e,d)}catch(e){if(!x(f)||r.readFileSync(f,`utf8`)!==m)throw e}}finally{r.rmSync(e,{recursive:!0,force:!0})}}s.push({source:t.source,name:c.name,description:c.description,filePath:f,baseDir:d})}return s}};export{C as DefaultHelpSkillMaterializer,S as HelpIndexCache,v as defaultHelpCacheRoot,_ as resolveHelpPackageIdentity,y as sha256Hex};
2
+ //# sourceMappingURL=helpStorage.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpStorage.mjs","names":[],"sources":["../../src/adapters/helpStorage.ts"],"sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { DoomHelpContribution, DoomHelpSkill } from '@agimon-ai/doompi-extension-contracts/help';\nimport { renderHelpSkillWrapper } from '../services/llmsContent.ts';\nimport type { HelpPackageIdentity, HelpSkillMaterializer, ResolvedHelpIndex } from '../types/help.ts';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst HELP_INDEX_PATH = 'llms.txt';\nconst CACHE_SCHEMA_VERSION = 1;\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst COMPLETION_FILE = '.complete';\nconst CACHE_METADATA_FILE = 'metadata.json';\nconst WRAPPER_DIRECTORY = 'wrappers';\nconst SKILL_FILE = 'SKILL.md';\nconst EXACT_SEMVER_PATTERN =\n /^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/u;\nconst NPM_PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._~-]*\\/)?[a-z0-9][a-z0-9._~-]*$/u;\n\ninterface CacheMetadata {\n schemaVersion: typeof CACHE_SCHEMA_VERSION;\n source: string;\n version: string;\n path: typeof HELP_INDEX_PATH;\n integrity: string;\n digest: string;\n referenceBase: string;\n}\n\nexport interface CachedHelpIndex {\n bytes: Uint8Array;\n filePath: string;\n integrity: string;\n digest: string;\n referenceBase: string;\n}\n\nfunction assertNotAborted(signal: AbortSignal): void {\n if (signal.aborted) throw new Error('Help activation was cancelled.');\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isContained(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));\n}\n\nfunction readManifest(filePath: string): Record<string, unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(filePath, 'utf8')) as unknown;\n } catch (error) {\n throw new Error(\n `Cannot read Help package manifest at ${filePath}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!isRecord(parsed)) throw new Error(`Help package manifest at ${filePath} must contain an object.`);\n return parsed;\n}\n\nexport function resolveHelpPackageIdentity(moduleUrl: string, expectedSource: string): HelpPackageIdentity {\n if (!NPM_PACKAGE_NAME_PATTERN.test(expectedSource)) {\n throw new Error(`Help source '${expectedSource}' must be a valid lowercase npm package name.`);\n }\n let modulePath: string;\n try {\n const url = new URL(moduleUrl);\n if (url.protocol !== 'file:') throw new Error(`Help module URL must use file:, received ${url.protocol}`);\n modulePath = fs.realpathSync(fileURLToPath(url));\n } catch (error) {\n throw new Error(\n `Invalid Help contributor module URL '${moduleUrl}': ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!fs.lstatSync(modulePath).isFile())\n throw new Error(`Help contributor module is not a regular file: ${modulePath}`);\n\n let directory = path.dirname(modulePath);\n while (true) {\n const manifestPath = path.join(directory, PACKAGE_MANIFEST);\n if (fs.existsSync(manifestPath)) {\n const manifest = readManifest(manifestPath);\n const source = manifest.name;\n const version = manifest.version;\n if (source !== expectedSource) {\n throw new Error(`Help source '${expectedSource}' does not match nearest package '${String(source)}'.`);\n }\n if (typeof version !== 'string' || !EXACT_SEMVER_PATTERN.test(version)) {\n throw new Error(`Help package '${expectedSource}' must declare an exact semantic version.`);\n }\n const packageRoot = fs.realpathSync(directory);\n if (!isContained(packageRoot, modulePath))\n throw new Error('Help contributor module escapes its resolved package root.');\n return { source: expectedSource, version, packageRoot, modulePath };\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n throw new Error(`Cannot find a package manifest for Help contributor ${modulePath}.`);\n}\n\nexport function defaultHelpCacheRoot(homeDirectory = os.homedir()): string {\n return path.join(homeDirectory, '.pi', '.doom', 'llms-cache');\n}\n\nexport function sha256Hex(bytes: Uint8Array | string): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\nfunction parseCacheMetadata(value: unknown, identity: HelpPackageIdentity): CacheMetadata | undefined {\n if (!isRecord(value)) return undefined;\n if (\n value.schemaVersion !== CACHE_SCHEMA_VERSION ||\n value.source !== identity.source ||\n value.version !== identity.version ||\n value.path !== HELP_INDEX_PATH ||\n typeof value.integrity !== 'string' ||\n typeof value.digest !== 'string' ||\n typeof value.referenceBase !== 'string'\n ) {\n return undefined;\n }\n return value as unknown as CacheMetadata;\n}\n\nfunction regularFile(filePath: string): boolean {\n try {\n const metadata = fs.lstatSync(filePath);\n return metadata.isFile() && !metadata.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\nexport class HelpIndexCache {\n readonly root: string;\n\n constructor(root = defaultHelpCacheRoot()) {\n this.root = root;\n }\n\n entryDirectory(identity: HelpPackageIdentity): string {\n const key = sha256Hex(`${identity.source}\\0${identity.version}\\0${HELP_INDEX_PATH}`);\n return path.join(this.root, key);\n }\n\n discard(identity: HelpPackageIdentity): void {\n fs.rmSync(this.entryDirectory(identity), { recursive: true, force: true });\n }\n\n read(identity: HelpPackageIdentity): CachedHelpIndex | undefined {\n const directory = this.entryDirectory(identity);\n const completionPath = path.join(directory, COMPLETION_FILE);\n const indexPath = path.join(directory, HELP_INDEX_PATH);\n const metadataPath = path.join(directory, CACHE_METADATA_FILE);\n if (!regularFile(completionPath) || !regularFile(indexPath) || !regularFile(metadataPath)) return undefined;\n try {\n const metadata = parseCacheMetadata(JSON.parse(fs.readFileSync(metadataPath, 'utf8')) as unknown, identity);\n if (!metadata) return undefined;\n const bytes = fs.readFileSync(indexPath);\n if (sha256Hex(bytes) !== metadata.digest) return undefined;\n if (fs.readFileSync(completionPath, 'utf8').trim() !== metadata.digest) return undefined;\n return {\n bytes,\n filePath: indexPath,\n integrity: metadata.integrity,\n digest: metadata.digest,\n referenceBase: metadata.referenceBase,\n };\n } catch {\n return undefined;\n }\n }\n\n publish(\n identity: HelpPackageIdentity,\n bytes: Uint8Array,\n integrity: string,\n referenceBase: string,\n signal: AbortSignal,\n ): CachedHelpIndex {\n assertNotAborted(signal);\n const existing = this.read(identity);\n if (existing) return existing;\n const directory = this.entryDirectory(identity);\n fs.mkdirSync(this.root, { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n if (fs.existsSync(directory)) fs.rmSync(directory, { recursive: true, force: true });\n const temporary = `${directory}.${process.pid}.${randomUUID()}.tmp`;\n const digest = sha256Hex(bytes);\n const metadata: CacheMetadata = {\n schemaVersion: CACHE_SCHEMA_VERSION,\n source: identity.source,\n version: identity.version,\n path: HELP_INDEX_PATH,\n integrity,\n digest,\n referenceBase,\n };\n try {\n fs.mkdirSync(temporary, { mode: PRIVATE_DIRECTORY_MODE });\n fs.writeFileSync(path.join(temporary, HELP_INDEX_PATH), bytes, { mode: PRIVATE_FILE_MODE });\n fs.writeFileSync(path.join(temporary, CACHE_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}\\n`, {\n mode: PRIVATE_FILE_MODE,\n });\n assertNotAborted(signal);\n fs.writeFileSync(path.join(temporary, COMPLETION_FILE), `${digest}\\n`, { mode: PRIVATE_FILE_MODE });\n try {\n fs.renameSync(temporary, directory);\n } catch (error) {\n const winner = this.read(identity);\n if (winner) return winner;\n throw error;\n }\n return {\n bytes: Uint8Array.from(bytes),\n filePath: path.join(directory, HELP_INDEX_PATH),\n integrity,\n digest,\n referenceBase,\n };\n } finally {\n fs.rmSync(temporary, { recursive: true, force: true });\n }\n }\n}\n\nexport class DefaultHelpSkillMaterializer implements HelpSkillMaterializer {\n constructor(private readonly cacheRoot = defaultHelpCacheRoot()) {}\n\n async materialize(\n contribution: DoomHelpContribution,\n index: ResolvedHelpIndex,\n signal: AbortSignal,\n ): Promise<readonly DoomHelpSkill[]> {\n const skills: DoomHelpSkill[] = [];\n for (const descriptor of contribution.skills) {\n assertNotAborted(signal);\n const key = sha256Hex(\n `${index.identity.source}\\0${index.identity.version}\\0${descriptor.name}\\0${descriptor.description}\\0${index.digest}`,\n );\n const directory = path.join(this.cacheRoot, WRAPPER_DIRECTORY, key);\n const filePath = path.join(directory, SKILL_FILE);\n const content = renderHelpSkillWrapper(descriptor, index);\n if (!regularFile(filePath) || fs.readFileSync(filePath, 'utf8') !== content) {\n fs.mkdirSync(path.dirname(directory), { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n if (fs.existsSync(directory)) fs.rmSync(directory, { recursive: true, force: true });\n const temporary = `${directory}.${process.pid}.${randomUUID()}.tmp`;\n try {\n fs.mkdirSync(temporary, { mode: PRIVATE_DIRECTORY_MODE });\n fs.writeFileSync(path.join(temporary, SKILL_FILE), content, { mode: PRIVATE_FILE_MODE });\n assertNotAborted(signal);\n try {\n fs.renameSync(temporary, directory);\n } catch (error) {\n if (!regularFile(filePath) || fs.readFileSync(filePath, 'utf8') !== content) throw error;\n }\n } finally {\n fs.rmSync(temporary, { recursive: true, force: true });\n }\n }\n skills.push({\n source: contribution.source,\n name: descriptor.name,\n description: descriptor.description,\n filePath,\n baseDir: directory,\n });\n }\n return skills;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../services/llmsContent.cjs"),n=require("./helpStorage.cjs");let r=require("node:crypto"),i=require("node:fs");i=e.__toESM(i,1);let a=require("node:path");a=e.__toESM(a,1);const o=`llms.txt`,s=`https://unpkg.com`,c=524288,l=/^sha256-([A-Za-z0-9+/]+={0,2})$/u;function u(e,t){return fetch(e,t)}function d(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function f(e){try{let t=i.default.lstatSync(e);return t.isFile()&&!t.isSymbolicLink()}catch{return!1}}function p(e,t){return`${e.split(`/`).map(e=>e.startsWith(`@`)?`@${encodeURIComponent(e.slice(1))}`:encodeURIComponent(e)).join(`/`)}@${encodeURIComponent(t)}`}function m(e,t){return`${s}/${p(e,t)}/`}function h(e){let t=e.headers.get(`content-length`);if(!t)return;let n=Number.parseInt(t,10);return Number.isFinite(n)&&n>=0?n:void 0}function g(e,t){let n=new AbortController,r=()=>n.abort(e.reason);e.addEventListener(`abort`,r,{once:!0});let i=setTimeout(()=>n.abort(Error(`Help download timed out.`)),t);return e.aborted&&r(),{signal:n.signal,dispose(){clearTimeout(i),e.removeEventListener(`abort`,r)}}}async function _(e,t,n){let r=t,i=new URL(t);for(let t=0;t<=3;t+=1){let t=await e(r,{signal:n,redirect:`manual`});if(t.status<300||t.status>=400)return t;let a=t.headers.get(`location`);if(!a)throw Error(`Unpkg redirected ${r} without a location.`);let o=new URL(a,r);if(o.origin!==s||o.pathname!==i.pathname||o.search!==i.search)throw Error(`Unpkg redirect escaped the exact package/version path: ${o.href}`);r=o.href}throw Error(`Unpkg exceeded 3 redirects.`)}function v(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Unpkg metadata is not valid JSON.`)}if(!d(t)||!Array.isArray(t.files))throw Error(`Unpkg metadata has no files list.`);let n=t.files.find(e=>d(e)&&e.path===`/${o}`);if(!d(n)||typeof n.integrity!=`string`)throw Error(`Unpkg package does not publish /${o}.`);let r=typeof n.size==`number`?n.size:void 0;if(r!==void 0&&(!Number.isSafeInteger(r)||r<0||r>1048576))throw Error(`Unpkg /${o} exceeds the Help size limit.`);if(!l.test(n.integrity))throw Error(`Unpkg llms.txt metadata does not contain SHA-256 SRI.`);return{path:n.path,...r===void 0?{}:{size:r},integrity:n.integrity}}function y(e,t){let n=l.exec(t)?.[1];if(!n)throw Error(`Invalid llms.txt SRI metadata.`);if((0,r.createHash)(`sha256`).update(e).digest(`base64`)!==n)throw Error(`Downloaded llms.txt failed SRI verification.`)}var b=class{cache;fetcher;timeoutMs;constructor(e={}){this.cache=e.cache??new n.HelpIndexCache,this.fetcher=e.fetch??u,this.timeoutMs=e.timeoutMs??5e3}async resolve(e,r){if(r.aborted)throw Error(`Help activation was cancelled.`);let s=n.resolveHelpPackageIdentity(e.moduleUrl,e.source),l=a.default.join(s.packageRoot,o);if(i.default.existsSync(l)){if(!f(l))throw Error(`Bundled ${o} must be a regular file.`);let e=i.default.readFileSync(l);return t.validateLlmsBytes(e),{identity:s,location:`local`,filePath:l,referenceBase:s.packageRoot,byteLength:e.byteLength,digest:n.sha256Hex(e)}}let u=this.cache.read(s);if(u)try{return t.validateLlmsBytes(u.bytes),{identity:s,location:`cache`,filePath:u.filePath,referenceBase:u.referenceBase,byteLength:u.bytes.byteLength,digest:u.digest}}catch{this.cache.discard(s)}let d=g(r,this.timeoutMs);try{let e=m(s.source,s.version),n=await _(this.fetcher,`${e}?meta`,d.signal),r=h(n);if(r!==void 0&&r>c)throw Error(`Unpkg metadata exceeds the Help metadata size limit.`);if(!n.ok)throw Error(`Unpkg metadata request failed with HTTP ${n.status}.`);let i=await n.text();if(Buffer.byteLength(i,`utf8`)>c)throw Error(`Unpkg metadata exceeds the Help metadata size limit.`);let a=v(i),l=await _(this.fetcher,`${e}${o}`,d.signal),u=h(l);if(u!==void 0&&u>1048576)throw Error(`Downloaded ${o} exceeds ${t.MAX_LLMS_BYTES} bytes.`);if(!l.ok)throw Error(`Unpkg llms.txt request failed with HTTP ${l.status}.`);let f=new Uint8Array(await l.arrayBuffer());t.validateLlmsBytes(f),y(f,a.integrity);let p=this.cache.publish(s,f,a.integrity,e,d.signal);return{identity:s,location:`remote`,filePath:p.filePath,referenceBase:p.referenceBase,byteLength:p.bytes.byteLength,digest:p.digest}}finally{d.dispose()}}};exports.DefaultHelpIndexResolver=b;
2
+ //# sourceMappingURL=llmsResolver.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llmsResolver.cjs","names":["fs","createHash","HelpIndexCache","resolveHelpPackageIdentity","path","sha256Hex","MAX_LLMS_BYTES"],"sources":["../../src/adapters/llmsResolver.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { DoomHelpContribution } from '@agimon-ai/doompi-extension-contracts/help';\nimport { MAX_LLMS_BYTES, validateLlmsBytes } from '../services/llmsContent.ts';\nimport type { HelpFetch, HelpFetchResponse, HelpIndexResolver, ResolvedHelpIndex } from '../types/help.ts';\nimport { HelpIndexCache, resolveHelpPackageIdentity, sha256Hex } from './helpStorage.ts';\n\nconst HELP_INDEX_PATH = 'llms.txt';\nconst UNPKG_ORIGIN = 'https://unpkg.com';\nconst DEFAULT_FETCH_TIMEOUT_MS = 5_000;\nconst MAX_METADATA_BYTES = 512 * 1024;\nconst MAX_REDIRECTS = 3;\nconst SRI_PATTERN = /^sha256-([A-Za-z0-9+/]+={0,2})$/u;\n\ninterface UnpkgMetadataFile {\n path: string;\n size?: number;\n integrity: string;\n}\n\nexport interface DefaultHelpIndexResolverOptions {\n cache?: HelpIndexCache;\n fetch?: HelpFetch;\n timeoutMs?: number;\n}\n\nfunction defaultFetch(input: string, init: { signal: AbortSignal; redirect: 'manual' }): Promise<HelpFetchResponse> {\n return fetch(input, init) as unknown as Promise<HelpFetchResponse>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isRegularFile(filePath: string): boolean {\n try {\n const metadata = fs.lstatSync(filePath);\n return metadata.isFile() && !metadata.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\nfunction unpkgPackagePath(source: string, version: string): string {\n const encoded = source\n .split('/')\n .map((segment) =>\n segment.startsWith('@') ? `@${encodeURIComponent(segment.slice(1))}` : encodeURIComponent(segment),\n )\n .join('/');\n return `${encoded}@${encodeURIComponent(version)}`;\n}\n\nfunction exactUnpkgBase(source: string, version: string): string {\n return `${UNPKG_ORIGIN}/${unpkgPackagePath(source, version)}/`;\n}\n\nfunction contentLength(response: HelpFetchResponse): number | undefined {\n const raw = response.headers.get('content-length');\n if (!raw) return undefined;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;\n}\n\nfunction timeoutSignal(parent: AbortSignal, timeoutMs: number): { signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n const abort = () => controller.abort(parent.reason);\n parent.addEventListener('abort', abort, { once: true });\n const timer = setTimeout(() => controller.abort(new Error('Help download timed out.')), timeoutMs);\n if (parent.aborted) abort();\n return {\n signal: controller.signal,\n dispose() {\n clearTimeout(timer);\n parent.removeEventListener('abort', abort);\n },\n };\n}\n\nasync function fetchExact(fetcher: HelpFetch, initialUrl: string, signal: AbortSignal): Promise<HelpFetchResponse> {\n let url = initialUrl;\n const expected = new URL(initialUrl);\n for (let redirect = 0; redirect <= MAX_REDIRECTS; redirect += 1) {\n const response = await fetcher(url, { signal, redirect: 'manual' });\n if (response.status < 300 || response.status >= 400) return response;\n const location = response.headers.get('location');\n if (!location) throw new Error(`Unpkg redirected ${url} without a location.`);\n const next = new URL(location, url);\n if (next.origin !== UNPKG_ORIGIN || next.pathname !== expected.pathname || next.search !== expected.search) {\n throw new Error(`Unpkg redirect escaped the exact package/version path: ${next.href}`);\n }\n url = next.href;\n }\n throw new Error(`Unpkg exceeded ${MAX_REDIRECTS} redirects.`);\n}\n\nfunction parseMetadata(text: string): UnpkgMetadataFile {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n throw new Error('Unpkg metadata is not valid JSON.');\n }\n if (!isRecord(parsed) || !Array.isArray(parsed.files)) throw new Error('Unpkg metadata has no files list.');\n const match = parsed.files.find((entry) => isRecord(entry) && entry.path === `/${HELP_INDEX_PATH}`);\n if (!isRecord(match) || typeof match.integrity !== 'string') {\n throw new Error(`Unpkg package does not publish /${HELP_INDEX_PATH}.`);\n }\n const size = typeof match.size === 'number' ? match.size : undefined;\n if (size !== undefined && (!Number.isSafeInteger(size) || size < 0 || size > MAX_LLMS_BYTES)) {\n throw new Error(`Unpkg /${HELP_INDEX_PATH} exceeds the Help size limit.`);\n }\n if (!SRI_PATTERN.test(match.integrity)) throw new Error('Unpkg llms.txt metadata does not contain SHA-256 SRI.');\n return { path: match.path as string, ...(size === undefined ? {} : { size }), integrity: match.integrity };\n}\n\nfunction verifySri(bytes: Uint8Array, integrity: string): void {\n const expected = SRI_PATTERN.exec(integrity)?.[1];\n if (!expected) throw new Error('Invalid llms.txt SRI metadata.');\n const actual = createHash('sha256').update(bytes).digest('base64');\n if (actual !== expected) throw new Error('Downloaded llms.txt failed SRI verification.');\n}\n\nexport class DefaultHelpIndexResolver implements HelpIndexResolver {\n private readonly cache: HelpIndexCache;\n private readonly fetcher: HelpFetch;\n private readonly timeoutMs: number;\n\n constructor(options: DefaultHelpIndexResolverOptions = {}) {\n this.cache = options.cache ?? new HelpIndexCache();\n this.fetcher = options.fetch ?? defaultFetch;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n }\n\n async resolve(contribution: DoomHelpContribution, signal: AbortSignal): Promise<ResolvedHelpIndex> {\n if (signal.aborted) throw new Error('Help activation was cancelled.');\n const identity = resolveHelpPackageIdentity(contribution.moduleUrl, contribution.source);\n const localPath = path.join(identity.packageRoot, HELP_INDEX_PATH);\n if (fs.existsSync(localPath)) {\n if (!isRegularFile(localPath)) throw new Error(`Bundled ${HELP_INDEX_PATH} must be a regular file.`);\n const bytes = fs.readFileSync(localPath);\n validateLlmsBytes(bytes);\n return {\n identity,\n location: 'local',\n filePath: localPath,\n referenceBase: identity.packageRoot,\n byteLength: bytes.byteLength,\n digest: sha256Hex(bytes),\n };\n }\n\n const cached = this.cache.read(identity);\n if (cached) {\n try {\n validateLlmsBytes(cached.bytes);\n return {\n identity,\n location: 'cache',\n filePath: cached.filePath,\n referenceBase: cached.referenceBase,\n byteLength: cached.bytes.byteLength,\n digest: cached.digest,\n };\n } catch {\n this.cache.discard(identity);\n }\n }\n\n const timed = timeoutSignal(signal, this.timeoutMs);\n try {\n const referenceBase = exactUnpkgBase(identity.source, identity.version);\n const metadataResponse = await fetchExact(this.fetcher, `${referenceBase}?meta`, timed.signal);\n const metadataLength = contentLength(metadataResponse);\n if (metadataLength !== undefined && metadataLength > MAX_METADATA_BYTES) {\n throw new Error('Unpkg metadata exceeds the Help metadata size limit.');\n }\n if (!metadataResponse.ok) throw new Error(`Unpkg metadata request failed with HTTP ${metadataResponse.status}.`);\n const metadataText = await metadataResponse.text();\n if (Buffer.byteLength(metadataText, 'utf8') > MAX_METADATA_BYTES) {\n throw new Error('Unpkg metadata exceeds the Help metadata size limit.');\n }\n const metadata = parseMetadata(metadataText);\n const indexResponse = await fetchExact(this.fetcher, `${referenceBase}${HELP_INDEX_PATH}`, timed.signal);\n const indexLength = contentLength(indexResponse);\n if (indexLength !== undefined && indexLength > MAX_LLMS_BYTES) {\n throw new Error(`Downloaded ${HELP_INDEX_PATH} exceeds ${MAX_LLMS_BYTES} bytes.`);\n }\n if (!indexResponse.ok) throw new Error(`Unpkg llms.txt request failed with HTTP ${indexResponse.status}.`);\n const bytes = new Uint8Array(await indexResponse.arrayBuffer());\n validateLlmsBytes(bytes);\n verifySri(bytes, metadata.integrity);\n const published = this.cache.publish(identity, bytes, metadata.integrity, referenceBase, timed.signal);\n return {\n identity,\n location: 'remote',\n filePath: published.filePath,\n referenceBase: published.referenceBase,\n byteLength: published.bytes.byteLength,\n digest: published.digest,\n };\n } finally {\n timed.dispose();\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{MAX_LLMS_BYTES as e,validateLlmsBytes as t}from"../services/llmsContent.mjs";import{HelpIndexCache as n,resolveHelpPackageIdentity as r,sha256Hex as i}from"./helpStorage.mjs";import{createHash as a}from"node:crypto";import o from"node:fs";import s from"node:path";const c=`llms.txt`,l=`https://unpkg.com`,u=524288,d=/^sha256-([A-Za-z0-9+/]+={0,2})$/u;function f(e,t){return fetch(e,t)}function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e){try{let t=o.lstatSync(e);return t.isFile()&&!t.isSymbolicLink()}catch{return!1}}function h(e,t){return`${e.split(`/`).map(e=>e.startsWith(`@`)?`@${encodeURIComponent(e.slice(1))}`:encodeURIComponent(e)).join(`/`)}@${encodeURIComponent(t)}`}function g(e,t){return`${l}/${h(e,t)}/`}function _(e){let t=e.headers.get(`content-length`);if(!t)return;let n=Number.parseInt(t,10);return Number.isFinite(n)&&n>=0?n:void 0}function v(e,t){let n=new AbortController,r=()=>n.abort(e.reason);e.addEventListener(`abort`,r,{once:!0});let i=setTimeout(()=>n.abort(Error(`Help download timed out.`)),t);return e.aborted&&r(),{signal:n.signal,dispose(){clearTimeout(i),e.removeEventListener(`abort`,r)}}}async function y(e,t,n){let r=t,i=new URL(t);for(let t=0;t<=3;t+=1){let t=await e(r,{signal:n,redirect:`manual`});if(t.status<300||t.status>=400)return t;let a=t.headers.get(`location`);if(!a)throw Error(`Unpkg redirected ${r} without a location.`);let o=new URL(a,r);if(o.origin!==l||o.pathname!==i.pathname||o.search!==i.search)throw Error(`Unpkg redirect escaped the exact package/version path: ${o.href}`);r=o.href}throw Error(`Unpkg exceeded 3 redirects.`)}function b(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Unpkg metadata is not valid JSON.`)}if(!p(t)||!Array.isArray(t.files))throw Error(`Unpkg metadata has no files list.`);let n=t.files.find(e=>p(e)&&e.path===`/${c}`);if(!p(n)||typeof n.integrity!=`string`)throw Error(`Unpkg package does not publish /${c}.`);let r=typeof n.size==`number`?n.size:void 0;if(r!==void 0&&(!Number.isSafeInteger(r)||r<0||r>1048576))throw Error(`Unpkg /${c} exceeds the Help size limit.`);if(!d.test(n.integrity))throw Error(`Unpkg llms.txt metadata does not contain SHA-256 SRI.`);return{path:n.path,...r===void 0?{}:{size:r},integrity:n.integrity}}function x(e,t){let n=d.exec(t)?.[1];if(!n)throw Error(`Invalid llms.txt SRI metadata.`);if(a(`sha256`).update(e).digest(`base64`)!==n)throw Error(`Downloaded llms.txt failed SRI verification.`)}var S=class{cache;fetcher;timeoutMs;constructor(e={}){this.cache=e.cache??new n,this.fetcher=e.fetch??f,this.timeoutMs=e.timeoutMs??5e3}async resolve(n,a){if(a.aborted)throw Error(`Help activation was cancelled.`);let l=r(n.moduleUrl,n.source),d=s.join(l.packageRoot,c);if(o.existsSync(d)){if(!m(d))throw Error(`Bundled ${c} must be a regular file.`);let e=o.readFileSync(d);return t(e),{identity:l,location:`local`,filePath:d,referenceBase:l.packageRoot,byteLength:e.byteLength,digest:i(e)}}let f=this.cache.read(l);if(f)try{return t(f.bytes),{identity:l,location:`cache`,filePath:f.filePath,referenceBase:f.referenceBase,byteLength:f.bytes.byteLength,digest:f.digest}}catch{this.cache.discard(l)}let p=v(a,this.timeoutMs);try{let n=g(l.source,l.version),r=await y(this.fetcher,`${n}?meta`,p.signal),i=_(r);if(i!==void 0&&i>u)throw Error(`Unpkg metadata exceeds the Help metadata size limit.`);if(!r.ok)throw Error(`Unpkg metadata request failed with HTTP ${r.status}.`);let a=await r.text();if(Buffer.byteLength(a,`utf8`)>u)throw Error(`Unpkg metadata exceeds the Help metadata size limit.`);let o=b(a),s=await y(this.fetcher,`${n}${c}`,p.signal),d=_(s);if(d!==void 0&&d>1048576)throw Error(`Downloaded ${c} exceeds ${e} bytes.`);if(!s.ok)throw Error(`Unpkg llms.txt request failed with HTTP ${s.status}.`);let f=new Uint8Array(await s.arrayBuffer());t(f),x(f,o.integrity);let m=this.cache.publish(l,f,o.integrity,n,p.signal);return{identity:l,location:`remote`,filePath:m.filePath,referenceBase:m.referenceBase,byteLength:m.bytes.byteLength,digest:m.digest}}finally{p.dispose()}}};export{S as DefaultHelpIndexResolver};
2
+ //# sourceMappingURL=llmsResolver.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llmsResolver.mjs","names":[],"sources":["../../src/adapters/llmsResolver.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { DoomHelpContribution } from '@agimon-ai/doompi-extension-contracts/help';\nimport { MAX_LLMS_BYTES, validateLlmsBytes } from '../services/llmsContent.ts';\nimport type { HelpFetch, HelpFetchResponse, HelpIndexResolver, ResolvedHelpIndex } from '../types/help.ts';\nimport { HelpIndexCache, resolveHelpPackageIdentity, sha256Hex } from './helpStorage.ts';\n\nconst HELP_INDEX_PATH = 'llms.txt';\nconst UNPKG_ORIGIN = 'https://unpkg.com';\nconst DEFAULT_FETCH_TIMEOUT_MS = 5_000;\nconst MAX_METADATA_BYTES = 512 * 1024;\nconst MAX_REDIRECTS = 3;\nconst SRI_PATTERN = /^sha256-([A-Za-z0-9+/]+={0,2})$/u;\n\ninterface UnpkgMetadataFile {\n path: string;\n size?: number;\n integrity: string;\n}\n\nexport interface DefaultHelpIndexResolverOptions {\n cache?: HelpIndexCache;\n fetch?: HelpFetch;\n timeoutMs?: number;\n}\n\nfunction defaultFetch(input: string, init: { signal: AbortSignal; redirect: 'manual' }): Promise<HelpFetchResponse> {\n return fetch(input, init) as unknown as Promise<HelpFetchResponse>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isRegularFile(filePath: string): boolean {\n try {\n const metadata = fs.lstatSync(filePath);\n return metadata.isFile() && !metadata.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\nfunction unpkgPackagePath(source: string, version: string): string {\n const encoded = source\n .split('/')\n .map((segment) =>\n segment.startsWith('@') ? `@${encodeURIComponent(segment.slice(1))}` : encodeURIComponent(segment),\n )\n .join('/');\n return `${encoded}@${encodeURIComponent(version)}`;\n}\n\nfunction exactUnpkgBase(source: string, version: string): string {\n return `${UNPKG_ORIGIN}/${unpkgPackagePath(source, version)}/`;\n}\n\nfunction contentLength(response: HelpFetchResponse): number | undefined {\n const raw = response.headers.get('content-length');\n if (!raw) return undefined;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;\n}\n\nfunction timeoutSignal(parent: AbortSignal, timeoutMs: number): { signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n const abort = () => controller.abort(parent.reason);\n parent.addEventListener('abort', abort, { once: true });\n const timer = setTimeout(() => controller.abort(new Error('Help download timed out.')), timeoutMs);\n if (parent.aborted) abort();\n return {\n signal: controller.signal,\n dispose() {\n clearTimeout(timer);\n parent.removeEventListener('abort', abort);\n },\n };\n}\n\nasync function fetchExact(fetcher: HelpFetch, initialUrl: string, signal: AbortSignal): Promise<HelpFetchResponse> {\n let url = initialUrl;\n const expected = new URL(initialUrl);\n for (let redirect = 0; redirect <= MAX_REDIRECTS; redirect += 1) {\n const response = await fetcher(url, { signal, redirect: 'manual' });\n if (response.status < 300 || response.status >= 400) return response;\n const location = response.headers.get('location');\n if (!location) throw new Error(`Unpkg redirected ${url} without a location.`);\n const next = new URL(location, url);\n if (next.origin !== UNPKG_ORIGIN || next.pathname !== expected.pathname || next.search !== expected.search) {\n throw new Error(`Unpkg redirect escaped the exact package/version path: ${next.href}`);\n }\n url = next.href;\n }\n throw new Error(`Unpkg exceeded ${MAX_REDIRECTS} redirects.`);\n}\n\nfunction parseMetadata(text: string): UnpkgMetadataFile {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n throw new Error('Unpkg metadata is not valid JSON.');\n }\n if (!isRecord(parsed) || !Array.isArray(parsed.files)) throw new Error('Unpkg metadata has no files list.');\n const match = parsed.files.find((entry) => isRecord(entry) && entry.path === `/${HELP_INDEX_PATH}`);\n if (!isRecord(match) || typeof match.integrity !== 'string') {\n throw new Error(`Unpkg package does not publish /${HELP_INDEX_PATH}.`);\n }\n const size = typeof match.size === 'number' ? match.size : undefined;\n if (size !== undefined && (!Number.isSafeInteger(size) || size < 0 || size > MAX_LLMS_BYTES)) {\n throw new Error(`Unpkg /${HELP_INDEX_PATH} exceeds the Help size limit.`);\n }\n if (!SRI_PATTERN.test(match.integrity)) throw new Error('Unpkg llms.txt metadata does not contain SHA-256 SRI.');\n return { path: match.path as string, ...(size === undefined ? {} : { size }), integrity: match.integrity };\n}\n\nfunction verifySri(bytes: Uint8Array, integrity: string): void {\n const expected = SRI_PATTERN.exec(integrity)?.[1];\n if (!expected) throw new Error('Invalid llms.txt SRI metadata.');\n const actual = createHash('sha256').update(bytes).digest('base64');\n if (actual !== expected) throw new Error('Downloaded llms.txt failed SRI verification.');\n}\n\nexport class DefaultHelpIndexResolver implements HelpIndexResolver {\n private readonly cache: HelpIndexCache;\n private readonly fetcher: HelpFetch;\n private readonly timeoutMs: number;\n\n constructor(options: DefaultHelpIndexResolverOptions = {}) {\n this.cache = options.cache ?? new HelpIndexCache();\n this.fetcher = options.fetch ?? defaultFetch;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n }\n\n async resolve(contribution: DoomHelpContribution, signal: AbortSignal): Promise<ResolvedHelpIndex> {\n if (signal.aborted) throw new Error('Help activation was cancelled.');\n const identity = resolveHelpPackageIdentity(contribution.moduleUrl, contribution.source);\n const localPath = path.join(identity.packageRoot, HELP_INDEX_PATH);\n if (fs.existsSync(localPath)) {\n if (!isRegularFile(localPath)) throw new Error(`Bundled ${HELP_INDEX_PATH} must be a regular file.`);\n const bytes = fs.readFileSync(localPath);\n validateLlmsBytes(bytes);\n return {\n identity,\n location: 'local',\n filePath: localPath,\n referenceBase: identity.packageRoot,\n byteLength: bytes.byteLength,\n digest: sha256Hex(bytes),\n };\n }\n\n const cached = this.cache.read(identity);\n if (cached) {\n try {\n validateLlmsBytes(cached.bytes);\n return {\n identity,\n location: 'cache',\n filePath: cached.filePath,\n referenceBase: cached.referenceBase,\n byteLength: cached.bytes.byteLength,\n digest: cached.digest,\n };\n } catch {\n this.cache.discard(identity);\n }\n }\n\n const timed = timeoutSignal(signal, this.timeoutMs);\n try {\n const referenceBase = exactUnpkgBase(identity.source, identity.version);\n const metadataResponse = await fetchExact(this.fetcher, `${referenceBase}?meta`, timed.signal);\n const metadataLength = contentLength(metadataResponse);\n if (metadataLength !== undefined && metadataLength > MAX_METADATA_BYTES) {\n throw new Error('Unpkg metadata exceeds the Help metadata size limit.');\n }\n if (!metadataResponse.ok) throw new Error(`Unpkg metadata request failed with HTTP ${metadataResponse.status}.`);\n const metadataText = await metadataResponse.text();\n if (Buffer.byteLength(metadataText, 'utf8') > MAX_METADATA_BYTES) {\n throw new Error('Unpkg metadata exceeds the Help metadata size limit.');\n }\n const metadata = parseMetadata(metadataText);\n const indexResponse = await fetchExact(this.fetcher, `${referenceBase}${HELP_INDEX_PATH}`, timed.signal);\n const indexLength = contentLength(indexResponse);\n if (indexLength !== undefined && indexLength > MAX_LLMS_BYTES) {\n throw new Error(`Downloaded ${HELP_INDEX_PATH} exceeds ${MAX_LLMS_BYTES} bytes.`);\n }\n if (!indexResponse.ok) throw new Error(`Unpkg llms.txt request failed with HTTP ${indexResponse.status}.`);\n const bytes = new Uint8Array(await indexResponse.arrayBuffer());\n validateLlmsBytes(bytes);\n verifySri(bytes, metadata.integrity);\n const published = this.cache.publish(identity, bytes, metadata.integrity, referenceBase, timed.signal);\n return {\n identity,\n location: 'remote',\n filePath: published.filePath,\n referenceBase: published.referenceBase,\n byteLength: published.bytes.byteLength,\n digest: published.digest,\n };\n } finally {\n timed.dispose();\n }\n }\n}\n"],"mappings":"+QAQA,MAAM,EAAkB,WAClB,EAAe,oBAEf,EAAqB,OAErB,EAAc,mCAcpB,SAAS,EAAa,EAAe,EAA+E,CAClH,OAAO,MAAM,EAAO,CAAI,CAC1B,CAEA,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAEA,SAAS,EAAc,EAA2B,CAChD,GAAI,CACF,IAAM,EAAW,EAAG,UAAU,CAAQ,EACtC,OAAO,EAAS,OAAO,GAAK,CAAC,EAAS,eAAe,CACvD,MAAQ,CACN,MAAO,EACT,CACF,CAEA,SAAS,EAAiB,EAAgB,EAAyB,CAOjE,MAAO,GANS,EACb,MAAM,GAAG,CAAC,CACV,IAAK,GACJ,EAAQ,WAAW,GAAG,EAAI,IAAI,mBAAmB,EAAQ,MAAM,CAAC,CAAC,IAAM,mBAAmB,CAAO,CACnG,CAAC,CACA,KAAK,GACQ,EAAE,GAAG,mBAAmB,CAAO,GACjD,CAEA,SAAS,EAAe,EAAgB,EAAyB,CAC/D,MAAO,GAAG,EAAa,GAAG,EAAiB,EAAQ,CAAO,EAAE,EAC9D,CAEA,SAAS,EAAc,EAAiD,CACtE,IAAM,EAAM,EAAS,QAAQ,IAAI,gBAAgB,EACjD,GAAI,CAAC,EAAK,OACV,IAAM,EAAS,OAAO,SAAS,EAAK,EAAE,EACtC,OAAO,OAAO,SAAS,CAAM,GAAK,GAAU,EAAI,EAAS,IAAA,EAC3D,CAEA,SAAS,EAAc,EAAqB,EAA6D,CACvG,IAAM,EAAa,IAAI,gBACjB,MAAc,EAAW,MAAM,EAAO,MAAM,EAClD,EAAO,iBAAiB,QAAS,EAAO,CAAE,KAAM,EAAK,CAAC,EACtD,IAAM,EAAQ,eAAiB,EAAW,MAAU,MAAM,0BAA0B,CAAC,EAAG,CAAS,EAEjG,OADI,EAAO,SAAS,EAAM,EACnB,CACL,OAAQ,EAAW,OACnB,SAAU,CACR,aAAa,CAAK,EAClB,EAAO,oBAAoB,QAAS,CAAK,CAC3C,CACF,CACF,CAEA,eAAe,EAAW,EAAoB,EAAoB,EAAiD,CACjH,IAAI,EAAM,EACJ,EAAW,IAAI,IAAI,CAAU,EACnC,IAAK,IAAI,EAAW,EAAG,GAAY,EAAe,GAAY,EAAG,CAC/D,IAAM,EAAW,MAAM,EAAQ,EAAK,CAAE,SAAQ,SAAU,QAAS,CAAC,EAClE,GAAI,EAAS,OAAS,KAAO,EAAS,QAAU,IAAK,OAAO,EAC5D,IAAM,EAAW,EAAS,QAAQ,IAAI,UAAU,EAChD,GAAI,CAAC,EAAU,MAAU,MAAM,oBAAoB,EAAI,qBAAqB,EAC5E,IAAM,EAAO,IAAI,IAAI,EAAU,CAAG,EAClC,GAAI,EAAK,SAAW,GAAgB,EAAK,WAAa,EAAS,UAAY,EAAK,SAAW,EAAS,OAClG,MAAU,MAAM,0DAA0D,EAAK,MAAM,EAEvF,EAAM,EAAK,IACb,CACA,MAAU,MAAM,6BAA4C,CAC9D,CAEA,SAAS,EAAc,EAAiC,CACtD,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,CAAI,CAC1B,MAAQ,CACN,MAAU,MAAM,mCAAmC,CACrD,CACA,GAAI,CAAC,EAAS,CAAM,GAAK,CAAC,MAAM,QAAQ,EAAO,KAAK,EAAG,MAAU,MAAM,mCAAmC,EAC1G,IAAM,EAAQ,EAAO,MAAM,KAAM,GAAU,EAAS,CAAK,GAAK,EAAM,OAAS,IAAI,GAAiB,EAClG,GAAI,CAAC,EAAS,CAAK,GAAK,OAAO,EAAM,WAAc,SACjD,MAAU,MAAM,mCAAmC,EAAgB,EAAE,EAEvE,IAAM,EAAO,OAAO,EAAM,MAAS,SAAW,EAAM,KAAO,IAAA,GAC3D,GAAI,IAAS,IAAA,KAAc,CAAC,OAAO,cAAc,CAAI,GAAK,EAAO,GAAK,EAAA,SACpE,MAAU,MAAM,UAAU,EAAgB,8BAA8B,EAE1E,GAAI,CAAC,EAAY,KAAK,EAAM,SAAS,EAAG,MAAU,MAAM,uDAAuD,EAC/G,MAAO,CAAE,KAAM,EAAM,KAAgB,GAAI,IAAS,IAAA,GAAY,CAAC,EAAI,CAAE,MAAK,EAAI,UAAW,EAAM,SAAU,CAC3G,CAEA,SAAS,EAAU,EAAmB,EAAyB,CAC7D,IAAM,EAAW,EAAY,KAAK,CAAS,CAAC,GAAG,GAC/C,GAAI,CAAC,EAAU,MAAU,MAAM,gCAAgC,EAE/D,GADe,EAAW,QAAQ,CAAC,CAAC,OAAO,CAAK,CAAC,CAAC,OAAO,QAChD,IAAM,EAAU,MAAU,MAAM,8CAA8C,CACzF,CAEA,IAAa,EAAb,KAAmE,CACjE,MACA,QACA,UAEA,YAAY,EAA2C,CAAC,EAAG,CACzD,KAAK,MAAQ,EAAQ,OAAS,IAAI,EAClC,KAAK,QAAU,EAAQ,OAAS,EAChC,KAAK,UAAY,EAAQ,WAAa,GACxC,CAEA,MAAM,QAAQ,EAAoC,EAAiD,CACjG,GAAI,EAAO,QAAS,MAAU,MAAM,gCAAgC,EACpE,IAAM,EAAW,EAA2B,EAAa,UAAW,EAAa,MAAM,EACjF,EAAY,EAAK,KAAK,EAAS,YAAa,CAAe,EACjE,GAAI,EAAG,WAAW,CAAS,EAAG,CAC5B,GAAI,CAAC,EAAc,CAAS,EAAG,MAAU,MAAM,WAAW,EAAgB,yBAAyB,EACnG,IAAM,EAAQ,EAAG,aAAa,CAAS,EAEvC,OADA,EAAkB,CAAK,EAChB,CACL,WACA,SAAU,QACV,SAAU,EACV,cAAe,EAAS,YACxB,WAAY,EAAM,WAClB,OAAQ,EAAU,CAAK,CACzB,CACF,CAEA,IAAM,EAAS,KAAK,MAAM,KAAK,CAAQ,EACvC,GAAI,EACF,GAAI,CAEF,OADA,EAAkB,EAAO,KAAK,EACvB,CACL,WACA,SAAU,QACV,SAAU,EAAO,SACjB,cAAe,EAAO,cACtB,WAAY,EAAO,MAAM,WACzB,OAAQ,EAAO,MACjB,CACF,MAAQ,CACN,KAAK,MAAM,QAAQ,CAAQ,CAC7B,CAGF,IAAM,EAAQ,EAAc,EAAQ,KAAK,SAAS,EAClD,GAAI,CACF,IAAM,EAAgB,EAAe,EAAS,OAAQ,EAAS,OAAO,EAChE,EAAmB,MAAM,EAAW,KAAK,QAAS,GAAG,EAAc,OAAQ,EAAM,MAAM,EACvF,EAAiB,EAAc,CAAgB,EACrD,GAAI,IAAmB,IAAA,IAAa,EAAiB,EACnD,MAAU,MAAM,sDAAsD,EAExE,GAAI,CAAC,EAAiB,GAAI,MAAU,MAAM,2CAA2C,EAAiB,OAAO,EAAE,EAC/G,IAAM,EAAe,MAAM,EAAiB,KAAK,EACjD,GAAI,OAAO,WAAW,EAAc,MAAM,EAAI,EAC5C,MAAU,MAAM,sDAAsD,EAExE,IAAM,EAAW,EAAc,CAAY,EACrC,EAAgB,MAAM,EAAW,KAAK,QAAS,GAAG,IAAgB,IAAmB,EAAM,MAAM,EACjG,EAAc,EAAc,CAAa,EAC/C,GAAI,IAAgB,IAAA,IAAa,EAAA,QAC/B,MAAU,MAAM,cAAc,EAAgB,WAAW,EAAe,QAAQ,EAElF,GAAI,CAAC,EAAc,GAAI,MAAU,MAAM,2CAA2C,EAAc,OAAO,EAAE,EACzG,IAAM,EAAQ,IAAI,WAAW,MAAM,EAAc,YAAY,CAAC,EAC9D,EAAkB,CAAK,EACvB,EAAU,EAAO,EAAS,SAAS,EACnC,IAAM,EAAY,KAAK,MAAM,QAAQ,EAAU,EAAO,EAAS,UAAW,EAAe,EAAM,MAAM,EACrG,MAAO,CACL,WACA,SAAU,SACV,SAAU,EAAU,SACpB,cAAe,EAAU,cACzB,WAAY,EAAU,MAAM,WAC5B,OAAQ,EAAU,MACpB,CACF,QAAU,CACR,EAAM,QAAQ,CAChB,CACF,CACF"}
@@ -0,0 +1,2 @@
1
+ let e=require("@agimon-ai/doompi-extension-contracts/leader"),t=require("@agimon-ai/doompi-extension-contracts/mode");const n=`@agimon-ai/doompi-help`,r=`help`,i=`help.toggle`,a={key:`h`,label:`help`,order:70},o=`activate`,s=`deactivate`;function c(e){return e.slice(0,160)}function l(e){if(e.activation===`activating`)return{activation:`activating`,condition:`queued`,detail:`loading package Help`,actions:[{id:o,enabled:!1,disabledReason:`Help activation is already running.`},{id:s,enabled:!0}]};if(e.activation===`active`||e.activation===`degraded`){let t=e.activation===`degraded`;return{activation:`active`,condition:t?`degraded`:`ready`,detail:c(`${e.skills.length} package Help skill${e.skills.length===1?``:`s`}`),...t?{color:`warning`}:{color:`accent`},actions:[{id:o,enabled:!1,disabledReason:`Help is already active.`},{id:s,enabled:!0}]}}let t=e.diagnostics[0]?.message;return{activation:`inactive`,condition:t?`failed`:`ready`,...t?{detail:c(t),color:`warning`}:{},actions:[{id:o,enabled:!0},{id:s,enabled:!1,disabledReason:`Help is not active.`}]}}function u(e){let t=e.activation!==`inactive`;return[{id:`help.toggle`,path:[a,t?{key:`e`,label:`exit`,detail:`hide package Help`}:{key:`e`,label:`enter`,detail:`load package Help`}],action:{name:i}}]}function d(e){queueMicrotask(()=>{throw e instanceof Error?e:Error(String(e))})}function f(a,f){let p=a,m=(0,t.registerMinorModeOwner)(p,{descriptor:{source:n,id:r,label:`Help`,description:`Activation-gated package guidance from exact installed package versions.`,order:50,actions:[{id:o,label:`Activate`,description:`Load package-owned Help indexes and expose their generated skills.`,contexts:[`tui`,`headless`],parameters:[]},{id:s,label:`Deactivate`,description:`Remove all active package Help skills immediately.`,contexts:[`tui`,`headless`],parameters:[]}]},initialState:l(f.getState()),async handleAction(e,t,n){if(e===o){let e=await f.activate(n.signal);return{message:c(`Activated ${e.skills.length} package Help skill${e.skills.length===1?``:`s`}${e.activation===`degraded`?` with diagnostics.`:`.`}`)}}if(e===s)return f.deactivate(),{message:`Package Help deactivated.`};throw Error(`Unknown Help mode action: ${e}`)},onError:d}),h=(0,e.createDoomLeaderContribution)(p,{source:n,bindings:u(f.getState())}),g=(0,e.registerDoomLeaderActionHandlers)(p,{source:n,handlers:{[i]:async e=>{f.getState().activation===`inactive`?await f.activate():f.deactivate(),e.hasUI&&e.ui.notify(f.getState().activation===`inactive`?`Package Help deactivated.`:`Package Help activated.`,`info`)}},onError:(e,t,n)=>{n.hasUI?n.ui.notify(e instanceof Error?e.message:String(e),`error`):d(e)}}),_=f.subscribe(e=>{m.publish(l(e)),h.update(u(e))}),v=!1;return{mode:m,dispose(){v||(v=!0,_(),g(),h.dispose(),m.dispose())}}}exports.HELP_LEADER_ACTION=i,exports.HELP_MODE_ID=r,exports.HELP_PACKAGE_SOURCE=n,exports.helpMinorModeState=l,exports.registerHelpModeIntegration=f;
2
+ //# sourceMappingURL=helpMode.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpMode.cjs","names":["registerMinorModeOwner","createDoomLeaderContribution","registerDoomLeaderActionHandlers"],"sources":["../../../src/adapters/pi/helpMode.ts"],"sourcesContent":["import type { DoomExtensionContext, DoomExtensionHost } from '@agimon-ai/doompi-extension-contracts/config';\nimport {\n createDoomLeaderContribution,\n type LeaderBinding,\n registerDoomLeaderActionHandlers,\n} from '@agimon-ai/doompi-extension-contracts/leader';\nimport {\n type MinorModeOwnerHandle,\n type MinorModeState,\n registerMinorModeOwner,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { HelpActivationService, HelpRuntimeState } from '../../types/help.ts';\n\nexport const HELP_PACKAGE_SOURCE = '@agimon-ai/doompi-help';\nexport const HELP_MODE_ID = 'help';\nexport const HELP_MODE_ORDER = 50;\nexport const HELP_LEADER_ACTION = 'help.toggle';\n\nconst HELP_GROUP = { key: 'h', label: 'help', order: 70 } as const;\nconst MODE_ACTION_ACTIVATE = 'activate';\nconst MODE_ACTION_DEACTIVATE = 'deactivate';\nconst MAX_MODE_DETAIL_LENGTH = 160;\n\ntype HelpModeContext = ExtensionContext & DoomExtensionContext;\ntype HelpModeHost = DoomExtensionHost<HelpModeContext>;\n\nfunction boundedDetail(value: string): string {\n return value.slice(0, MAX_MODE_DETAIL_LENGTH);\n}\n\nexport function helpMinorModeState(state: HelpRuntimeState): MinorModeState {\n if (state.activation === 'activating') {\n return {\n activation: 'activating',\n condition: 'queued',\n detail: 'loading package Help',\n actions: [\n { id: MODE_ACTION_ACTIVATE, enabled: false, disabledReason: 'Help activation is already running.' },\n { id: MODE_ACTION_DEACTIVATE, enabled: true },\n ],\n };\n }\n if (state.activation === 'active' || state.activation === 'degraded') {\n const degraded = state.activation === 'degraded';\n return {\n activation: 'active',\n condition: degraded ? 'degraded' : 'ready',\n detail: boundedDetail(`${state.skills.length} package Help skill${state.skills.length === 1 ? '' : 's'}`),\n ...(degraded ? { color: 'warning' as const } : { color: 'accent' as const }),\n actions: [\n { id: MODE_ACTION_ACTIVATE, enabled: false, disabledReason: 'Help is already active.' },\n { id: MODE_ACTION_DEACTIVATE, enabled: true },\n ],\n };\n }\n const failure = state.diagnostics[0]?.message;\n return {\n activation: 'inactive',\n condition: failure ? 'failed' : 'ready',\n ...(failure ? { detail: boundedDetail(failure), color: 'warning' as const } : {}),\n actions: [\n { id: MODE_ACTION_ACTIVATE, enabled: true },\n { id: MODE_ACTION_DEACTIVATE, enabled: false, disabledReason: 'Help is not active.' },\n ],\n };\n}\n\nfunction leaderBindings(state: HelpRuntimeState): LeaderBinding[] {\n const active = state.activation !== 'inactive';\n return [\n {\n id: 'help.toggle',\n path: [\n HELP_GROUP,\n active\n ? { key: 'e', label: 'exit', detail: 'hide package Help' }\n : { key: 'e', label: 'enter', detail: 'load package Help' },\n ],\n action: { name: HELP_LEADER_ACTION },\n },\n ];\n}\n\nfunction reportAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error instanceof Error ? error : new Error(String(error));\n });\n}\n\nexport interface HelpModeIntegration {\n mode: MinorModeOwnerHandle;\n dispose(): void;\n}\n\nexport function registerHelpModeIntegration(pi: ExtensionAPI, activation: HelpActivationService): HelpModeIntegration {\n const host = pi as unknown as HelpModeHost;\n const mode = registerMinorModeOwner(host, {\n descriptor: {\n source: HELP_PACKAGE_SOURCE,\n id: HELP_MODE_ID,\n label: 'Help',\n description: 'Activation-gated package guidance from exact installed package versions.',\n order: HELP_MODE_ORDER,\n actions: [\n {\n id: MODE_ACTION_ACTIVATE,\n label: 'Activate',\n description: 'Load package-owned Help indexes and expose their generated skills.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n {\n id: MODE_ACTION_DEACTIVATE,\n label: 'Deactivate',\n description: 'Remove all active package Help skills immediately.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n ],\n },\n initialState: helpMinorModeState(activation.getState()),\n async handleAction(actionId, _arguments, execution) {\n if (actionId === MODE_ACTION_ACTIVATE) {\n const state = await activation.activate(execution.signal);\n return {\n message: boundedDetail(\n `Activated ${state.skills.length} package Help skill${state.skills.length === 1 ? '' : 's'}${state.activation === 'degraded' ? ' with diagnostics.' : '.'}`,\n ),\n };\n }\n if (actionId === MODE_ACTION_DEACTIVATE) {\n activation.deactivate();\n return { message: 'Package Help deactivated.' };\n }\n throw new Error(`Unknown Help mode action: ${actionId}`);\n },\n onError: reportAsync,\n });\n const leader = createDoomLeaderContribution(host, {\n source: HELP_PACKAGE_SOURCE,\n bindings: leaderBindings(activation.getState()),\n });\n const actionDisposer = registerDoomLeaderActionHandlers(host, {\n source: HELP_PACKAGE_SOURCE,\n handlers: {\n [HELP_LEADER_ACTION]: async (context) => {\n const state = activation.getState();\n if (state.activation === 'inactive') await activation.activate();\n else activation.deactivate();\n if (context.hasUI) {\n context.ui.notify(\n activation.getState().activation === 'inactive' ? 'Package Help deactivated.' : 'Package Help activated.',\n 'info',\n );\n }\n },\n },\n onError: (error, _action, context) => {\n if (context.hasUI) context.ui.notify(error instanceof Error ? error.message : String(error), 'error');\n else reportAsync(error);\n },\n });\n const stateDisposer = activation.subscribe((state) => {\n mode.publish(helpMinorModeState(state));\n leader.update(leaderBindings(state));\n });\n let disposed = false;\n return {\n mode,\n dispose() {\n if (disposed) return;\n disposed = true;\n stateDisposer();\n actionDisposer();\n leader.dispose();\n mode.dispose();\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{createDoomLeaderContribution as e,registerDoomLeaderActionHandlers as t}from"@agimon-ai/doompi-extension-contracts/leader";import{registerMinorModeOwner as n}from"@agimon-ai/doompi-extension-contracts/mode";const r=`@agimon-ai/doompi-help`,i=`help`,a=`help.toggle`,o={key:`h`,label:`help`,order:70},s=`activate`,c=`deactivate`;function l(e){return e.slice(0,160)}function u(e){if(e.activation===`activating`)return{activation:`activating`,condition:`queued`,detail:`loading package Help`,actions:[{id:s,enabled:!1,disabledReason:`Help activation is already running.`},{id:c,enabled:!0}]};if(e.activation===`active`||e.activation===`degraded`){let t=e.activation===`degraded`;return{activation:`active`,condition:t?`degraded`:`ready`,detail:l(`${e.skills.length} package Help skill${e.skills.length===1?``:`s`}`),...t?{color:`warning`}:{color:`accent`},actions:[{id:s,enabled:!1,disabledReason:`Help is already active.`},{id:c,enabled:!0}]}}let t=e.diagnostics[0]?.message;return{activation:`inactive`,condition:t?`failed`:`ready`,...t?{detail:l(t),color:`warning`}:{},actions:[{id:s,enabled:!0},{id:c,enabled:!1,disabledReason:`Help is not active.`}]}}function d(e){let t=e.activation!==`inactive`;return[{id:`help.toggle`,path:[o,t?{key:`e`,label:`exit`,detail:`hide package Help`}:{key:`e`,label:`enter`,detail:`load package Help`}],action:{name:a}}]}function f(e){queueMicrotask(()=>{throw e instanceof Error?e:Error(String(e))})}function p(o,p){let m=o,h=n(m,{descriptor:{source:r,id:i,label:`Help`,description:`Activation-gated package guidance from exact installed package versions.`,order:50,actions:[{id:s,label:`Activate`,description:`Load package-owned Help indexes and expose their generated skills.`,contexts:[`tui`,`headless`],parameters:[]},{id:c,label:`Deactivate`,description:`Remove all active package Help skills immediately.`,contexts:[`tui`,`headless`],parameters:[]}]},initialState:u(p.getState()),async handleAction(e,t,n){if(e===s){let e=await p.activate(n.signal);return{message:l(`Activated ${e.skills.length} package Help skill${e.skills.length===1?``:`s`}${e.activation===`degraded`?` with diagnostics.`:`.`}`)}}if(e===c)return p.deactivate(),{message:`Package Help deactivated.`};throw Error(`Unknown Help mode action: ${e}`)},onError:f}),g=e(m,{source:r,bindings:d(p.getState())}),_=t(m,{source:r,handlers:{[a]:async e=>{p.getState().activation===`inactive`?await p.activate():p.deactivate(),e.hasUI&&e.ui.notify(p.getState().activation===`inactive`?`Package Help deactivated.`:`Package Help activated.`,`info`)}},onError:(e,t,n)=>{n.hasUI?n.ui.notify(e instanceof Error?e.message:String(e),`error`):f(e)}}),v=p.subscribe(e=>{h.publish(u(e)),g.update(d(e))}),y=!1;return{mode:h,dispose(){y||(y=!0,v(),_(),g.dispose(),h.dispose())}}}export{a as HELP_LEADER_ACTION,i as HELP_MODE_ID,r as HELP_PACKAGE_SOURCE,u as helpMinorModeState,p as registerHelpModeIntegration};
2
+ //# sourceMappingURL=helpMode.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpMode.mjs","names":[],"sources":["../../../src/adapters/pi/helpMode.ts"],"sourcesContent":["import type { DoomExtensionContext, DoomExtensionHost } from '@agimon-ai/doompi-extension-contracts/config';\nimport {\n createDoomLeaderContribution,\n type LeaderBinding,\n registerDoomLeaderActionHandlers,\n} from '@agimon-ai/doompi-extension-contracts/leader';\nimport {\n type MinorModeOwnerHandle,\n type MinorModeState,\n registerMinorModeOwner,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { HelpActivationService, HelpRuntimeState } from '../../types/help.ts';\n\nexport const HELP_PACKAGE_SOURCE = '@agimon-ai/doompi-help';\nexport const HELP_MODE_ID = 'help';\nexport const HELP_MODE_ORDER = 50;\nexport const HELP_LEADER_ACTION = 'help.toggle';\n\nconst HELP_GROUP = { key: 'h', label: 'help', order: 70 } as const;\nconst MODE_ACTION_ACTIVATE = 'activate';\nconst MODE_ACTION_DEACTIVATE = 'deactivate';\nconst MAX_MODE_DETAIL_LENGTH = 160;\n\ntype HelpModeContext = ExtensionContext & DoomExtensionContext;\ntype HelpModeHost = DoomExtensionHost<HelpModeContext>;\n\nfunction boundedDetail(value: string): string {\n return value.slice(0, MAX_MODE_DETAIL_LENGTH);\n}\n\nexport function helpMinorModeState(state: HelpRuntimeState): MinorModeState {\n if (state.activation === 'activating') {\n return {\n activation: 'activating',\n condition: 'queued',\n detail: 'loading package Help',\n actions: [\n { id: MODE_ACTION_ACTIVATE, enabled: false, disabledReason: 'Help activation is already running.' },\n { id: MODE_ACTION_DEACTIVATE, enabled: true },\n ],\n };\n }\n if (state.activation === 'active' || state.activation === 'degraded') {\n const degraded = state.activation === 'degraded';\n return {\n activation: 'active',\n condition: degraded ? 'degraded' : 'ready',\n detail: boundedDetail(`${state.skills.length} package Help skill${state.skills.length === 1 ? '' : 's'}`),\n ...(degraded ? { color: 'warning' as const } : { color: 'accent' as const }),\n actions: [\n { id: MODE_ACTION_ACTIVATE, enabled: false, disabledReason: 'Help is already active.' },\n { id: MODE_ACTION_DEACTIVATE, enabled: true },\n ],\n };\n }\n const failure = state.diagnostics[0]?.message;\n return {\n activation: 'inactive',\n condition: failure ? 'failed' : 'ready',\n ...(failure ? { detail: boundedDetail(failure), color: 'warning' as const } : {}),\n actions: [\n { id: MODE_ACTION_ACTIVATE, enabled: true },\n { id: MODE_ACTION_DEACTIVATE, enabled: false, disabledReason: 'Help is not active.' },\n ],\n };\n}\n\nfunction leaderBindings(state: HelpRuntimeState): LeaderBinding[] {\n const active = state.activation !== 'inactive';\n return [\n {\n id: 'help.toggle',\n path: [\n HELP_GROUP,\n active\n ? { key: 'e', label: 'exit', detail: 'hide package Help' }\n : { key: 'e', label: 'enter', detail: 'load package Help' },\n ],\n action: { name: HELP_LEADER_ACTION },\n },\n ];\n}\n\nfunction reportAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error instanceof Error ? error : new Error(String(error));\n });\n}\n\nexport interface HelpModeIntegration {\n mode: MinorModeOwnerHandle;\n dispose(): void;\n}\n\nexport function registerHelpModeIntegration(pi: ExtensionAPI, activation: HelpActivationService): HelpModeIntegration {\n const host = pi as unknown as HelpModeHost;\n const mode = registerMinorModeOwner(host, {\n descriptor: {\n source: HELP_PACKAGE_SOURCE,\n id: HELP_MODE_ID,\n label: 'Help',\n description: 'Activation-gated package guidance from exact installed package versions.',\n order: HELP_MODE_ORDER,\n actions: [\n {\n id: MODE_ACTION_ACTIVATE,\n label: 'Activate',\n description: 'Load package-owned Help indexes and expose their generated skills.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n {\n id: MODE_ACTION_DEACTIVATE,\n label: 'Deactivate',\n description: 'Remove all active package Help skills immediately.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n ],\n },\n initialState: helpMinorModeState(activation.getState()),\n async handleAction(actionId, _arguments, execution) {\n if (actionId === MODE_ACTION_ACTIVATE) {\n const state = await activation.activate(execution.signal);\n return {\n message: boundedDetail(\n `Activated ${state.skills.length} package Help skill${state.skills.length === 1 ? '' : 's'}${state.activation === 'degraded' ? ' with diagnostics.' : '.'}`,\n ),\n };\n }\n if (actionId === MODE_ACTION_DEACTIVATE) {\n activation.deactivate();\n return { message: 'Package Help deactivated.' };\n }\n throw new Error(`Unknown Help mode action: ${actionId}`);\n },\n onError: reportAsync,\n });\n const leader = createDoomLeaderContribution(host, {\n source: HELP_PACKAGE_SOURCE,\n bindings: leaderBindings(activation.getState()),\n });\n const actionDisposer = registerDoomLeaderActionHandlers(host, {\n source: HELP_PACKAGE_SOURCE,\n handlers: {\n [HELP_LEADER_ACTION]: async (context) => {\n const state = activation.getState();\n if (state.activation === 'inactive') await activation.activate();\n else activation.deactivate();\n if (context.hasUI) {\n context.ui.notify(\n activation.getState().activation === 'inactive' ? 'Package Help deactivated.' : 'Package Help activated.',\n 'info',\n );\n }\n },\n },\n onError: (error, _action, context) => {\n if (context.hasUI) context.ui.notify(error instanceof Error ? error.message : String(error), 'error');\n else reportAsync(error);\n },\n });\n const stateDisposer = activation.subscribe((state) => {\n mode.publish(helpMinorModeState(state));\n leader.update(leaderBindings(state));\n });\n let disposed = false;\n return {\n mode,\n dispose() {\n if (disposed) return;\n disposed = true;\n stateDisposer();\n actionDisposer();\n leader.dispose();\n mode.dispose();\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("../adapters/helpStorage.cjs"),t=require("../adapters/llmsResolver.cjs"),n=require("../services/helpActivation.cjs");function r(e){queueMicrotask(()=>{throw e instanceof Error?e:Error(String(e))})}function i(i,a={}){let o=a.cacheRoot??e.defaultHelpCacheRoot(),s=new e.HelpIndexCache(o),c=new n.DefaultHelpActivationService({resolver:new t.DefaultHelpIndexResolver({cache:s,fetch:a.fetch,timeoutMs:a.timeoutMs}),materializer:new e.DefaultHelpSkillMaterializer(o),publisher:{publish:e=>i.publish(e)},onBackgroundError(e){a.onBackgroundError?a.onBackgroundError(e):r(e)}}),l=e=>{c.replaceContributions(e)},u=i.subscribeContributions(e=>l(e));l(i.listContributions());let d=!1;return{activation:c,dispose(){d||(d=!0,u(),c.dispose())}}}exports.createHelpRuntime=i;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["defaultHelpCacheRoot","HelpIndexCache","DefaultHelpActivationService","DefaultHelpIndexResolver","DefaultHelpSkillMaterializer"],"sources":["../../src/container/index.ts"],"sourcesContent":["import type { DoomHelpContribution, DoomHelpHostHandle } from '@agimon-ai/doompi-extension-contracts/help';\nimport { DefaultHelpSkillMaterializer, defaultHelpCacheRoot, HelpIndexCache } from '../adapters/helpStorage.ts';\nimport { DefaultHelpIndexResolver } from '../adapters/llmsResolver.ts';\nimport { DefaultHelpActivationService } from '../services/helpActivation.ts';\nimport type { HelpFetch } from '../types/help.ts';\n\nexport interface HelpRuntimeOptions {\n cacheRoot?: string;\n fetch?: HelpFetch;\n timeoutMs?: number;\n onBackgroundError?(error: unknown): void;\n}\n\nexport interface HelpRuntimeComposition {\n activation: DefaultHelpActivationService;\n dispose(): void;\n}\n\nfunction reportAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error instanceof Error ? error : new Error(String(error));\n });\n}\n\nexport function createHelpRuntime(host: DoomHelpHostHandle, options: HelpRuntimeOptions = {}): HelpRuntimeComposition {\n const cacheRoot = options.cacheRoot ?? defaultHelpCacheRoot();\n const cache = new HelpIndexCache(cacheRoot);\n const activation = new DefaultHelpActivationService({\n resolver: new DefaultHelpIndexResolver({ cache, fetch: options.fetch, timeoutMs: options.timeoutMs }),\n materializer: new DefaultHelpSkillMaterializer(cacheRoot),\n publisher: { publish: (snapshot) => host.publish(snapshot) },\n onBackgroundError(error) {\n if (options.onBackgroundError) options.onBackgroundError(error);\n else reportAsync(error);\n },\n });\n const synchronize = (contributions: readonly DoomHelpContribution[]): void => {\n activation.replaceContributions(contributions);\n };\n const unsubscribe = host.subscribeContributions((contributions) => synchronize(contributions));\n synchronize(host.listContributions());\n let disposed = false;\n return {\n activation,\n dispose() {\n if (disposed) return;\n disposed = true;\n unsubscribe();\n activation.dispose();\n },\n };\n}\n"],"mappings":"qIAkBA,SAAS,EAAY,EAAsB,CACzC,mBAAqB,CACnB,MAAM,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,CAAC,CAChE,CAAC,CACH,CAEA,SAAgB,EAAkB,EAA0B,EAA8B,CAAC,EAA2B,CACpH,IAAM,EAAY,EAAQ,WAAaA,EAAAA,qBAAqB,EACtD,EAAQ,IAAIC,EAAAA,eAAe,CAAS,EACpC,EAAa,IAAIC,EAAAA,6BAA6B,CAClD,SAAU,IAAIC,EAAAA,yBAAyB,CAAE,QAAO,MAAO,EAAQ,MAAO,UAAW,EAAQ,SAAU,CAAC,EACpG,aAAc,IAAIC,EAAAA,6BAA6B,CAAS,EACxD,UAAW,CAAE,QAAU,GAAa,EAAK,QAAQ,CAAQ,CAAE,EAC3D,kBAAkB,EAAO,CACnB,EAAQ,kBAAmB,EAAQ,kBAAkB,CAAK,EACzD,EAAY,CAAK,CACxB,CACF,CAAC,EACK,EAAe,GAAyD,CAC5E,EAAW,qBAAqB,CAAa,CAC/C,EACM,EAAc,EAAK,uBAAwB,GAAkB,EAAY,CAAa,CAAC,EAC7F,EAAY,EAAK,kBAAkB,CAAC,EACpC,IAAI,EAAW,GACf,MAAO,CACL,aACA,SAAU,CACJ,IACJ,EAAW,GACX,EAAY,EACZ,EAAW,QAAQ,EACrB,CACF,CACF"}
@@ -0,0 +1,13 @@
1
+ import { HelpFetch } from "../types/help.cjs";
2
+ import "../services/helpActivation.cjs";
3
+ import "@agimon-ai/doompi-extension-contracts/help";
4
+ //#region src/container/index.d.ts
5
+ interface HelpRuntimeOptions {
6
+ cacheRoot?: string;
7
+ fetch?: HelpFetch;
8
+ timeoutMs?: number;
9
+ onBackgroundError?(error: unknown): void;
10
+ }
11
+ //#endregion
12
+ export { HelpRuntimeOptions };
13
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/container/index.ts"],"mappings":";;;;UAMiB;EACf;EACA,QAAQ;EACR;EACA,mBAAmB"}
@@ -0,0 +1,13 @@
1
+ import { HelpFetch } from "../types/help.mjs";
2
+ import "../services/helpActivation.mjs";
3
+ import "@agimon-ai/doompi-extension-contracts/help";
4
+ //#region src/container/index.d.ts
5
+ interface HelpRuntimeOptions {
6
+ cacheRoot?: string;
7
+ fetch?: HelpFetch;
8
+ timeoutMs?: number;
9
+ onBackgroundError?(error: unknown): void;
10
+ }
11
+ //#endregion
12
+ export { HelpRuntimeOptions };
13
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/container/index.ts"],"mappings":";;;;UAMiB;EACf;EACA,QAAQ;EACR;EACA,mBAAmB"}
@@ -0,0 +1,2 @@
1
+ import{DefaultHelpSkillMaterializer as e,HelpIndexCache as t,defaultHelpCacheRoot as n}from"../adapters/helpStorage.mjs";import{DefaultHelpIndexResolver as r}from"../adapters/llmsResolver.mjs";import{DefaultHelpActivationService as i}from"../services/helpActivation.mjs";function a(e){queueMicrotask(()=>{throw e instanceof Error?e:Error(String(e))})}function o(o,s={}){let c=s.cacheRoot??n(),l=new t(c),u=new i({resolver:new r({cache:l,fetch:s.fetch,timeoutMs:s.timeoutMs}),materializer:new e(c),publisher:{publish:e=>o.publish(e)},onBackgroundError(e){s.onBackgroundError?s.onBackgroundError(e):a(e)}}),d=e=>{u.replaceContributions(e)},f=o.subscribeContributions(e=>d(e));d(o.listContributions());let p=!1;return{activation:u,dispose(){p||(p=!0,f(),u.dispose())}}}export{o as createHelpRuntime};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/container/index.ts"],"sourcesContent":["import type { DoomHelpContribution, DoomHelpHostHandle } from '@agimon-ai/doompi-extension-contracts/help';\nimport { DefaultHelpSkillMaterializer, defaultHelpCacheRoot, HelpIndexCache } from '../adapters/helpStorage.ts';\nimport { DefaultHelpIndexResolver } from '../adapters/llmsResolver.ts';\nimport { DefaultHelpActivationService } from '../services/helpActivation.ts';\nimport type { HelpFetch } from '../types/help.ts';\n\nexport interface HelpRuntimeOptions {\n cacheRoot?: string;\n fetch?: HelpFetch;\n timeoutMs?: number;\n onBackgroundError?(error: unknown): void;\n}\n\nexport interface HelpRuntimeComposition {\n activation: DefaultHelpActivationService;\n dispose(): void;\n}\n\nfunction reportAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error instanceof Error ? error : new Error(String(error));\n });\n}\n\nexport function createHelpRuntime(host: DoomHelpHostHandle, options: HelpRuntimeOptions = {}): HelpRuntimeComposition {\n const cacheRoot = options.cacheRoot ?? defaultHelpCacheRoot();\n const cache = new HelpIndexCache(cacheRoot);\n const activation = new DefaultHelpActivationService({\n resolver: new DefaultHelpIndexResolver({ cache, fetch: options.fetch, timeoutMs: options.timeoutMs }),\n materializer: new DefaultHelpSkillMaterializer(cacheRoot),\n publisher: { publish: (snapshot) => host.publish(snapshot) },\n onBackgroundError(error) {\n if (options.onBackgroundError) options.onBackgroundError(error);\n else reportAsync(error);\n },\n });\n const synchronize = (contributions: readonly DoomHelpContribution[]): void => {\n activation.replaceContributions(contributions);\n };\n const unsubscribe = host.subscribeContributions((contributions) => synchronize(contributions));\n synchronize(host.listContributions());\n let disposed = false;\n return {\n activation,\n dispose() {\n if (disposed) return;\n disposed = true;\n unsubscribe();\n activation.dispose();\n },\n };\n}\n"],"mappings":"+QAkBA,SAAS,EAAY,EAAsB,CACzC,mBAAqB,CACnB,MAAM,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,CAAC,CAChE,CAAC,CACH,CAEA,SAAgB,EAAkB,EAA0B,EAA8B,CAAC,EAA2B,CACpH,IAAM,EAAY,EAAQ,WAAa,EAAqB,EACtD,EAAQ,IAAI,EAAe,CAAS,EACpC,EAAa,IAAI,EAA6B,CAClD,SAAU,IAAI,EAAyB,CAAE,QAAO,MAAO,EAAQ,MAAO,UAAW,EAAQ,SAAU,CAAC,EACpG,aAAc,IAAI,EAA6B,CAAS,EACxD,UAAW,CAAE,QAAU,GAAa,EAAK,QAAQ,CAAQ,CAAE,EAC3D,kBAAkB,EAAO,CACnB,EAAQ,kBAAmB,EAAQ,kBAAkB,CAAK,EACzD,EAAY,CAAK,CACxB,CACF,CAAC,EACK,EAAe,GAAyD,CAC5E,EAAW,qBAAqB,CAAa,CAC/C,EACM,EAAc,EAAK,uBAAwB,GAAkB,EAAY,CAAa,CAAC,EAC7F,EAAY,EAAK,kBAAkB,CAAC,EACpC,IAAI,EAAW,GACf,MAAO,CACL,aACA,SAAU,CACJ,IACJ,EAAW,GACX,EAAY,EACZ,EAAW,QAAQ,EACrB,CACF,CACF"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../adapters/pi/helpMode.cjs"),t=require("../container/index.cjs");let n=require("@agimon-ai/doompi-extension-contracts/help");const r=`@agimon-ai/doompi-help`,i=Symbol.for(`${r}/installed-hosts`);function a(e){let t=globalThis,n=t[i]??new WeakSet;return t[i]=n,!n.has(e)&&(n.add(e),!0)}function o(i,a={}){let o=i,s=(0,n.provideDoomHelpHost)(o),c=t.createHelpRuntime(s,a),l=e.registerHelpModeIntegration(i,c.activation),u=(0,n.registerDoomHelpContribution)(o,{source:r,moduleUrl:require("url").pathToFileURL(__filename).href,skills:[{name:`doompi-help`,description:`Use Doom Pi package Help safely, including activation, exact-version retrieval, and diagnostics.`}]});i.on(`session_start`,()=>{c.activation.deactivate()});let d=!1;return()=>{d||(d=!0,l.dispose(),u.dispose(),c.dispose(),s.dispose())}}function s(e){if(!a(e))return;let t=o(e);e.on(`session_shutdown`,t)}exports.activateHelpExtension=o,exports.default=s,exports.registerHelpExtension=s;
2
+ //# sourceMappingURL=doom.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doom.cjs","names":["provideDoomHelpHost","createHelpRuntime","registerHelpModeIntegration","registerDoomHelpContribution"],"sources":["../../src/exports/extensions/doom.ts"],"sourcesContent":["import type { DoomExtensionHost } from '@agimon-ai/doompi-extension-contracts/config';\nimport { provideDoomHelpHost, registerDoomHelpContribution } from '@agimon-ai/doompi-extension-contracts/help';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { registerHelpModeIntegration } from '../../adapters/pi/helpMode.ts';\nimport { createHelpRuntime, type HelpRuntimeOptions } from '../../container/index.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-help';\nconst INSTALLATIONS_KEY = Symbol.for(`${PACKAGE_SOURCE}/installed-hosts`);\n\ntype InstallationRegistry = typeof globalThis & {\n [INSTALLATIONS_KEY]?: WeakSet<object>;\n};\n\nfunction claimHostInstallation(pi: ExtensionAPI): boolean {\n const registry = globalThis as InstallationRegistry;\n const installedHosts = registry[INSTALLATIONS_KEY] ?? new WeakSet<object>();\n registry[INSTALLATIONS_KEY] = installedHosts;\n if (installedHosts.has(pi)) return false;\n installedHosts.add(pi);\n return true;\n}\n\nexport function activateHelpExtension(pi: ExtensionAPI, options: HelpRuntimeOptions = {}): () => void {\n const protocolHost = pi as unknown as DoomExtensionHost;\n const host = provideDoomHelpHost(protocolHost);\n const runtime = createHelpRuntime(host, options);\n const mode = registerHelpModeIntegration(pi, runtime.activation);\n const selfContribution = registerDoomHelpContribution(protocolHost, {\n source: PACKAGE_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-help',\n description: 'Use Doom Pi package Help safely, including activation, exact-version retrieval, and diagnostics.',\n },\n ],\n });\n pi.on('session_start', () => {\n runtime.activation.deactivate();\n });\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n mode.dispose();\n selfContribution.dispose();\n runtime.dispose();\n host.dispose();\n };\n}\n\nexport function registerHelpExtension(pi: ExtensionAPI): void {\n if (!claimHostInstallation(pi)) return;\n const dispose = activateHelpExtension(pi);\n pi.on('session_shutdown', dispose);\n}\n\nexport default registerHelpExtension;\n"],"mappings":"8OAMA,MAAM,EAAiB,yBACjB,EAAoB,OAAO,IAAI,GAAG,EAAe,iBAAiB,EAMxE,SAAS,EAAsB,EAA2B,CACxD,IAAM,EAAW,WACX,EAAiB,EAAS,IAAsB,IAAI,QAI1D,MAHA,GAAS,GAAqB,EAC9B,CAAI,EAAe,IAAI,CAAE,IACzB,EAAe,IAAI,CAAE,EACd,GACT,CAEA,SAAgB,EAAsB,EAAkB,EAA8B,CAAC,EAAe,CACpG,IAAM,EAAe,EACf,GAAA,EAAOA,EAAAA,oBAAAA,CAAoB,CAAY,EACvC,EAAUC,EAAAA,kBAAkB,EAAM,CAAO,EACzC,EAAOC,EAAAA,4BAA4B,EAAI,EAAQ,UAAU,EACzD,GAAA,EAAmBC,EAAAA,6BAAAA,CAA6B,EAAc,CAClE,OAAQ,EACR,UAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,KACA,OAAQ,CACN,CACE,KAAM,cACN,YAAa,kGACf,CACF,CACF,CAAC,EACD,EAAG,GAAG,oBAAuB,CAC3B,EAAQ,WAAW,WAAW,CAChC,CAAC,EACD,IAAI,EAAW,GACf,UAAa,CACP,IACJ,EAAW,GACX,EAAK,QAAQ,EACb,EAAiB,QAAQ,EACzB,EAAQ,QAAQ,EAChB,EAAK,QAAQ,EACf,CACF,CAEA,SAAgB,EAAsB,EAAwB,CAC5D,GAAI,CAAC,EAAsB,CAAE,EAAG,OAChC,IAAM,EAAU,EAAsB,CAAE,EACxC,EAAG,GAAG,mBAAoB,CAAO,CACnC"}
@@ -0,0 +1,8 @@
1
+ import { HelpRuntimeOptions } from "../container/index.cjs";
2
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
+ //#region src/exports/extensions/doom.d.ts
4
+ declare function activateHelpExtension(pi: ExtensionAPI, options?: HelpRuntimeOptions): () => void;
5
+ declare function registerHelpExtension(pi: ExtensionAPI): void;
6
+ //#endregion
7
+ export { activateHelpExtension, registerHelpExtension as default, registerHelpExtension };
8
+ //# sourceMappingURL=doom.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doom.d.cts","names":[],"sources":["../../src/exports/extensions/doom.ts"],"mappings":";;;iBAsBgB,sBAAsB,IAAI,cAAc,UAAS;iBA6BjD,sBAAsB,IAAI"}
@@ -0,0 +1,8 @@
1
+ import { HelpRuntimeOptions } from "../container/index.mjs";
2
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
+ //#region src/exports/extensions/doom.d.ts
4
+ declare function activateHelpExtension(pi: ExtensionAPI, options?: HelpRuntimeOptions): () => void;
5
+ declare function registerHelpExtension(pi: ExtensionAPI): void;
6
+ //#endregion
7
+ export { activateHelpExtension, registerHelpExtension as default, registerHelpExtension };
8
+ //# sourceMappingURL=doom.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doom.d.mts","names":[],"sources":["../../src/exports/extensions/doom.ts"],"mappings":";;;iBAsBgB,sBAAsB,IAAI,cAAc,UAAS;iBA6BjD,sBAAsB,IAAI"}
@@ -0,0 +1,2 @@
1
+ import{registerHelpModeIntegration as e}from"../adapters/pi/helpMode.mjs";import{createHelpRuntime as t}from"../container/index.mjs";import{provideDoomHelpHost as n,registerDoomHelpContribution as r}from"@agimon-ai/doompi-extension-contracts/help";const i=`@agimon-ai/doompi-help`,a=Symbol.for(`${i}/installed-hosts`);function o(e){let t=globalThis,n=t[a]??new WeakSet;return t[a]=n,!n.has(e)&&(n.add(e),!0)}function s(a,o={}){let s=a,c=n(s),l=t(c,o),u=e(a,l.activation),d=r(s,{source:i,moduleUrl:import.meta.url,skills:[{name:`doompi-help`,description:`Use Doom Pi package Help safely, including activation, exact-version retrieval, and diagnostics.`}]});a.on(`session_start`,()=>{l.activation.deactivate()});let f=!1;return()=>{f||(f=!0,u.dispose(),d.dispose(),l.dispose(),c.dispose())}}function c(e){if(!o(e))return;let t=s(e);e.on(`session_shutdown`,t)}export{s as activateHelpExtension,c as default,c as registerHelpExtension};
2
+ //# sourceMappingURL=doom.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doom.mjs","names":[],"sources":["../../src/exports/extensions/doom.ts"],"sourcesContent":["import type { DoomExtensionHost } from '@agimon-ai/doompi-extension-contracts/config';\nimport { provideDoomHelpHost, registerDoomHelpContribution } from '@agimon-ai/doompi-extension-contracts/help';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { registerHelpModeIntegration } from '../../adapters/pi/helpMode.ts';\nimport { createHelpRuntime, type HelpRuntimeOptions } from '../../container/index.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-help';\nconst INSTALLATIONS_KEY = Symbol.for(`${PACKAGE_SOURCE}/installed-hosts`);\n\ntype InstallationRegistry = typeof globalThis & {\n [INSTALLATIONS_KEY]?: WeakSet<object>;\n};\n\nfunction claimHostInstallation(pi: ExtensionAPI): boolean {\n const registry = globalThis as InstallationRegistry;\n const installedHosts = registry[INSTALLATIONS_KEY] ?? new WeakSet<object>();\n registry[INSTALLATIONS_KEY] = installedHosts;\n if (installedHosts.has(pi)) return false;\n installedHosts.add(pi);\n return true;\n}\n\nexport function activateHelpExtension(pi: ExtensionAPI, options: HelpRuntimeOptions = {}): () => void {\n const protocolHost = pi as unknown as DoomExtensionHost;\n const host = provideDoomHelpHost(protocolHost);\n const runtime = createHelpRuntime(host, options);\n const mode = registerHelpModeIntegration(pi, runtime.activation);\n const selfContribution = registerDoomHelpContribution(protocolHost, {\n source: PACKAGE_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-help',\n description: 'Use Doom Pi package Help safely, including activation, exact-version retrieval, and diagnostics.',\n },\n ],\n });\n pi.on('session_start', () => {\n runtime.activation.deactivate();\n });\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n mode.dispose();\n selfContribution.dispose();\n runtime.dispose();\n host.dispose();\n };\n}\n\nexport function registerHelpExtension(pi: ExtensionAPI): void {\n if (!claimHostInstallation(pi)) return;\n const dispose = activateHelpExtension(pi);\n pi.on('session_shutdown', dispose);\n}\n\nexport default registerHelpExtension;\n"],"mappings":"wPAMA,MAAM,EAAiB,yBACjB,EAAoB,OAAO,IAAI,GAAG,EAAe,iBAAiB,EAMxE,SAAS,EAAsB,EAA2B,CACxD,IAAM,EAAW,WACX,EAAiB,EAAS,IAAsB,IAAI,QAI1D,MAHA,GAAS,GAAqB,EAC9B,CAAI,EAAe,IAAI,CAAE,IACzB,EAAe,IAAI,CAAE,EACd,GACT,CAEA,SAAgB,EAAsB,EAAkB,EAA8B,CAAC,EAAe,CACpG,IAAM,EAAe,EACf,EAAO,EAAoB,CAAY,EACvC,EAAU,EAAkB,EAAM,CAAO,EACzC,EAAO,EAA4B,EAAI,EAAQ,UAAU,EACzD,EAAmB,EAA6B,EAAc,CAClE,OAAQ,EACR,UAAW,YAAY,IACvB,OAAQ,CACN,CACE,KAAM,cACN,YAAa,kGACf,CACF,CACF,CAAC,EACD,EAAG,GAAG,oBAAuB,CAC3B,EAAQ,WAAW,WAAW,CAChC,CAAC,EACD,IAAI,EAAW,GACf,UAAa,CACP,IACJ,EAAW,GACX,EAAK,QAAQ,EACb,EAAiB,QAAQ,EACzB,EAAQ,QAAQ,EAChB,EAAK,QAAQ,EACf,CACF,CAEA,SAAgB,EAAsB,EAAwB,CAC5D,GAAI,CAAC,EAAsB,CAAE,EAAG,OAChC,IAAM,EAAU,EAAsB,CAAE,EACxC,EAAG,GAAG,mBAAoB,CAAO,CACnC"}
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./extensions/doom.cjs");exports.activateHelpExtension=e.activateHelpExtension,exports.registerHelpExtension=e.default;
@@ -0,0 +1,2 @@
1
+ import registerHelpExtension, { activateHelpExtension } from "./extensions/doom.cjs";
2
+ export { activateHelpExtension, registerHelpExtension };
@@ -0,0 +1,2 @@
1
+ import registerHelpExtension, { activateHelpExtension } from "./extensions/doom.mjs";
2
+ export { activateHelpExtension, registerHelpExtension };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import e,{activateHelpExtension as t}from"./extensions/doom.mjs";export{t as activateHelpExtension,e as registerHelpExtension};
@@ -0,0 +1,2 @@
1
+ require("./llmsContent.cjs");let e=require("@agimon-ai/doompi-extension-contracts/help");const t=`Help activation was cancelled.`;var n=class extends Error{constructor(e=`No package Help source could be activated.`){super(e),this.name=`HelpActivationError`}};function r(e){return{source:e.source,moduleUrl:e.moduleUrl,skills:e.skills.map(e=>({...e}))}}function i(e){return{activation:e.activation,skills:e.skills.map(e=>({...e})),diagnostics:e.diagnostics.map(e=>({...e}))}}function a(t,n,r){return{source:t,code:n,message:((r instanceof Error?r.message:String(r))||`Unknown Help activation failure.`).slice(0,e.DOOM_HELP_MAX_DIAGNOSTIC_LENGTH)}}function o(e){return JSON.stringify(e.map(e=>({source:e.source,moduleUrl:e.moduleUrl,skills:e.skills})))}var s=class{dependencies;listeners=new Set;contributions=[];fingerprint=`[]`;state={activation:`inactive`,skills:[],diagnostics:[]};settledState={activation:`inactive`,skills:[],diagnostics:[]};generation=0;controller;disposed=!1;constructor(e){this.dependencies=e}getState(){return i(this.state)}replaceContributions(e){if(this.disposed)return;let t=e.map(r).sort((e,t)=>e.source.localeCompare(t.source)),i=o(t);i!==this.fingerprint&&(this.contributions=t,this.fingerprint=i,this.state.activation!==`inactive`&&this.activate().catch(e=>{e instanceof n||this.dependencies.onBackgroundError(e)}))}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}publish(e){this.state=i(e),e.activation!==`activating`&&(this.settledState=i(e)),this.dependencies.publisher.publish(this.state);for(let e of this.listeners)e(i(this.state));return this.getState()}async loadSources(e){let r=Array.from({length:this.contributions.length}),i=0,a=async()=>{for(;i<this.contributions.length;){let a=i;i+=1;let o=this.contributions[a];if(!o)return;if(e.aborted)throw new n(t);try{let t=await this.dependencies.resolver.resolve(o,e),n=await this.dependencies.materializer.materialize(o,t,e);r[a]={source:o.source,loaded:{contribution:o,index:t,skills:n}}}catch(i){if(e.aborted)throw new n(t);r[a]={source:o.source,error:i}}}},o=Math.min(4,this.contributions.length);return await Promise.all(Array.from({length:o},()=>a())),r}async activate(r){if(this.disposed)throw new n(`Help runtime is disposed.`);this.controller?.abort(`Help activation generation replaced.`);let o=new AbortController;this.controller=o;let s=++this.generation,c=()=>o.abort(r?.reason);r?.addEventListener(`abort`,c,{once:!0}),r?.aborted&&c();let l=i(this.settledState);this.publish({activation:`activating`,skills:l.skills,diagnostics:l.diagnostics});try{let r=await this.loadSources(o.signal);if(o.signal.aborted||s!==this.generation)throw new n(t);let i=[],c=[],l=0;for(let e of r)if(e){if(e.error||!e.loaded){i.push(a(e.source,`HELP_SOURCE_FAILED`,e.error));continue}if(l+e.loaded.index.byteLength>4194304){i.push(a(e.source,`HELP_AGGREGATE_LIMIT`,`The aggregate llms.txt byte limit was exceeded.`));continue}l+=e.loaded.index.byteLength,c.push(e.loaded)}let u=[],d=new Set;for(let t of c)for(let n of t.skills){if(u.length>=e.DOOM_HELP_MAX_SKILLS){i.push(a(t.contribution.source,`HELP_SKILL_LIMIT`,`The Help skill limit was reached.`));break}if(d.has(n.name)){i.push(a(t.contribution.source,`HELP_SKILL_COLLISION`,`Help skill '${n.name}' was already provided by an earlier package source.`));continue}d.add(n.name),u.push({...n})}let f=i.slice(0,e.DOOM_HELP_MAX_DIAGNOSTICS);if(u.length===0)throw this.publish({activation:`inactive`,skills:[],diagnostics:f}),new n;return this.publish({activation:f.length>0?`degraded`:`active`,skills:u,diagnostics:f})}catch(e){throw s===this.generation&&this.state.activation===`activating`&&this.publish(l),e}finally{r?.removeEventListener(`abort`,c),this.controller===o&&(this.controller=void 0)}}deactivate(){return this.generation+=1,this.controller?.abort(`Help deactivated.`),this.controller=void 0,this.publish({activation:`inactive`,skills:[],diagnostics:[]})}dispose(){this.disposed||(this.deactivate(),this.disposed=!0,this.listeners.clear())}};exports.DefaultHelpActivationService=s,exports.HelpActivationError=n;
2
+ //# sourceMappingURL=helpActivation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpActivation.cjs","names":["DOOM_HELP_MAX_DIAGNOSTIC_LENGTH","DOOM_HELP_MAX_SKILLS","DOOM_HELP_MAX_DIAGNOSTICS"],"sources":["../../src/services/helpActivation.ts"],"sourcesContent":["import {\n DOOM_HELP_MAX_DIAGNOSTIC_LENGTH,\n DOOM_HELP_MAX_DIAGNOSTICS,\n DOOM_HELP_MAX_SKILLS,\n type DoomHelpContribution,\n type DoomHelpDiagnostic,\n type DoomHelpSkill,\n} from '@agimon-ai/doompi-extension-contracts/help';\nimport type {\n HelpActivationDependencies,\n HelpActivationService,\n HelpRuntimeState,\n ResolvedHelpIndex,\n} from '../types/help.ts';\nimport { MAX_AGGREGATE_LLMS_BYTES } from './llmsContent.ts';\n\nconst MAX_RESOLUTION_CONCURRENCY = 4;\nconst FAILURE_MESSAGE = 'No package Help source could be activated.';\nconst CANCELLATION_MESSAGE = 'Help activation was cancelled.';\n\ninterface LoadedSource {\n contribution: DoomHelpContribution;\n index: ResolvedHelpIndex;\n skills: readonly DoomHelpSkill[];\n}\n\ninterface SourceOutcome {\n source: string;\n loaded?: LoadedSource;\n error?: unknown;\n}\n\nexport class HelpActivationError extends Error {\n constructor(message = FAILURE_MESSAGE) {\n super(message);\n this.name = 'HelpActivationError';\n }\n}\n\nfunction cloneContribution(contribution: DoomHelpContribution): DoomHelpContribution {\n return {\n source: contribution.source,\n moduleUrl: contribution.moduleUrl,\n skills: contribution.skills.map((skill) => ({ ...skill })),\n };\n}\n\nfunction cloneState(state: HelpRuntimeState): HelpRuntimeState {\n return {\n activation: state.activation,\n skills: state.skills.map((skill) => ({ ...skill })),\n diagnostics: state.diagnostics.map((diagnostic) => ({ ...diagnostic })),\n };\n}\n\nfunction diagnostic(source: string, code: string, error: unknown): DoomHelpDiagnostic {\n const raw = error instanceof Error ? error.message : String(error);\n const message = (raw || 'Unknown Help activation failure.').slice(0, DOOM_HELP_MAX_DIAGNOSTIC_LENGTH);\n return { source, code, message };\n}\n\nfunction contributionFingerprint(contributions: readonly DoomHelpContribution[]): string {\n return JSON.stringify(\n contributions.map((contribution) => ({\n source: contribution.source,\n moduleUrl: contribution.moduleUrl,\n skills: contribution.skills,\n })),\n );\n}\n\nexport class DefaultHelpActivationService implements HelpActivationService {\n private readonly dependencies: HelpActivationDependencies;\n private readonly listeners = new Set<(state: HelpRuntimeState) => void>();\n private contributions: DoomHelpContribution[] = [];\n private fingerprint = '[]';\n private state: HelpRuntimeState = { activation: 'inactive', skills: [], diagnostics: [] };\n private settledState: HelpRuntimeState = { activation: 'inactive', skills: [], diagnostics: [] };\n private generation = 0;\n private controller: AbortController | undefined;\n private disposed = false;\n\n constructor(dependencies: HelpActivationDependencies) {\n this.dependencies = dependencies;\n }\n\n getState(): HelpRuntimeState {\n return cloneState(this.state);\n }\n\n replaceContributions(contributions: readonly DoomHelpContribution[]): void {\n if (this.disposed) return;\n const next = contributions.map(cloneContribution).sort((left, right) => left.source.localeCompare(right.source));\n const fingerprint = contributionFingerprint(next);\n if (fingerprint === this.fingerprint) return;\n this.contributions = next;\n this.fingerprint = fingerprint;\n if (this.state.activation !== 'inactive') {\n void this.activate().catch((error: unknown) => {\n // Activation failures publish a bounded settled state before rejecting.\n // Only unexpected implementation failures need an out-of-band report.\n if (error instanceof HelpActivationError) return;\n this.dependencies.onBackgroundError(error);\n });\n }\n }\n\n subscribe(listener: (state: HelpRuntimeState) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private publish(state: HelpRuntimeState): HelpRuntimeState {\n this.state = cloneState(state);\n if (state.activation !== 'activating') this.settledState = cloneState(state);\n this.dependencies.publisher.publish(this.state);\n for (const listener of this.listeners) listener(cloneState(this.state));\n return this.getState();\n }\n\n private async loadSources(signal: AbortSignal): Promise<SourceOutcome[]> {\n const outcomes: SourceOutcome[] = Array.from({ length: this.contributions.length });\n let cursor = 0;\n const worker = async (): Promise<void> => {\n while (cursor < this.contributions.length) {\n const index = cursor;\n cursor += 1;\n const contribution = this.contributions[index];\n if (!contribution) return;\n if (signal.aborted) throw new HelpActivationError(CANCELLATION_MESSAGE);\n try {\n const resolved = await this.dependencies.resolver.resolve(contribution, signal);\n const skills = await this.dependencies.materializer.materialize(contribution, resolved, signal);\n outcomes[index] = { source: contribution.source, loaded: { contribution, index: resolved, skills } };\n } catch (error) {\n if (signal.aborted) throw new HelpActivationError(CANCELLATION_MESSAGE);\n outcomes[index] = { source: contribution.source, error };\n }\n }\n };\n const count = Math.min(MAX_RESOLUTION_CONCURRENCY, this.contributions.length);\n await Promise.all(Array.from({ length: count }, () => worker()));\n return outcomes;\n }\n\n async activate(externalSignal?: AbortSignal): Promise<HelpRuntimeState> {\n if (this.disposed) throw new HelpActivationError('Help runtime is disposed.');\n this.controller?.abort('Help activation generation replaced.');\n const controller = new AbortController();\n this.controller = controller;\n const generation = ++this.generation;\n const abortFromExternal = () => controller.abort(externalSignal?.reason);\n externalSignal?.addEventListener('abort', abortFromExternal, { once: true });\n if (externalSignal?.aborted) abortFromExternal();\n\n const settledState = cloneState(this.settledState);\n this.publish({ activation: 'activating', skills: settledState.skills, diagnostics: settledState.diagnostics });\n try {\n const outcomes = await this.loadSources(controller.signal);\n if (controller.signal.aborted || generation !== this.generation) {\n throw new HelpActivationError(CANCELLATION_MESSAGE);\n }\n\n const diagnostics: DoomHelpDiagnostic[] = [];\n const loaded: LoadedSource[] = [];\n let aggregateBytes = 0;\n for (const outcome of outcomes) {\n if (!outcome) continue;\n if (outcome.error || !outcome.loaded) {\n diagnostics.push(diagnostic(outcome.source, 'HELP_SOURCE_FAILED', outcome.error));\n continue;\n }\n if (aggregateBytes + outcome.loaded.index.byteLength > MAX_AGGREGATE_LLMS_BYTES) {\n diagnostics.push(\n diagnostic(outcome.source, 'HELP_AGGREGATE_LIMIT', 'The aggregate llms.txt byte limit was exceeded.'),\n );\n continue;\n }\n aggregateBytes += outcome.loaded.index.byteLength;\n loaded.push(outcome.loaded);\n }\n\n const skills: DoomHelpSkill[] = [];\n const names = new Set<string>();\n for (const source of loaded) {\n for (const skill of source.skills) {\n if (skills.length >= DOOM_HELP_MAX_SKILLS) {\n diagnostics.push(\n diagnostic(source.contribution.source, 'HELP_SKILL_LIMIT', 'The Help skill limit was reached.'),\n );\n break;\n }\n if (names.has(skill.name)) {\n diagnostics.push(\n diagnostic(\n source.contribution.source,\n 'HELP_SKILL_COLLISION',\n `Help skill '${skill.name}' was already provided by an earlier package source.`,\n ),\n );\n continue;\n }\n names.add(skill.name);\n skills.push({ ...skill });\n }\n }\n\n const boundedDiagnostics = diagnostics.slice(0, DOOM_HELP_MAX_DIAGNOSTICS);\n if (skills.length === 0) {\n this.publish({ activation: 'inactive', skills: [], diagnostics: boundedDiagnostics });\n throw new HelpActivationError();\n }\n return this.publish({\n activation: boundedDiagnostics.length > 0 ? 'degraded' : 'active',\n skills,\n diagnostics: boundedDiagnostics,\n });\n } catch (error) {\n if (generation === this.generation && this.state.activation === 'activating') this.publish(settledState);\n throw error;\n } finally {\n externalSignal?.removeEventListener('abort', abortFromExternal);\n if (this.controller === controller) this.controller = undefined;\n }\n }\n\n deactivate(): HelpRuntimeState {\n this.generation += 1;\n this.controller?.abort('Help deactivated.');\n this.controller = undefined;\n return this.publish({ activation: 'inactive', skills: [], diagnostics: [] });\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.deactivate();\n this.disposed = true;\n this.listeners.clear();\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import "../types/help.cjs";
2
+ import "@agimon-ai/doompi-extension-contracts/help";
@@ -0,0 +1,2 @@
1
+ import "../types/help.mjs";
2
+ import "@agimon-ai/doompi-extension-contracts/help";
@@ -0,0 +1,2 @@
1
+ import"./llmsContent.mjs";import{DOOM_HELP_MAX_DIAGNOSTICS as e,DOOM_HELP_MAX_DIAGNOSTIC_LENGTH as t,DOOM_HELP_MAX_SKILLS as n}from"@agimon-ai/doompi-extension-contracts/help";const r=`Help activation was cancelled.`;var i=class extends Error{constructor(e=`No package Help source could be activated.`){super(e),this.name=`HelpActivationError`}};function a(e){return{source:e.source,moduleUrl:e.moduleUrl,skills:e.skills.map(e=>({...e}))}}function o(e){return{activation:e.activation,skills:e.skills.map(e=>({...e})),diagnostics:e.diagnostics.map(e=>({...e}))}}function s(e,n,r){return{source:e,code:n,message:((r instanceof Error?r.message:String(r))||`Unknown Help activation failure.`).slice(0,t)}}function c(e){return JSON.stringify(e.map(e=>({source:e.source,moduleUrl:e.moduleUrl,skills:e.skills})))}var l=class{dependencies;listeners=new Set;contributions=[];fingerprint=`[]`;state={activation:`inactive`,skills:[],diagnostics:[]};settledState={activation:`inactive`,skills:[],diagnostics:[]};generation=0;controller;disposed=!1;constructor(e){this.dependencies=e}getState(){return o(this.state)}replaceContributions(e){if(this.disposed)return;let t=e.map(a).sort((e,t)=>e.source.localeCompare(t.source)),n=c(t);n!==this.fingerprint&&(this.contributions=t,this.fingerprint=n,this.state.activation!==`inactive`&&this.activate().catch(e=>{e instanceof i||this.dependencies.onBackgroundError(e)}))}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}publish(e){this.state=o(e),e.activation!==`activating`&&(this.settledState=o(e)),this.dependencies.publisher.publish(this.state);for(let e of this.listeners)e(o(this.state));return this.getState()}async loadSources(e){let t=Array.from({length:this.contributions.length}),n=0,a=async()=>{for(;n<this.contributions.length;){let a=n;n+=1;let o=this.contributions[a];if(!o)return;if(e.aborted)throw new i(r);try{let n=await this.dependencies.resolver.resolve(o,e),r=await this.dependencies.materializer.materialize(o,n,e);t[a]={source:o.source,loaded:{contribution:o,index:n,skills:r}}}catch(n){if(e.aborted)throw new i(r);t[a]={source:o.source,error:n}}}},o=Math.min(4,this.contributions.length);return await Promise.all(Array.from({length:o},()=>a())),t}async activate(t){if(this.disposed)throw new i(`Help runtime is disposed.`);this.controller?.abort(`Help activation generation replaced.`);let a=new AbortController;this.controller=a;let c=++this.generation,l=()=>a.abort(t?.reason);t?.addEventListener(`abort`,l,{once:!0}),t?.aborted&&l();let u=o(this.settledState);this.publish({activation:`activating`,skills:u.skills,diagnostics:u.diagnostics});try{let t=await this.loadSources(a.signal);if(a.signal.aborted||c!==this.generation)throw new i(r);let o=[],l=[],u=0;for(let e of t)if(e){if(e.error||!e.loaded){o.push(s(e.source,`HELP_SOURCE_FAILED`,e.error));continue}if(u+e.loaded.index.byteLength>4194304){o.push(s(e.source,`HELP_AGGREGATE_LIMIT`,`The aggregate llms.txt byte limit was exceeded.`));continue}u+=e.loaded.index.byteLength,l.push(e.loaded)}let d=[],f=new Set;for(let e of l)for(let t of e.skills){if(d.length>=n){o.push(s(e.contribution.source,`HELP_SKILL_LIMIT`,`The Help skill limit was reached.`));break}if(f.has(t.name)){o.push(s(e.contribution.source,`HELP_SKILL_COLLISION`,`Help skill '${t.name}' was already provided by an earlier package source.`));continue}f.add(t.name),d.push({...t})}let p=o.slice(0,e);if(d.length===0)throw this.publish({activation:`inactive`,skills:[],diagnostics:p}),new i;return this.publish({activation:p.length>0?`degraded`:`active`,skills:d,diagnostics:p})}catch(e){throw c===this.generation&&this.state.activation===`activating`&&this.publish(u),e}finally{t?.removeEventListener(`abort`,l),this.controller===a&&(this.controller=void 0)}}deactivate(){return this.generation+=1,this.controller?.abort(`Help deactivated.`),this.controller=void 0,this.publish({activation:`inactive`,skills:[],diagnostics:[]})}dispose(){this.disposed||(this.deactivate(),this.disposed=!0,this.listeners.clear())}};export{l as DefaultHelpActivationService,i as HelpActivationError};
2
+ //# sourceMappingURL=helpActivation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpActivation.mjs","names":[],"sources":["../../src/services/helpActivation.ts"],"sourcesContent":["import {\n DOOM_HELP_MAX_DIAGNOSTIC_LENGTH,\n DOOM_HELP_MAX_DIAGNOSTICS,\n DOOM_HELP_MAX_SKILLS,\n type DoomHelpContribution,\n type DoomHelpDiagnostic,\n type DoomHelpSkill,\n} from '@agimon-ai/doompi-extension-contracts/help';\nimport type {\n HelpActivationDependencies,\n HelpActivationService,\n HelpRuntimeState,\n ResolvedHelpIndex,\n} from '../types/help.ts';\nimport { MAX_AGGREGATE_LLMS_BYTES } from './llmsContent.ts';\n\nconst MAX_RESOLUTION_CONCURRENCY = 4;\nconst FAILURE_MESSAGE = 'No package Help source could be activated.';\nconst CANCELLATION_MESSAGE = 'Help activation was cancelled.';\n\ninterface LoadedSource {\n contribution: DoomHelpContribution;\n index: ResolvedHelpIndex;\n skills: readonly DoomHelpSkill[];\n}\n\ninterface SourceOutcome {\n source: string;\n loaded?: LoadedSource;\n error?: unknown;\n}\n\nexport class HelpActivationError extends Error {\n constructor(message = FAILURE_MESSAGE) {\n super(message);\n this.name = 'HelpActivationError';\n }\n}\n\nfunction cloneContribution(contribution: DoomHelpContribution): DoomHelpContribution {\n return {\n source: contribution.source,\n moduleUrl: contribution.moduleUrl,\n skills: contribution.skills.map((skill) => ({ ...skill })),\n };\n}\n\nfunction cloneState(state: HelpRuntimeState): HelpRuntimeState {\n return {\n activation: state.activation,\n skills: state.skills.map((skill) => ({ ...skill })),\n diagnostics: state.diagnostics.map((diagnostic) => ({ ...diagnostic })),\n };\n}\n\nfunction diagnostic(source: string, code: string, error: unknown): DoomHelpDiagnostic {\n const raw = error instanceof Error ? error.message : String(error);\n const message = (raw || 'Unknown Help activation failure.').slice(0, DOOM_HELP_MAX_DIAGNOSTIC_LENGTH);\n return { source, code, message };\n}\n\nfunction contributionFingerprint(contributions: readonly DoomHelpContribution[]): string {\n return JSON.stringify(\n contributions.map((contribution) => ({\n source: contribution.source,\n moduleUrl: contribution.moduleUrl,\n skills: contribution.skills,\n })),\n );\n}\n\nexport class DefaultHelpActivationService implements HelpActivationService {\n private readonly dependencies: HelpActivationDependencies;\n private readonly listeners = new Set<(state: HelpRuntimeState) => void>();\n private contributions: DoomHelpContribution[] = [];\n private fingerprint = '[]';\n private state: HelpRuntimeState = { activation: 'inactive', skills: [], diagnostics: [] };\n private settledState: HelpRuntimeState = { activation: 'inactive', skills: [], diagnostics: [] };\n private generation = 0;\n private controller: AbortController | undefined;\n private disposed = false;\n\n constructor(dependencies: HelpActivationDependencies) {\n this.dependencies = dependencies;\n }\n\n getState(): HelpRuntimeState {\n return cloneState(this.state);\n }\n\n replaceContributions(contributions: readonly DoomHelpContribution[]): void {\n if (this.disposed) return;\n const next = contributions.map(cloneContribution).sort((left, right) => left.source.localeCompare(right.source));\n const fingerprint = contributionFingerprint(next);\n if (fingerprint === this.fingerprint) return;\n this.contributions = next;\n this.fingerprint = fingerprint;\n if (this.state.activation !== 'inactive') {\n void this.activate().catch((error: unknown) => {\n // Activation failures publish a bounded settled state before rejecting.\n // Only unexpected implementation failures need an out-of-band report.\n if (error instanceof HelpActivationError) return;\n this.dependencies.onBackgroundError(error);\n });\n }\n }\n\n subscribe(listener: (state: HelpRuntimeState) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private publish(state: HelpRuntimeState): HelpRuntimeState {\n this.state = cloneState(state);\n if (state.activation !== 'activating') this.settledState = cloneState(state);\n this.dependencies.publisher.publish(this.state);\n for (const listener of this.listeners) listener(cloneState(this.state));\n return this.getState();\n }\n\n private async loadSources(signal: AbortSignal): Promise<SourceOutcome[]> {\n const outcomes: SourceOutcome[] = Array.from({ length: this.contributions.length });\n let cursor = 0;\n const worker = async (): Promise<void> => {\n while (cursor < this.contributions.length) {\n const index = cursor;\n cursor += 1;\n const contribution = this.contributions[index];\n if (!contribution) return;\n if (signal.aborted) throw new HelpActivationError(CANCELLATION_MESSAGE);\n try {\n const resolved = await this.dependencies.resolver.resolve(contribution, signal);\n const skills = await this.dependencies.materializer.materialize(contribution, resolved, signal);\n outcomes[index] = { source: contribution.source, loaded: { contribution, index: resolved, skills } };\n } catch (error) {\n if (signal.aborted) throw new HelpActivationError(CANCELLATION_MESSAGE);\n outcomes[index] = { source: contribution.source, error };\n }\n }\n };\n const count = Math.min(MAX_RESOLUTION_CONCURRENCY, this.contributions.length);\n await Promise.all(Array.from({ length: count }, () => worker()));\n return outcomes;\n }\n\n async activate(externalSignal?: AbortSignal): Promise<HelpRuntimeState> {\n if (this.disposed) throw new HelpActivationError('Help runtime is disposed.');\n this.controller?.abort('Help activation generation replaced.');\n const controller = new AbortController();\n this.controller = controller;\n const generation = ++this.generation;\n const abortFromExternal = () => controller.abort(externalSignal?.reason);\n externalSignal?.addEventListener('abort', abortFromExternal, { once: true });\n if (externalSignal?.aborted) abortFromExternal();\n\n const settledState = cloneState(this.settledState);\n this.publish({ activation: 'activating', skills: settledState.skills, diagnostics: settledState.diagnostics });\n try {\n const outcomes = await this.loadSources(controller.signal);\n if (controller.signal.aborted || generation !== this.generation) {\n throw new HelpActivationError(CANCELLATION_MESSAGE);\n }\n\n const diagnostics: DoomHelpDiagnostic[] = [];\n const loaded: LoadedSource[] = [];\n let aggregateBytes = 0;\n for (const outcome of outcomes) {\n if (!outcome) continue;\n if (outcome.error || !outcome.loaded) {\n diagnostics.push(diagnostic(outcome.source, 'HELP_SOURCE_FAILED', outcome.error));\n continue;\n }\n if (aggregateBytes + outcome.loaded.index.byteLength > MAX_AGGREGATE_LLMS_BYTES) {\n diagnostics.push(\n diagnostic(outcome.source, 'HELP_AGGREGATE_LIMIT', 'The aggregate llms.txt byte limit was exceeded.'),\n );\n continue;\n }\n aggregateBytes += outcome.loaded.index.byteLength;\n loaded.push(outcome.loaded);\n }\n\n const skills: DoomHelpSkill[] = [];\n const names = new Set<string>();\n for (const source of loaded) {\n for (const skill of source.skills) {\n if (skills.length >= DOOM_HELP_MAX_SKILLS) {\n diagnostics.push(\n diagnostic(source.contribution.source, 'HELP_SKILL_LIMIT', 'The Help skill limit was reached.'),\n );\n break;\n }\n if (names.has(skill.name)) {\n diagnostics.push(\n diagnostic(\n source.contribution.source,\n 'HELP_SKILL_COLLISION',\n `Help skill '${skill.name}' was already provided by an earlier package source.`,\n ),\n );\n continue;\n }\n names.add(skill.name);\n skills.push({ ...skill });\n }\n }\n\n const boundedDiagnostics = diagnostics.slice(0, DOOM_HELP_MAX_DIAGNOSTICS);\n if (skills.length === 0) {\n this.publish({ activation: 'inactive', skills: [], diagnostics: boundedDiagnostics });\n throw new HelpActivationError();\n }\n return this.publish({\n activation: boundedDiagnostics.length > 0 ? 'degraded' : 'active',\n skills,\n diagnostics: boundedDiagnostics,\n });\n } catch (error) {\n if (generation === this.generation && this.state.activation === 'activating') this.publish(settledState);\n throw error;\n } finally {\n externalSignal?.removeEventListener('abort', abortFromExternal);\n if (this.controller === controller) this.controller = undefined;\n }\n }\n\n deactivate(): HelpRuntimeState {\n this.generation += 1;\n this.controller?.abort('Help deactivated.');\n this.controller = undefined;\n return this.publish({ activation: 'inactive', skills: [], diagnostics: [] });\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.deactivate();\n this.disposed = true;\n this.listeners.clear();\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=1048576,t=/!?\[[^\]]*\]\(\s*<?([^\s)>]+)>?(?:\s+[^)]*)?\)/gu,n=/^\s{0,3}\[[^\]\r\n]+\]:\s*<?([^\s>]+)>?/gmu,r=/<((?:\.{0,2}\/|[A-Za-z][A-Za-z0-9+.-]*:)[^<>\s]+)>/gu,i=/\b(?:href|src)\s*=\s*["']([^"']+)["']/giu,a=/^[a-z][a-z0-9+.-]*:/iu,o=/%(?:25|2e|2f|3a|5c)/iu,s=new Set([`http:`,`https:`,`mailto:`]);function c(e){if(a.test(e))return e.slice(0,e.indexOf(`:`)+1).toLowerCase()}function l(e){let t=e;try{for(let e=0;e<2;e+=1){let e=decodeURIComponent(t);if(e===t)break;t=e}}catch{throw Error(`llms.txt contains an invalid encoded link '${e}'.`)}if(o.test(t))throw Error(`llms.txt contains an unsafe nested encoding in link '${e}'.`);return t}function u(e){if(!e||e.startsWith(`#`))return;let t=c(e);if(t){if(!s.has(t))throw Error(`llms.txt contains unsupported link scheme '${t}'.`);return}let n=l(e),r=c(n);if(r){if(!s.has(r))throw Error(`llms.txt contains unsupported link scheme '${r}'.`);return}let i=n.split(/[?#]/u,1)[0]?.replaceAll(`\\`,`/`)??``;if(i.startsWith(`/`)||i.split(`/`).some(e=>e===`..`))throw Error(`llms.txt link '${e}' escapes the package root.`)}function d(e){for(let t of e){let e=t.codePointAt(0)??0;if(e>=0&&e<=8||e===11||e===12||e>=14&&e<=31||e===127)return!0}return!1}function f(a){if(a.byteLength===0)throw Error(`llms.txt is empty.`);if(a.byteLength>1048576)throw Error(`llms.txt exceeds ${e} bytes.`);let o;try{o=new TextDecoder(`utf-8`,{fatal:!0}).decode(a)}catch{throw Error(`llms.txt is not valid UTF-8.`)}if(o.startsWith(``)&&(o=o.slice(1)),d(o))throw Error(`llms.txt contains unsafe control bytes.`);let s=o.split(/\r?\n/u).find(e=>e.trim().length>0)?.trim();if(!s||!/^#\s+\S/u.test(s))throw Error(`llms.txt must begin with a Markdown H1 heading.`);for(let e of[t,n,r,i])for(let t of o.matchAll(e))u(t[1]??``);return o}function p(e,t){return`---\nname: ${JSON.stringify(e.name)}\ndescription: ${JSON.stringify(e.description)}\n---\n\n# Package Help\n\nRead the validated package Help index at ${JSON.stringify(t.filePath)}.\nResolve relative links in that index against ${JSON.stringify(t.referenceBase)}.\nOpen only the linked documents relevant to the current request, as needed; do not recursively load the whole reference set.\n`}exports.MAX_AGGREGATE_LLMS_BYTES=4194304,exports.MAX_LLMS_BYTES=e,exports.renderHelpSkillWrapper=p,exports.validateLlmsBytes=f;
2
+ //# sourceMappingURL=llmsContent.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llmsContent.cjs","names":[],"sources":["../../src/services/llmsContent.ts"],"sourcesContent":["import type { DoomHelpSkillDescriptor } from '@agimon-ai/doompi-extension-contracts/help';\nimport type { ResolvedHelpIndex } from '../types/help.ts';\n\nexport const MAX_LLMS_BYTES = 1024 * 1024;\nexport const MAX_AGGREGATE_LLMS_BYTES = 4 * MAX_LLMS_BYTES;\n\nconst MARKDOWN_LINK_PATTERN = /!?\\[[^\\]]*\\]\\(\\s*<?([^\\s)>]+)>?(?:\\s+[^)]*)?\\)/gu;\nconst MARKDOWN_REFERENCE_LINK_PATTERN = /^\\s{0,3}\\[[^\\]\\r\\n]+\\]:\\s*<?([^\\s>]+)>?/gmu;\nconst MARKDOWN_AUTOLINK_PATTERN = /<((?:\\.{0,2}\\/|[A-Za-z][A-Za-z0-9+.-]*:)[^<>\\s]+)>/gu;\nconst HTML_LINK_PATTERN = /\\b(?:href|src)\\s*=\\s*[\"']([^\"']+)[\"']/giu;\nconst URI_SCHEME_PATTERN = /^[a-z][a-z0-9+.-]*:/iu;\nconst NESTED_PATH_ENCODING_PATTERN = /%(?:25|2e|2f|3a|5c)/iu;\nconst SAFE_EXTERNAL_SCHEMES = new Set(['http:', 'https:', 'mailto:']);\n\nfunction externalScheme(target: string): string | undefined {\n if (!URI_SCHEME_PATTERN.test(target)) return undefined;\n return target.slice(0, target.indexOf(':') + 1).toLowerCase();\n}\n\nfunction decodeRelativeTarget(rawTarget: string): string {\n let decoded = rawTarget;\n try {\n for (let pass = 0; pass < 2; pass += 1) {\n const next = decodeURIComponent(decoded);\n if (next === decoded) break;\n decoded = next;\n }\n } catch {\n throw new Error(`llms.txt contains an invalid encoded link '${rawTarget}'.`);\n }\n if (NESTED_PATH_ENCODING_PATTERN.test(decoded)) {\n throw new Error(`llms.txt contains an unsafe nested encoding in link '${rawTarget}'.`);\n }\n return decoded;\n}\n\nfunction validateRelativeLink(rawTarget: string): void {\n if (!rawTarget || rawTarget.startsWith('#')) return;\n const rawScheme = externalScheme(rawTarget);\n if (rawScheme) {\n if (!SAFE_EXTERNAL_SCHEMES.has(rawScheme)) {\n throw new Error(`llms.txt contains unsupported link scheme '${rawScheme}'.`);\n }\n return;\n }\n\n const decoded = decodeRelativeTarget(rawTarget);\n const decodedScheme = externalScheme(decoded);\n if (decodedScheme) {\n if (!SAFE_EXTERNAL_SCHEMES.has(decodedScheme)) {\n throw new Error(`llms.txt contains unsupported link scheme '${decodedScheme}'.`);\n }\n return;\n }\n const withoutSuffix = decoded.split(/[?#]/u, 1)[0]?.replaceAll('\\\\', '/') ?? '';\n if (withoutSuffix.startsWith('/') || withoutSuffix.split('/').some((segment) => segment === '..')) {\n throw new Error(`llms.txt link '${rawTarget}' escapes the package root.`);\n }\n}\n\nfunction containsUnsafeControl(text: string): boolean {\n for (const character of text) {\n const code = character.codePointAt(0) ?? 0;\n if ((code >= 0 && code <= 8) || code === 11 || code === 12 || (code >= 14 && code <= 31) || code === 127) {\n return true;\n }\n }\n return false;\n}\n\nexport function validateLlmsBytes(bytes: Uint8Array): string {\n if (bytes.byteLength === 0) throw new Error('llms.txt is empty.');\n if (bytes.byteLength > MAX_LLMS_BYTES) throw new Error(`llms.txt exceeds ${MAX_LLMS_BYTES} bytes.`);\n\n let text: string;\n try {\n text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch {\n throw new Error('llms.txt is not valid UTF-8.');\n }\n if (text.startsWith('\\uFEFF')) text = text.slice(1);\n if (containsUnsafeControl(text)) throw new Error('llms.txt contains unsafe control bytes.');\n\n const firstContentLine = text\n .split(/\\r?\\n/u)\n .find((line) => line.trim().length > 0)\n ?.trim();\n if (!firstContentLine || !/^#\\s+\\S/u.test(firstContentLine)) {\n throw new Error('llms.txt must begin with a Markdown H1 heading.');\n }\n for (const pattern of [\n MARKDOWN_LINK_PATTERN,\n MARKDOWN_REFERENCE_LINK_PATTERN,\n MARKDOWN_AUTOLINK_PATTERN,\n HTML_LINK_PATTERN,\n ]) {\n for (const match of text.matchAll(pattern)) validateRelativeLink(match[1] ?? '');\n }\n return text;\n}\n\nexport function renderHelpSkillWrapper(descriptor: DoomHelpSkillDescriptor, index: ResolvedHelpIndex): string {\n const name = JSON.stringify(descriptor.name);\n const description = JSON.stringify(descriptor.description);\n const indexPath = JSON.stringify(index.filePath);\n const referenceBase = JSON.stringify(index.referenceBase);\n return `---\\nname: ${name}\\ndescription: ${description}\\n---\\n\\n# Package Help\\n\\nRead the validated package Help index at ${indexPath}.\\nResolve relative links in that index against ${referenceBase}.\\nOpen only the linked documents relevant to the current request, as needed; do not recursively load the whole reference set.\\n`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=1048576,t=4*e,n=/!?\[[^\]]*\]\(\s*<?([^\s)>]+)>?(?:\s+[^)]*)?\)/gu,r=/^\s{0,3}\[[^\]\r\n]+\]:\s*<?([^\s>]+)>?/gmu,i=/<((?:\.{0,2}\/|[A-Za-z][A-Za-z0-9+.-]*:)[^<>\s]+)>/gu,a=/\b(?:href|src)\s*=\s*["']([^"']+)["']/giu,o=/^[a-z][a-z0-9+.-]*:/iu,s=/%(?:25|2e|2f|3a|5c)/iu,c=new Set([`http:`,`https:`,`mailto:`]);function l(e){if(o.test(e))return e.slice(0,e.indexOf(`:`)+1).toLowerCase()}function u(e){let t=e;try{for(let e=0;e<2;e+=1){let e=decodeURIComponent(t);if(e===t)break;t=e}}catch{throw Error(`llms.txt contains an invalid encoded link '${e}'.`)}if(s.test(t))throw Error(`llms.txt contains an unsafe nested encoding in link '${e}'.`);return t}function d(e){if(!e||e.startsWith(`#`))return;let t=l(e);if(t){if(!c.has(t))throw Error(`llms.txt contains unsupported link scheme '${t}'.`);return}let n=u(e),r=l(n);if(r){if(!c.has(r))throw Error(`llms.txt contains unsupported link scheme '${r}'.`);return}let i=n.split(/[?#]/u,1)[0]?.replaceAll(`\\`,`/`)??``;if(i.startsWith(`/`)||i.split(`/`).some(e=>e===`..`))throw Error(`llms.txt link '${e}' escapes the package root.`)}function f(e){for(let t of e){let e=t.codePointAt(0)??0;if(e>=0&&e<=8||e===11||e===12||e>=14&&e<=31||e===127)return!0}return!1}function p(t){if(t.byteLength===0)throw Error(`llms.txt is empty.`);if(t.byteLength>1048576)throw Error(`llms.txt exceeds ${e} bytes.`);let o;try{o=new TextDecoder(`utf-8`,{fatal:!0}).decode(t)}catch{throw Error(`llms.txt is not valid UTF-8.`)}if(o.startsWith(``)&&(o=o.slice(1)),f(o))throw Error(`llms.txt contains unsafe control bytes.`);let s=o.split(/\r?\n/u).find(e=>e.trim().length>0)?.trim();if(!s||!/^#\s+\S/u.test(s))throw Error(`llms.txt must begin with a Markdown H1 heading.`);for(let e of[n,r,i,a])for(let t of o.matchAll(e))d(t[1]??``);return o}function m(e,t){return`---\nname: ${JSON.stringify(e.name)}\ndescription: ${JSON.stringify(e.description)}\n---\n\n# Package Help\n\nRead the validated package Help index at ${JSON.stringify(t.filePath)}.\nResolve relative links in that index against ${JSON.stringify(t.referenceBase)}.\nOpen only the linked documents relevant to the current request, as needed; do not recursively load the whole reference set.\n`}export{t as MAX_AGGREGATE_LLMS_BYTES,e as MAX_LLMS_BYTES,m as renderHelpSkillWrapper,p as validateLlmsBytes};
2
+ //# sourceMappingURL=llmsContent.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llmsContent.mjs","names":[],"sources":["../../src/services/llmsContent.ts"],"sourcesContent":["import type { DoomHelpSkillDescriptor } from '@agimon-ai/doompi-extension-contracts/help';\nimport type { ResolvedHelpIndex } from '../types/help.ts';\n\nexport const MAX_LLMS_BYTES = 1024 * 1024;\nexport const MAX_AGGREGATE_LLMS_BYTES = 4 * MAX_LLMS_BYTES;\n\nconst MARKDOWN_LINK_PATTERN = /!?\\[[^\\]]*\\]\\(\\s*<?([^\\s)>]+)>?(?:\\s+[^)]*)?\\)/gu;\nconst MARKDOWN_REFERENCE_LINK_PATTERN = /^\\s{0,3}\\[[^\\]\\r\\n]+\\]:\\s*<?([^\\s>]+)>?/gmu;\nconst MARKDOWN_AUTOLINK_PATTERN = /<((?:\\.{0,2}\\/|[A-Za-z][A-Za-z0-9+.-]*:)[^<>\\s]+)>/gu;\nconst HTML_LINK_PATTERN = /\\b(?:href|src)\\s*=\\s*[\"']([^\"']+)[\"']/giu;\nconst URI_SCHEME_PATTERN = /^[a-z][a-z0-9+.-]*:/iu;\nconst NESTED_PATH_ENCODING_PATTERN = /%(?:25|2e|2f|3a|5c)/iu;\nconst SAFE_EXTERNAL_SCHEMES = new Set(['http:', 'https:', 'mailto:']);\n\nfunction externalScheme(target: string): string | undefined {\n if (!URI_SCHEME_PATTERN.test(target)) return undefined;\n return target.slice(0, target.indexOf(':') + 1).toLowerCase();\n}\n\nfunction decodeRelativeTarget(rawTarget: string): string {\n let decoded = rawTarget;\n try {\n for (let pass = 0; pass < 2; pass += 1) {\n const next = decodeURIComponent(decoded);\n if (next === decoded) break;\n decoded = next;\n }\n } catch {\n throw new Error(`llms.txt contains an invalid encoded link '${rawTarget}'.`);\n }\n if (NESTED_PATH_ENCODING_PATTERN.test(decoded)) {\n throw new Error(`llms.txt contains an unsafe nested encoding in link '${rawTarget}'.`);\n }\n return decoded;\n}\n\nfunction validateRelativeLink(rawTarget: string): void {\n if (!rawTarget || rawTarget.startsWith('#')) return;\n const rawScheme = externalScheme(rawTarget);\n if (rawScheme) {\n if (!SAFE_EXTERNAL_SCHEMES.has(rawScheme)) {\n throw new Error(`llms.txt contains unsupported link scheme '${rawScheme}'.`);\n }\n return;\n }\n\n const decoded = decodeRelativeTarget(rawTarget);\n const decodedScheme = externalScheme(decoded);\n if (decodedScheme) {\n if (!SAFE_EXTERNAL_SCHEMES.has(decodedScheme)) {\n throw new Error(`llms.txt contains unsupported link scheme '${decodedScheme}'.`);\n }\n return;\n }\n const withoutSuffix = decoded.split(/[?#]/u, 1)[0]?.replaceAll('\\\\', '/') ?? '';\n if (withoutSuffix.startsWith('/') || withoutSuffix.split('/').some((segment) => segment === '..')) {\n throw new Error(`llms.txt link '${rawTarget}' escapes the package root.`);\n }\n}\n\nfunction containsUnsafeControl(text: string): boolean {\n for (const character of text) {\n const code = character.codePointAt(0) ?? 0;\n if ((code >= 0 && code <= 8) || code === 11 || code === 12 || (code >= 14 && code <= 31) || code === 127) {\n return true;\n }\n }\n return false;\n}\n\nexport function validateLlmsBytes(bytes: Uint8Array): string {\n if (bytes.byteLength === 0) throw new Error('llms.txt is empty.');\n if (bytes.byteLength > MAX_LLMS_BYTES) throw new Error(`llms.txt exceeds ${MAX_LLMS_BYTES} bytes.`);\n\n let text: string;\n try {\n text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch {\n throw new Error('llms.txt is not valid UTF-8.');\n }\n if (text.startsWith('\\uFEFF')) text = text.slice(1);\n if (containsUnsafeControl(text)) throw new Error('llms.txt contains unsafe control bytes.');\n\n const firstContentLine = text\n .split(/\\r?\\n/u)\n .find((line) => line.trim().length > 0)\n ?.trim();\n if (!firstContentLine || !/^#\\s+\\S/u.test(firstContentLine)) {\n throw new Error('llms.txt must begin with a Markdown H1 heading.');\n }\n for (const pattern of [\n MARKDOWN_LINK_PATTERN,\n MARKDOWN_REFERENCE_LINK_PATTERN,\n MARKDOWN_AUTOLINK_PATTERN,\n HTML_LINK_PATTERN,\n ]) {\n for (const match of text.matchAll(pattern)) validateRelativeLink(match[1] ?? '');\n }\n return text;\n}\n\nexport function renderHelpSkillWrapper(descriptor: DoomHelpSkillDescriptor, index: ResolvedHelpIndex): string {\n const name = JSON.stringify(descriptor.name);\n const description = JSON.stringify(descriptor.description);\n const indexPath = JSON.stringify(index.filePath);\n const referenceBase = JSON.stringify(index.referenceBase);\n return `---\\nname: ${name}\\ndescription: ${description}\\n---\\n\\n# Package Help\\n\\nRead the validated package Help index at ${indexPath}.\\nResolve relative links in that index against ${referenceBase}.\\nOpen only the linked documents relevant to the current request, as needed; do not recursively load the whole reference set.\\n`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import "@agimon-ai/doompi-extension-contracts/help";
2
+ //#region src/types/help.d.ts
3
+ interface HelpFetchResponse {
4
+ ok: boolean;
5
+ status: number;
6
+ headers: {
7
+ get(name: string): string | null;
8
+ };
9
+ text(): Promise<string>;
10
+ arrayBuffer(): Promise<ArrayBuffer>;
11
+ }
12
+ type HelpFetch = (input: string, init: {
13
+ signal: AbortSignal;
14
+ redirect: 'manual';
15
+ }) => Promise<HelpFetchResponse>;
16
+ //#endregion
17
+ export { HelpFetch, HelpFetchResponse };
18
+ //# sourceMappingURL=help.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.d.cts","names":[],"sources":["../../src/types/help.ts"],"mappings":";;UA+DiB;EACf;EACA;EACA;IAAW,IAAI;;EACf,QAAQ;EACR,eAAe,QAAQ;;KAGb,aACV,eACA;EAAQ,QAAQ;EAAa;MAC1B,QAAQ"}
@@ -0,0 +1,18 @@
1
+ import "@agimon-ai/doompi-extension-contracts/help";
2
+ //#region src/types/help.d.ts
3
+ interface HelpFetchResponse {
4
+ ok: boolean;
5
+ status: number;
6
+ headers: {
7
+ get(name: string): string | null;
8
+ };
9
+ text(): Promise<string>;
10
+ arrayBuffer(): Promise<ArrayBuffer>;
11
+ }
12
+ type HelpFetch = (input: string, init: {
13
+ signal: AbortSignal;
14
+ redirect: 'manual';
15
+ }) => Promise<HelpFetchResponse>;
16
+ //#endregion
17
+ export { HelpFetch, HelpFetchResponse };
18
+ //# sourceMappingURL=help.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.d.mts","names":[],"sources":["../../src/types/help.ts"],"mappings":";;UA+DiB;EACf;EACA;EACA;IAAW,IAAI;;EACf,QAAQ;EACR,eAAe,QAAQ;;KAGb,aACV,eACA;EAAQ,QAAQ;EAAa;MAC1B,QAAQ"}
package/llms.txt ADDED
@@ -0,0 +1,7 @@
1
+ # Doom Pi Help
2
+
3
+ Activation-gated, package-owned guidance for Doom Pi parent sessions.
4
+
5
+ ## Resources
6
+
7
+ - [Package README](./README.md): Public entrypoints, activation model, security guarantees, and development commands.
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@agimon-ai/doompi-help",
3
+ "version": "0.0.1-alpha.0",
4
+ "description": "Activation-gated package guidance for DoomPi",
5
+ "keywords": [
6
+ "ai",
7
+ "coding-agent",
8
+ "developer-tools",
9
+ "doompi",
10
+ "pi-extension",
11
+ "pi-package",
12
+ "typescript"
13
+ ],
14
+ "homepage": "https://agimon.ai",
15
+ "license": "MIT",
16
+ "author": "Vuong Ngo",
17
+ "files": [
18
+ "dist",
19
+ "llms.txt",
20
+ "README.md",
21
+ "LICENSE",
22
+ "package.json"
23
+ ],
24
+ "type": "module",
25
+ "main": "./dist/index.cjs",
26
+ "types": "./dist/index.d.mts",
27
+ "jsnext:main": "./dist/index.mjs",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.mts",
31
+ "import": "./dist/index.mjs",
32
+ "require": "./dist/index.cjs"
33
+ },
34
+ "./extensions/doom": {
35
+ "types": "./dist/extensions/doom.d.mts",
36
+ "import": "./dist/extensions/doom.mjs",
37
+ "require": "./dist/extensions/doom.cjs"
38
+ },
39
+ "./package.json": "./package.json"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "dependencies": {
45
+ "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.17"
46
+ },
47
+ "devDependencies": {
48
+ "@earendil-works/pi-coding-agent": "0.84.2",
49
+ "@types/node": "26.1.1",
50
+ "@vitest/coverage-v8": "4.1.10",
51
+ "tsdown": "0.22.14",
52
+ "typescript": "6.0.3",
53
+ "vitest": "4.1.10",
54
+ "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.17"
55
+ },
56
+ "peerDependencies": {
57
+ "@earendil-works/pi-coding-agent": "0.84.2"
58
+ },
59
+ "peerDependenciesMeta": {
60
+ "@earendil-works/pi-coding-agent": {
61
+ "optional": true
62
+ }
63
+ },
64
+ "engines": {
65
+ "node": ">=22.19.0"
66
+ },
67
+ "pi": {
68
+ "extensions": [
69
+ "./dist/extensions/doom.mjs"
70
+ ]
71
+ },
72
+ "scripts": {
73
+ "build": "tsdown",
74
+ "test": "vitest --run",
75
+ "typecheck": "tsc --noEmit",
76
+ "lint": "oxlint . && oxfmt . --check",
77
+ "fixcode": "oxlint . --fix && oxfmt ."
78
+ }
79
+ }