pi2dsh 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/dist/analyzer-CKTsWVzn.mjs +628 -0
- package/dist/analyzer-CKTsWVzn.mjs.map +1 -0
- package/dist/cli.mjs +3 -1
- package/dist/cli.mjs.map +1 -1
- package/dist/compat/pi-ai.d.mts +1 -11
- package/dist/compat/pi-ai.d.mts.map +1 -1
- package/dist/compat/pi-ai.mjs +2 -2
- package/dist/credentials-oauth.mjs +1 -1
- package/dist/generator-eyViezvs.mjs +300 -0
- package/dist/generator-eyViezvs.mjs.map +1 -0
- package/dist/host.d.mts +2 -0
- package/dist/host.d.mts.map +1 -1
- package/dist/host.mjs +2 -1
- package/dist/host.mjs.map +1 -1
- package/dist/index.d.mts +28 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +27 -4
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-config-Dlou-ZA-.mjs +707 -0
- package/dist/mcp-config-Dlou-ZA-.mjs.map +1 -0
- package/dist/{pi-ai-B4hucafU.mjs → pi-ai-C6Xag6xt.mjs} +2 -74
- package/dist/pi-ai-C6Xag6xt.mjs.map +1 -0
- package/dist/{runtime-k3IlCgjQ.mjs → runtime-B-Mun-jX.mjs} +44 -947
- package/dist/runtime-B-Mun-jX.mjs.map +1 -0
- package/dist/runtime.d.mts +11 -6
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/package.json +6 -3
- package/dist/all-BChhwMVE.mjs +0 -28512
- package/dist/all-BChhwMVE.mjs.map +0 -1
- package/dist/anthropic-messages-Dlw4T0S4.mjs +0 -6438
- package/dist/anthropic-messages-Dlw4T0S4.mjs.map +0 -1
- package/dist/azure-openai-responses-vGUNukZ7.mjs +0 -209
- package/dist/azure-openai-responses-vGUNukZ7.mjs.map +0 -1
- package/dist/deferred-tools-BD4g5QUx.mjs +0 -32
- package/dist/deferred-tools-BD4g5QUx.mjs.map +0 -1
- package/dist/diagnostics-CJye1UFh.mjs +0 -99
- package/dist/diagnostics-CJye1UFh.mjs.map +0 -1
- package/dist/dist-DY2GeEQ6.mjs +0 -1089
- package/dist/dist-DY2GeEQ6.mjs.map +0 -1
- package/dist/dist-DYfTHu0C.mjs +0 -1246
- package/dist/dist-DYfTHu0C.mjs.map +0 -1
- package/dist/error-body-DKA3lknR.mjs +0 -104
- package/dist/error-body-DKA3lknR.mjs.map +0 -1
- package/dist/github-copilot-headers-CZo2QHrt.mjs +0 -25
- package/dist/github-copilot-headers-CZo2QHrt.mjs.map +0 -1
- package/dist/google-generative-ai-C30gRjRi.mjs +0 -358
- package/dist/google-generative-ai-C30gRjRi.mjs.map +0 -1
- package/dist/google-shared-W8g3Esep.mjs +0 -29042
- package/dist/google-shared-W8g3Esep.mjs.map +0 -1
- package/dist/google-vertex--O_gyVYA.mjs +0 -402
- package/dist/google-vertex--O_gyVYA.mjs.map +0 -1
- package/dist/hash-Dbggamac.mjs +0 -19
- package/dist/hash-Dbggamac.mjs.map +0 -1
- package/dist/headers-CPzZhJQn.mjs +0 -17
- package/dist/headers-CPzZhJQn.mjs.map +0 -1
- package/dist/images-models-DJtHo9Rp.mjs +0 -1068
- package/dist/images-models-DJtHo9Rp.mjs.map +0 -1
- package/dist/json-parse-C-vG4_qc.mjs +0 -384
- package/dist/json-parse-C-vG4_qc.mjs.map +0 -1
- package/dist/mcp-config-Cful6uUS.mjs +0 -1618
- package/dist/mcp-config-Cful6uUS.mjs.map +0 -1
- package/dist/mistral-conversations-LSDG9sjq.mjs +0 -42007
- package/dist/mistral-conversations-LSDG9sjq.mjs.map +0 -1
- package/dist/multipart-parser-CoM3rwav.mjs +0 -301
- package/dist/multipart-parser-CoM3rwav.mjs.map +0 -1
- package/dist/openai-codex-responses-JxII_OUX.mjs +0 -1169
- package/dist/openai-codex-responses-JxII_OUX.mjs.map +0 -1
- package/dist/openai-completions-Dp-VwLzJ.mjs +0 -947
- package/dist/openai-completions-Dp-VwLzJ.mjs.map +0 -1
- package/dist/openai-completions-lite-BrM7gJzs.mjs +0 -316
- package/dist/openai-completions-lite-BrM7gJzs.mjs.map +0 -1
- package/dist/openai-prompt-cache-BDWtZRKh.mjs +0 -11
- package/dist/openai-prompt-cache-BDWtZRKh.mjs.map +0 -1
- package/dist/openai-responses-CWmNks8K.mjs +0 -247
- package/dist/openai-responses-CWmNks8K.mjs.map +0 -1
- package/dist/openai-responses-shared-CYgIDTf3.mjs +0 -572
- package/dist/openai-responses-shared-CYgIDTf3.mjs.map +0 -1
- package/dist/openrouter-images-DfAULV7l.mjs +0 -127
- package/dist/openrouter-images-DfAULV7l.mjs.map +0 -1
- package/dist/otel-Boafyju5.mjs +0 -24935
- package/dist/otel-Boafyju5.mjs.map +0 -1
- package/dist/pi-ai-B4hucafU.mjs.map +0 -1
- package/dist/pi-messages-HzGtvc5_.mjs +0 -306
- package/dist/pi-messages-HzGtvc5_.mjs.map +0 -1
- package/dist/provider-env-C9gOBFJi.mjs +0 -40
- package/dist/provider-env-C9gOBFJi.mjs.map +0 -1
- package/dist/provider-retry-Cw6YJ4cr.mjs +0 -80
- package/dist/provider-retry-Cw6YJ4cr.mjs.map +0 -1
- package/dist/runtime-k3IlCgjQ.mjs.map +0 -1
- package/dist/sanitize-unicode-wLA11KvZ.mjs +0 -29
- package/dist/sanitize-unicode-wLA11KvZ.mjs.map +0 -1
- package/dist/src-D0GRWCE8.mjs +0 -5031
- package/dist/src-D0GRWCE8.mjs.map +0 -1
- package/dist/transform-messages-DGq9mvhA.mjs +0 -379
- package/dist/transform-messages-DGq9mvhA.mjs.map +0 -1
- package/dist/uuid-DtFT7tOE.mjs +0 -65
- package/dist/uuid-DtFT7tOE.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator-eyViezvs.mjs","names":["parseYaml"],"sources":["../src/generator.ts"],"sourcesContent":["import { cp, lstat, mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises'\nimport { basename, dirname, extname, join, relative, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { parse as parseYaml } from 'yaml'\nimport { analyzePackage } from './analyzer.js'\nimport { collectLocalClosure, runtimeExternalPackages, SCRIPT_EXTENSIONS } from './module-graph.js'\nimport type {\n CompatibilityReport,\n GenerateOptions,\n GeneratedRuntimeManifest,\n ResolvedPiPackage,\n} from './types.js'\n\ninterface PromptMetadata {\n name: string\n description: string\n argumentHint?: string\n path: string\n}\n\nconst SHIMMED_PI_HOST_PACKAGES = new Set([\n '@earendil-works/pi-coding-agent',\n '@mariozechner/pi-coding-agent',\n '@earendil-works/pi-tui',\n '@mariozechner/pi-tui',\n '@earendil-works/pi-ai',\n '@mariozechner/pi-ai',\n // Host-provided in Pi's loader whitelist; the runtime aliases them too.\n 'typebox',\n '@sinclair/typebox',\n])\n\nfunction packageSlug(name: string): string {\n const slug = name.replace(/^@/u, '').replaceAll('/', '-').replace(/[^a-zA-Z0-9._-]+/gu, '-').toLowerCase()\n return slug.replace(/^-+|-+$/gu, '') || 'package'\n}\n\nfunction stringRecord(value: unknown): Record<string, string> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return {}\n return Object.fromEntries(Object.entries(value).filter((entry): entry is [string, string] => typeof entry[1] === 'string'))\n}\n\nasync function assertEmptyOrMissing(path: string): Promise<void> {\n try {\n const info = await stat(path)\n if (!info.isDirectory()) throw new Error(`output exists and is not a directory: ${path}`)\n const entries = await readdir(path)\n if (entries.length > 0) throw new Error(`output directory is not empty: ${path}`)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n}\n\nfunction parseFrontmatter(text: string): { attributes: Record<string, string>; body: string } {\n const normalized = text.replace(/\\r\\n?/gu, '\\n')\n if (!normalized.startsWith('---')) return { attributes: {}, body: normalized }\n const endIndex = normalized.indexOf('\\n---', 3)\n if (endIndex === -1) return { attributes: {}, body: normalized }\n const raw: unknown = parseYaml(normalized.slice(4, endIndex))\n const attributes = typeof raw === 'object' && raw !== null && !Array.isArray(raw)\n ? stringRecord(raw)\n : {}\n return { attributes, body: normalized.slice(endIndex + 4).trim() }\n}\n\nasync function assertNoSymlinks(path: string): Promise<void> {\n const info = await lstat(path)\n if (info.isSymbolicLink()) throw new Error(`refusing to copy symbolic link from Pi package: ${path}`)\n if (!info.isDirectory()) return\n for (const entry of await readdir(path)) await assertNoSymlinks(join(path, entry))\n}\n\nasync function copyExtensions(pkg: ResolvedPiPackage, outDir: string): Promise<{ entries: string[]; runtimePackages: Set<string>; skillScriptPackages: Set<string> }> {\n const copied: string[] = []\n const runtimePackages = new Set<string>()\n const closure = await collectLocalClosure(pkg.rootDir, pkg.resources.extensions)\n // Unresolved references never block the snapshot here: the analyzer grades\n // them (fatal only on the load-time path) and enforceReport is the gate.\n // The copy below preserves the published layout, so lazy dead references\n // behave exactly as they would under Pi.\n for (const issue of closure.issues) {\n console.warn(`pi2dsh: unresolved ${issue.kind} reference ${JSON.stringify(issue.specifier)} from ${relative(pkg.rootDir, issue.file)} (${issue.lazy ? 'lazy path — fails at feature use, as under Pi' : 'load-time path'})`)\n }\n for (const source of closure.files) {\n if (SCRIPT_EXTENSIONS.has(extname(source))) {\n const text = await readFile(source, 'utf8')\n // Lazy undeclared imports stay out of bundle dependencies: the package\n // works without them (Pi semantics) and they may not even be installable.\n // Lazy means the import site OR the whole file only evaluates on demand\n // (a top-level import inside a dynamically-imported module loads lazily).\n const lazyFile = !closure.loadTimeFiles.has(source)\n for (const use of runtimeExternalPackages(source, text)) {\n if ((!use.lazy && !lazyFile) || use.name in stringRecord(pkg.packageJson.dependencies)) runtimePackages.add(use.name)\n }\n }\n const sourceRelative = relative(pkg.rootDir, source).replaceAll('\\\\', '/')\n const targetRelative = `vendor/${sourceRelative}`\n const target = join(outDir, targetRelative)\n await mkdir(dirname(target), { recursive: true })\n await cp(source, target, { dereference: false })\n if (pkg.resources.extensions.map(entry => resolve(entry)).includes(source)) copied.push(targetRelative)\n }\n // Skill helper scripts run on the user's explicit request, not at extension\n // load; their imports (often themselves try/catch-guarded) are informational,\n // never a conversion blocker (mitsupi ships googleapis-using skill scripts\n // this way and works fine in Pi).\n const skillScriptPackages = new Set<string>()\n for (const source of pkg.resources.skills) {\n if (!SCRIPT_EXTENSIONS.has(extname(source))) continue\n const text = await readFile(source, 'utf8')\n for (const use of runtimeExternalPackages(source, text)) skillScriptPackages.add(use.name)\n }\n return { entries: copied, runtimePackages, skillScriptPackages }\n}\n\nasync function copySkills(pkg: ResolvedPiPackage, outDir: string): Promise<string[]> {\n const entryFiles = pkg.resources.skills.filter(file => basename(file) === 'SKILL.md' || file.endsWith('.md'))\n if (entryFiles.length === 0) return []\n const names = new Set<string>()\n for (const entry of entryFiles) {\n const isBundle = basename(entry) === 'SKILL.md'\n let name = isBundle ? basename(dirname(entry)) : basename(entry, '.md')\n if (names.has(name)) {\n // Same-named skills under different parents (piolium ships several):\n // disambiguate with the parent directory instead of refusing the package.\n const parent = basename(dirname(isBundle ? dirname(entry) : entry))\n const candidate = `${parent}-${name}`.replace(/[^a-zA-Z0-9._-]+/gu, '-')\n name = names.has(candidate) ? `${candidate}-${names.size}` : candidate\n }\n names.add(name)\n const target = join(outDir, 'skills', isBundle ? name : `${name}.md`)\n await mkdir(dirname(target), { recursive: true })\n const source = isBundle ? dirname(entry) : entry\n await assertNoSymlinks(source)\n await cp(source, target, { recursive: isBundle, dereference: false })\n }\n return ['skills']\n}\n\nasync function copyPrompts(pkg: ResolvedPiPackage, outDir: string): Promise<PromptMetadata[]> {\n const prompts: PromptMetadata[] = []\n const names = new Set<string>()\n for (const source of pkg.resources.prompts) {\n const name = basename(source, '.md').toLowerCase().replace(/[^a-z0-9_-]+/gu, '-')\n if (names.has(name)) throw new Error(`prompt command name collision while flattening Pi package: ${name}`)\n names.add(name)\n const targetRelative = `prompts/${name}.md`\n const target = join(outDir, targetRelative)\n await mkdir(dirname(target), { recursive: true })\n await assertNoSymlinks(source)\n await cp(source, target, { dereference: false })\n const { attributes, body } = parseFrontmatter(await readFile(source, 'utf8'))\n const firstLine = body.split(/\\r?\\n/u).map(line => line.trim()).find(Boolean)\n prompts.push({\n name,\n description: attributes.description ?? firstLine ?? `Run migrated Pi prompt ${name}`,\n ...(attributes['argument-hint'] !== undefined ? { argumentHint: attributes['argument-hint'] } : {}),\n path: targetRelative,\n })\n }\n return prompts\n}\n\nasync function copyNotices(pkg: ResolvedPiPackage, outDir: string): Promise<string[]> {\n const copied: string[] = []\n for (const entry of await readdir(pkg.rootDir)) {\n if (!/^(?:licen[cs]e|notice|copying)(?:[._-].*)?$/iu.test(entry)) continue\n const source = join(pkg.rootDir, entry)\n const info = await lstat(source)\n if (info.isSymbolicLink()) throw new Error(`refusing to copy symbolic link from Pi package: ${source}`)\n if (!info.isFile()) continue\n await cp(source, join(outDir, entry), { dereference: false })\n copied.push(entry)\n }\n return copied.sort()\n}\n\nfunction generatedPackageJson(\n pkg: ResolvedPiPackage,\n generatedName: string,\n runtimeSpec: string | undefined,\n runtimePackages: ReadonlySet<string>,\n hasSkills: boolean,\n): Record<string, unknown> {\n const declaredDependencies = {\n ...stringRecord(pkg.packageJson.dependencies),\n ...stringRecord(pkg.packageJson.optionalDependencies),\n ...stringRecord(pkg.packageJson.peerDependencies),\n }\n const externalRuntimePackages = [...runtimePackages].filter(name => !SHIMMED_PI_HOST_PACKAGES.has(name))\n const missing = externalRuntimePackages.filter(name => declaredDependencies[name] === undefined)\n if (missing.length > 0) {\n throw new Error(`runtime dependencies are imported but not declared by the Pi package: ${missing.join(', ')}`)\n }\n // Carry EVERY declared runtime dependency, not only statically detected\n // imports: packages load their own deps dynamically (computed require,\n // optional native backends) and the original manifest is the authority on\n // what they need.\n const declaredRuntime = {\n ...stringRecord(pkg.packageJson.dependencies),\n ...stringRecord(pkg.packageJson.optionalDependencies),\n }\n const dependencies = {\n ...Object.fromEntries(Object.entries(declaredRuntime).filter(([name]) => !SHIMMED_PI_HOST_PACKAGES.has(name))),\n ...Object.fromEntries(externalRuntimePackages.sort().map(name => [name, declaredDependencies[name]])),\n // The embedded runtime's own runtime dependencies (vendored Pi width math\n // uses get-east-asian-width; the pi-tui shim re-exports marked; typebox is\n // the host-provided schema library Pi's loader gives every extension;\n // vendored Pi bash tooling spawns through cross-spawn exactly as Pi does).\n ...(runtimeSpec === undefined\n ? { jiti: '^2.7.0', 'get-east-asian-width': '^1.6.0', marked: '^16.4.1', typebox: '^1.0.4', 'cross-spawn': '^7.0.6', diff: '^9.0.0' }\n : {}),\n // The bridge's own openai-completions client (openai SDK) backs the\n // single model directory's most common wire protocol; the rarer apis\n // lazily use a real pi-ai when a mounted package's dependency tree\n // carries one. Depending on pi-ai here would drag @google/genai →\n // protobufjs, whose blocked install script fails `dsh plugin add`\n // for transitive dependencies.\n openai: '^6.40.0',\n ...(hasSkills ? { '@deepseek-ai/dsh-skill-filesystem': '^0.1.0-rc.6' } : {}),\n ...(runtimeSpec !== undefined ? { pi2dsh: runtimeSpec } : {}),\n }\n // Re-point the package's Node subpath-imports map (\"#x\": \"./src/x.js\") at\n // the vendored snapshot so '#'-imports keep resolving inside the bundle.\n const remapImports = (value: unknown): unknown => {\n if (typeof value === 'string') return value.startsWith('./') ? `./vendor/${value.slice(2)}` : value\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, remapImports(entry)]))\n }\n return value\n }\n const sourceImports = pkg.packageJson.imports\n return {\n name: generatedName,\n version: pkg.identity.version,\n description: `DeepSeek Harness adapter generated from ${pkg.identity.name}`,\n type: 'module',\n main: './index.js',\n ...(typeof sourceImports === 'object' && sourceImports !== null\n ? { imports: remapImports(sourceImports) as Record<string, unknown> }\n : {}),\n files: ['index.js', 'cordis.patch.yml', 'pi2dsh.manifest.json', 'pi2dsh.report.json', 'README.md', 'LICENSE*', 'NOTICE*', 'COPYING*', 'PI2DSH-LICENSE', 'runtime', 'vendor', 'skills', 'prompts'],\n dependencies,\n ...(runtimeSpec === undefined\n ? {\n peerDependencies: {\n '@deepseek-ai/dsh-llm': '^0.1.0-rc.6',\n '@deepseek-ai/dsh-system-prompt': '^0.1.0-rc.6',\n },\n }\n : {}),\n keywords: ['dsh-plugin', 'deepseek-harness', 'pi-package', 'pi2dsh'],\n license: typeof pkg.packageJson.license === 'string' ? pkg.packageJson.license : 'UNLICENSED',\n dsh: { bundle: { patch: './cordis.patch.yml' } },\n }\n}\n\nfunction generatedReadme(pkg: ResolvedPiPackage, packageName: string, report: CompatibilityReport): string {\n return `# ${packageName}\\n\\n`\n + `Generated by [pi2dsh](https://github.com/weijiafu14/pi2dsh) from \\`${pkg.identity.name}@${pkg.identity.version}\\`.\\n\\n`\n + `Compatibility verdict: **${report.verdict}** (full ${report.summary.full}, partial ${report.summary.partial}, unsupported ${report.summary.unsupported}).\\n\\n`\n + `Review \\`pi2dsh.report.json\\` before installation. This bundle executes the original Pi extension source and should only be installed when that source is trusted.\\n\\n`\n + `Install with DeepSeek Harness (keep the \\`file:\\` prefix so pnpm installs this bundle's dependencies instead of creating a bare link):\\n\\n`\n + `\\`\\`\\`sh\\ndsh plugin --profile headless add file:$PWD\\ndsh --profile headless --dump-config\\n\\`\\`\\`\\n\\n`\n + `If the install stops with \\`ERR_PNPM_IGNORED_BUILDS\\` (pnpm 10+ blocks dependency build scripts by default), approve the listed packages — either run \\`pnpm approve-builds\\` inside the profile directory, or set them to \\`true\\` under \\`allowBuilds\\` in the profile's \\`pnpm-workspace.yaml\\` — then re-run the add command.\\n`\n}\n\nfunction pluginSource(manifest: GeneratedRuntimeManifest, runtimeImport: string): string {\n const injections = ['tools', 'systemPrompt']\n if (manifest.prompts.length > 0 || manifest.report?.findings.some(item => item.capability === 'registerCommand') === true) {\n injections.push('commands')\n }\n if (manifest.skillDirs.length > 0) injections.push('skills')\n return `import { applyPiPackage } from ${JSON.stringify(runtimeImport)}\\n\\n`\n + `export const name = ${JSON.stringify(`pi2dsh:${packageSlug(manifest.package.name)}`)}\\n`\n + `export const inject = ${JSON.stringify(injections)}\\n\\n`\n + `const manifest = ${JSON.stringify(manifest, null, 2)}\\n\\n`\n + `export async function apply(ctx, config = {}) {\\n`\n + ` await applyPiPackage(ctx, { rootUrl: new URL('.', import.meta.url), manifest, config })\\n`\n + `}\\n`\n}\n\nasync function firstExisting(paths: string[]): Promise<string> {\n for (const path of paths) {\n try {\n await stat(path)\n return path\n } catch {\n // Try the next package/source layout.\n }\n }\n throw new Error(`cannot locate pi2dsh runtime artifact; tried: ${paths.join(', ')}`)\n}\n\nasync function copyEmbeddedRuntime(outDir: string): Promise<void> {\n const moduleDir = dirname(fileURLToPath(import.meta.url))\n const runtimeSource = await firstExisting([\n join(moduleDir, 'runtime.mjs'),\n join(moduleDir, '../dist/runtime.mjs'),\n ])\n const runtimeRoot = dirname(runtimeSource)\n const targetRoot = join(outDir, 'runtime')\n await mkdir(targetRoot, { recursive: true })\n // Copy every emitted module, including bundler-named shared chunks — a\n // fixed file list silently breaks whenever the bundler re-splits chunks.\n for (const entry of await readdir(runtimeRoot)) {\n if (entry.endsWith('.mjs')) await cp(join(runtimeRoot, entry), join(targetRoot, entry))\n }\n for (const sub of ['compat', join('compat', 'vendor')]) {\n const sourceDir = join(runtimeRoot, sub)\n try {\n const entries = await readdir(sourceDir)\n await mkdir(join(targetRoot, sub), { recursive: true })\n for (const entry of entries) {\n if (entry.endsWith('.mjs')) await cp(join(sourceDir, entry), join(targetRoot, sub, entry))\n }\n } catch {\n // dist layout without that subdirectory\n }\n }\n await cp(join(targetRoot, 'runtime.mjs'), join(targetRoot, 'pi2dsh-runtime.mjs'))\n const license = await firstExisting([join(moduleDir, '../LICENSE'), join(moduleDir, '../../LICENSE')])\n await cp(license, join(outDir, 'PI2DSH-LICENSE'))\n}\n\nfunction patchSource(generatedName: string, slug: string): string {\n return `- insert:\\n - id: pi2dsh-${slug}\\n name: ${JSON.stringify(generatedName)}\\n`\n}\n\nfunction enforceReport(report: CompatibilityReport, options: GenerateOptions): void {\n // Fatal findings (incomplete module closure, undeclared runtime deps,\n // resource escapes) mean the bundle cannot be built or trusted; no flag\n // bypasses them. Unsupported findings are explicit, load-safe degradations\n // — the bundle installs and the black-box run decides real usability.\n if (report.summary.fatal > 0) {\n throw new Error(\n `conversion blocked: ${report.summary.fatal} fatal finding(s) — the bundle cannot be built or trusted; run inspect for details`,\n )\n }\n if (options.strict && (report.summary.partial > 0 || report.summary.unsupported > 0)) {\n throw new Error('strict conversion requires every detected Pi API use to have full compatibility')\n }\n}\n\nexport async function generateBundle(\n pkg: ResolvedPiPackage,\n options: GenerateOptions,\n): Promise<{ outDir: string; report: CompatibilityReport; packageName: string }> {\n const outDir = resolve(options.outDir)\n const report = await analyzePackage(pkg)\n enforceReport(report, options)\n await assertEmptyOrMissing(outDir)\n await mkdir(outDir, { recursive: true })\n\n const slug = packageSlug(pkg.identity.name)\n const packageName = `dsh-pi-${slug}`\n const extensionSnapshot = await copyExtensions(pkg, outDir)\n const skillDirs = await copySkills(pkg, outDir)\n const prompts = await copyPrompts(pkg, outDir)\n await copyNotices(pkg, outDir)\n const manifest: GeneratedRuntimeManifest = {\n schemaVersion: 1,\n package: pkg.identity,\n extensions: extensionSnapshot.entries,\n skillDirs,\n prompts,\n report,\n }\n const runtimeSpec = options.runtimeSpec\n if (runtimeSpec === undefined) await copyEmbeddedRuntime(outDir)\n const optionalSkillDeps = [...extensionSnapshot.skillScriptPackages]\n .filter(name => !SHIMMED_PI_HOST_PACKAGES.has(name) && !(name in stringRecord(pkg.packageJson.dependencies)))\n if (optionalSkillDeps.length > 0) {\n console.warn(`pi2dsh: skill helper scripts reference ${optionalSkillDeps.join(', ')}; install them only if you use those skills`)\n }\n\n await Promise.all([\n writeFile(join(outDir, 'package.json'), `${JSON.stringify(generatedPackageJson(pkg, packageName, runtimeSpec, extensionSnapshot.runtimePackages, skillDirs.length > 0), null, 2)}\\n`),\n writeFile(join(outDir, 'pi2dsh.manifest.json'), `${JSON.stringify(manifest, null, 2)}\\n`),\n writeFile(join(outDir, 'pi2dsh.report.json'), `${JSON.stringify(report, null, 2)}\\n`),\n writeFile(join(outDir, 'index.js'), pluginSource(manifest, runtimeSpec === undefined ? './runtime/pi2dsh-runtime.mjs' : 'pi2dsh/runtime')),\n writeFile(join(outDir, 'cordis.patch.yml'), patchSource(packageName, slug)),\n writeFile(join(outDir, 'README.md'), generatedReadme(pkg, packageName, report)),\n ])\n return { outDir, report, packageName }\n}\n"],"mappings":"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"}
|
package/dist/host.d.mts
CHANGED
|
@@ -11,6 +11,8 @@ interface PiHostPackageSpec {
|
|
|
11
11
|
}
|
|
12
12
|
interface PiHostConfig {
|
|
13
13
|
packages: Array<string | PiHostPackageSpec>;
|
|
14
|
+
/** Image-admission companion routes (host-level): `{ <existingRoute>: [modelIds] }`. */
|
|
15
|
+
visionCompanions?: Record<string, readonly string[]>;
|
|
14
16
|
}
|
|
15
17
|
/** Build a runtime manifest in place over an installed Pi package directory. */
|
|
16
18
|
declare function manifestForInstalled(pkg: ResolvedPiPackage): Promise<GeneratedRuntimeManifest>;
|
package/dist/host.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.mts","names":[],"sources":["../src/host.ts"],"mappings":";;;;KAmBK,gBAAgB;UAEJ;;EAEf;;EAEA,SAAS;;UAGM;EACf,UAAU,eAAe;;;
|
|
1
|
+
{"version":3,"file":"host.d.mts","names":[],"sources":["../src/host.ts"],"mappings":";;;;KAmBK,gBAAgB;UAEJ;;EAEf;;EAEA,SAAS;;UAGM;EACf,UAAU,eAAe;;EAEzB,mBAAmB;;;iBAuBC,qBAAqB,KAAK,oBAAoB,QAAQ;;;;;;iBA8DtD,YAAY,KAAK,SAAS,QAAQ,cAAc,kBAAkB;UAoCvE;EACf;;EAEA;EACA;;iBA+CoB,mBAAmB,SAAS,oBAAoB;EAAU;EAAgB"}
|
package/dist/host.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { t as applyPiPackage } from "./runtime-
|
|
2
|
+
import { r as registerVisionCompanions, t as applyPiPackage } from "./runtime-B-Mun-jX.mjs";
|
|
3
3
|
import { t as resolvePiPackage } from "./source-0sA5z08z.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { cp, mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
@@ -82,6 +82,7 @@ function resolveInstalledDir(anchor, packageName) {
|
|
|
82
82
|
*/
|
|
83
83
|
async function applyPiHost(ctx, config, anchor) {
|
|
84
84
|
const anchorPath = anchor ?? fileURLToPath(import.meta.url);
|
|
85
|
+
registerVisionCompanions(ctx, config.visionCompanions);
|
|
85
86
|
const errors = [];
|
|
86
87
|
for (const spec of normalizeSpecs(config)) try {
|
|
87
88
|
const dir = resolveInstalledDir(anchorPath, spec.name);
|
package/dist/host.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.mjs","names":[],"sources":["../src/host.ts"],"sourcesContent":["// PiHostOnDSH: one DSH plugin that hosts unmodified Pi packages.\n//\n// Instead of converting each package into a vendored bundle, the host bundle\n// declares Pi packages as ordinary npm dependencies; DSH's plugin manager\n// (pnpm) installs them, and at load time this module resolves each installed\n// package, discovers its Pi entry points, and mounts it through the same\n// package-agnostic runtime as converted bundles. One host, any package —\n// there is deliberately no per-package branching here.\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { readdir, readFile, stat, writeFile, mkdir, cp } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { basename, dirname, join, relative } from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { applyPiPackage } from './runtime.js'\nimport { resolvePiPackage } from './source.js'\nimport type { GeneratedRuntimeManifest, ResolvedPiPackage } from './types.js'\n\ntype UnknownRecord = Record<string, unknown>\n\nexport interface PiHostPackageSpec {\n /** npm package name as installed in the host bundle's node_modules. */\n name: string\n /** Optional per-package config forwarded to the runtime. */\n config?: UnknownRecord\n}\n\nexport interface PiHostConfig {\n packages: Array<string | PiHostPackageSpec>\n}\n\nfunction parseFrontmatter(text: string): { attributes: Record<string, string>; body: string } {\n const normalized = text.replace(/\\r\\n?/gu, '\\n')\n if (!normalized.startsWith('---')) return { attributes: {}, body: normalized }\n const endIndex = normalized.indexOf('\\n---', 3)\n if (endIndex === -1) return { attributes: {}, body: normalized }\n const attributes: Record<string, string> = {}\n for (const line of normalized.slice(4, endIndex).split('\\n')) {\n const separator = line.indexOf(':')\n if (separator === -1) continue\n const key = line.slice(0, separator).trim()\n let value = line.slice(separator + 1).trim()\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1)\n }\n if (key.length > 0) attributes[key] = value\n }\n return { attributes, body: normalized.slice(endIndex + 4).trim() }\n}\n\n/** Build a runtime manifest in place over an installed Pi package directory. */\nexport async function manifestForInstalled(pkg: ResolvedPiPackage): Promise<GeneratedRuntimeManifest> {\n const relativeTo = (file: string): string => relative(pkg.rootDir, file).replaceAll('\\\\', '/')\n\n const skillDirs = new Set<string>()\n for (const file of pkg.resources.skills) {\n // <dir>/<name>/SKILL.md contributes <dir>; a flat <dir>/<name>.md contributes <dir>.\n skillDirs.add(relativeTo(basename(file) === 'SKILL.md' ? dirname(dirname(file)) : dirname(file)))\n }\n\n const prompts: GeneratedRuntimeManifest['prompts'] = []\n const promptNames = new Set<string>()\n for (const source of pkg.resources.prompts) {\n const name = basename(source, '.md').toLowerCase().replace(/[^a-z0-9_-]+/gu, '-')\n if (promptNames.has(name)) throw new Error(`prompt command name collision in ${pkg.identity.name}: ${name}`)\n promptNames.add(name)\n const { attributes, body } = parseFrontmatter(await readFile(source, 'utf8'))\n const firstLine = body.split(/\\r?\\n/u).map(line => line.trim()).find(Boolean)\n prompts.push({\n name,\n description: attributes.description ?? firstLine ?? `Run migrated Pi prompt ${name}`,\n ...(attributes['argument-hint'] !== undefined ? { argumentHint: attributes['argument-hint'] } : {}),\n path: relativeTo(source),\n })\n }\n\n return {\n schemaVersion: 1,\n package: pkg.identity,\n extensions: pkg.resources.extensions.map(relativeTo),\n skillDirs: [...skillDirs].sort(),\n prompts,\n }\n}\n\nfunction normalizeSpecs(config: PiHostConfig): PiHostPackageSpec[] {\n const packages = Array.isArray(config?.packages) ? config.packages : []\n return packages.map(spec => (typeof spec === 'string' ? { name: spec } : spec))\n .filter(spec => typeof spec?.name === 'string' && spec.name.length > 0)\n}\n\nfunction resolveInstalledDir(anchor: string, packageName: string): string {\n const require = createRequire(anchor)\n try {\n return dirname(require.resolve(`${packageName}/package.json`))\n } catch {\n // Modern strict `exports` maps refuse the package.json subpath, and pure\n // ESM packages (no \"require\" condition) refuse CJS entry resolution too.\n // Locate the installed directory on the filesystem instead: probe every\n // node_modules candidate on the resolution path — no exports involved.\n for (const candidate of require.resolve.paths(packageName) ?? []) {\n const dir = join(candidate, packageName)\n if (existsSync(join(dir, 'package.json'))) return dir\n }\n throw new Error(`cannot locate the installed package directory for ${JSON.stringify(packageName)} near ${JSON.stringify(anchor)}`)\n }\n}\n\n/**\n * Mount every configured Pi package from the host bundle's own node_modules.\n * Packages that fail to mount report their error and do not take down the\n * host or their siblings — matching Pi's own per-extension error isolation.\n */\nexport async function applyPiHost(ctx: Context, config: PiHostConfig, anchor?: string): Promise<void> {\n const anchorPath = anchor ?? fileURLToPath(import.meta.url)\n const errors: Array<{ name: string; error: string }> = []\n for (const spec of normalizeSpecs(config)) {\n try {\n const dir = resolveInstalledDir(anchorPath, spec.name)\n const pkg = await resolvePiPackage(dir)\n try {\n const manifest = await manifestForInstalled(pkg)\n await applyPiPackage(ctx, {\n rootUrl: pathToFileURL(`${pkg.rootDir}/`),\n manifest,\n ...(spec.config === undefined ? {} : { config: spec.config }),\n })\n } finally {\n await pkg.dispose()\n }\n } catch (error) {\n errors.push({ name: spec.name, error: error instanceof Error ? error.message : String(error) })\n }\n }\n for (const failure of errors) {\n const log = (ctx as unknown as { logger?: { warn?(message: string): void } }).logger\n const warn = log?.warn?.bind(log) ?? console.warn\n warn(`[pi2dsh host] failed to mount ${failure.name}: ${failure.error}`)\n }\n if (errors.length > 0 && errors.length === normalizeSpecs(config).length) {\n throw new Error(`pi2dsh host mounted no packages; first failure: ${errors[0]!.name}: ${errors[0]!.error}`)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Host bundle generation\n// ---------------------------------------------------------------------------\n\nexport interface HostBundleOptions {\n outDir: string\n /** npm specs, e.g. \"@narumitw/pi-lsp@0.49.4\" or \"pi-ask-user\". */\n packages: string[]\n bundleName?: string\n}\n\nfunction splitSpec(spec: string): { name: string; range: string } {\n const at = spec.lastIndexOf('@')\n if (at > 0) return { name: spec.slice(0, at), range: spec.slice(at + 1) }\n return { name: spec, range: '*' }\n}\n\nasync function firstExisting(paths: string[]): Promise<string> {\n for (const path of paths) {\n try {\n await stat(path)\n return path\n } catch {\n // Try the next layout.\n }\n }\n throw new Error(`cannot locate pi2dsh runtime artifact; tried: ${paths.join(', ')}`)\n}\n\nasync function copyEmbeddedHostRuntime(outDir: string): Promise<void> {\n const moduleDir = dirname(fileURLToPath(import.meta.url))\n const hostSource = await firstExisting([\n join(moduleDir, 'host.mjs'),\n join(moduleDir, '../dist/host.mjs'),\n ])\n const distRoot = dirname(hostSource)\n const targetRoot = join(outDir, 'runtime')\n await mkdir(join(targetRoot, 'compat', 'vendor'), { recursive: true })\n for (const entry of await readdir(distRoot)) {\n if (entry.endsWith('.mjs') || entry.endsWith('.d.mts')) {\n await cp(join(distRoot, entry), join(targetRoot, entry))\n }\n }\n for (const sub of ['compat', join('compat', 'vendor')]) {\n const dir = join(distRoot, sub)\n try {\n for (const entry of await readdir(dir)) {\n if (entry.endsWith('.mjs')) await cp(join(dir, entry), join(targetRoot, sub, entry))\n }\n } catch {\n // dist layout without that subdirectory\n }\n }\n}\n\nexport async function generateHostBundle(options: HostBundleOptions): Promise<{ outDir: string; packageName: string }> {\n const specs = options.packages.map(splitSpec)\n if (specs.length === 0) throw new Error('host bundle requires at least one Pi package spec')\n const packageName = options.bundleName ?? 'dsh-pi-host'\n await mkdir(options.outDir, { recursive: true })\n await copyEmbeddedHostRuntime(options.outDir)\n\n const packageJson = {\n name: packageName,\n version: '0.1.0',\n description: `pi2dsh host bundle mounting ${specs.map(spec => spec.name).join(', ')} as native DSH plugins`,\n type: 'module',\n main: './index.js',\n files: ['index.js', 'cordis.patch.yml', 'runtime', 'PI2DSH-LICENSE', 'README.md'],\n dependencies: {\n ...Object.fromEntries(specs.map(spec => [spec.name, spec.range])),\n jiti: '^2.7.0',\n 'get-east-asian-width': '^1.6.0',\n marked: '^16.4.1',\n typebox: '^1.0.4',\n tinyglobby: '^0.2.15',\n // The vendored Pi built-in tool constructors spawn through cross-spawn\n // and diff exactly as Pi does — same runtime set the convert bundle\n // carries (generator.ts keeps the sibling list).\n 'cross-spawn': '^7.0.6',\n diff: '^9.0.0',\n '@deepseek-ai/dsh-skill-filesystem': '^0.1.0-rc.6',\n // The bridge's own openai-completions client (openai SDK) serves the\n // common gateway protocol; rarer apis lazily use a real pi-ai from\n // the mounted packages' own dependency trees. A direct pi-ai\n // dependency would drag @google/genai → protobufjs, whose blocked\n // install script fails `dsh plugin add` for transitive dependencies.\n openai: '^6.40.0',\n },\n peerDependencies: {\n '@deepseek-ai/dsh-llm': '^0.1.0-rc.6',\n '@deepseek-ai/dsh-system-prompt': '^0.1.0-rc.6',\n },\n keywords: ['dsh-plugin', 'deepseek-harness', 'pi-package', 'pi2dsh', 'pi-host'],\n license: 'MIT',\n dsh: { bundle: { patch: './cordis.patch.yml' } },\n }\n await writeFile(join(options.outDir, 'package.json'), `${JSON.stringify(packageJson, null, 2)}\\n`)\n\n const hostConfig: PiHostConfig = { packages: specs.map(spec => spec.name) }\n const indexSource = `import { applyPiHost } from './runtime/host.mjs'\\n\\n`\n + `export const name = ${JSON.stringify(packageName)}\\n`\n + `export const inject = ${JSON.stringify(['tools', 'systemPrompt', 'commands', 'skills'])}\\n\\n`\n + `const hostConfig = ${JSON.stringify(hostConfig, null, 2)}\\n\\n`\n + `export async function apply(ctx, config = {}) {\\n`\n + ` await applyPiHost(ctx, { ...hostConfig, ...config }, new URL(import.meta.url).pathname)\\n`\n + `}\\n`\n await writeFile(join(options.outDir, 'index.js'), indexSource)\n\n await writeFile(join(options.outDir, 'cordis.patch.yml'),\n `- insert:\\n - id: ${packageName}\\n name: ${JSON.stringify(packageName)}\\n`)\n\n const licenseSource = await firstExisting([\n join(dirname(fileURLToPath(import.meta.url)), 'compat/vendor/PI-LICENSE'),\n join(dirname(fileURLToPath(import.meta.url)), '../src/compat/vendor/PI-LICENSE'),\n ])\n await cp(licenseSource, join(options.outDir, 'PI2DSH-LICENSE'))\n\n await writeFile(join(options.outDir, 'README.md'),\n `# ${packageName}\\n\\n`\n + `A [pi2dsh](https://github.com/weijiafu14/pi2dsh) host bundle. The Pi packages below are installed as ordinary npm dependencies and mounted at load time — no per-package conversion, no vendored source snapshots.\\n\\n`\n + specs.map(spec => `- \\`${spec.name}@${spec.range}\\`\\n`).join('')\n + `\\nInstall:\\n\\n\\`\\`\\`sh\\ndsh plugin --profile headless add file:$PWD\\ndsh --profile headless --dump-config\\n\\`\\`\\`\\n`\n + `\\nThe packages execute their original Pi extension source inside the pi2dsh Host ABI; install only sources you trust. Run \\`pi2dsh inspect <package>\\` for each package's compatibility report.\\n`)\n\n return { outDir: options.outDir, packageName }\n}\n"],"mappings":";;;;;;;;;AAgCA,SAAS,iBAAiB,MAAoE;CAC5F,MAAM,aAAa,KAAK,QAAQ,WAAW,IAAI;CAC/C,IAAI,CAAC,WAAW,WAAW,KAAK,GAAG,OAAO;EAAE,YAAY,CAAC;EAAG,MAAM;CAAW;CAC7E,MAAM,WAAW,WAAW,QAAQ,SAAS,CAAC;CAC9C,IAAI,aAAa,IAAI,OAAO;EAAE,YAAY,CAAC;EAAG,MAAM;CAAW;CAC/D,MAAM,aAAqC,CAAC;CAC5C,KAAK,MAAM,QAAQ,WAAW,MAAM,GAAG,QAAQ,CAAC,CAAC,MAAM,IAAI,GAAG;EAC5D,MAAM,YAAY,KAAK,QAAQ,GAAG;EAClC,IAAI,cAAc,IAAI;EACtB,MAAM,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK;EAC1C,IAAI,QAAQ,KAAK,MAAM,YAAY,CAAC,CAAC,CAAC,KAAK;EAC3C,IAAK,MAAM,WAAW,IAAG,KAAK,MAAM,SAAS,IAAG,KAAO,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAChG,QAAQ,MAAM,MAAM,GAAG,EAAE;EAE3B,IAAI,IAAI,SAAS,GAAG,WAAW,OAAO;CACxC;CACA,OAAO;EAAE;EAAY,MAAM,WAAW,MAAM,WAAW,CAAC,CAAC,CAAC,KAAK;CAAE;AACnE;;AAGA,eAAsB,qBAAqB,KAA2D;CACpG,MAAM,cAAc,SAAyB,SAAS,IAAI,SAAS,IAAI,CAAC,CAAC,WAAW,MAAM,GAAG;CAE7F,MAAM,4BAAY,IAAI,IAAY;CAClC,KAAK,MAAM,QAAQ,IAAI,UAAU,QAE/B,UAAU,IAAI,WAAW,SAAS,IAAI,MAAM,aAAa,QAAQ,QAAQ,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,CAAC;CAGlG,MAAM,UAA+C,CAAC;CACtD,MAAM,8BAAc,IAAI,IAAY;CACpC,KAAK,MAAM,UAAU,IAAI,UAAU,SAAS;EAC1C,MAAM,OAAO,SAAS,QAAQ,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,kBAAkB,GAAG;EAChF,IAAI,YAAY,IAAI,IAAI,GAAG,MAAM,IAAI,MAAM,oCAAoC,IAAI,SAAS,KAAK,IAAI,MAAM;EAC3G,YAAY,IAAI,IAAI;EACpB,MAAM,EAAE,YAAY,SAAS,iBAAiB,MAAM,SAAS,QAAQ,MAAM,CAAC;EAC5E,MAAM,YAAY,KAAK,MAAM,QAAQ,CAAC,CAAC,KAAI,SAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO;EAC5E,QAAQ,KAAK;GACX;GACA,aAAa,WAAW,eAAe,aAAa,0BAA0B;GAC9E,GAAI,WAAW,qBAAqB,KAAA,IAAY,EAAE,cAAc,WAAW,iBAAiB,IAAI,CAAC;GACjG,MAAM,WAAW,MAAM;EACzB,CAAC;CACH;CAEA,OAAO;EACL,eAAe;EACf,SAAS,IAAI;EACb,YAAY,IAAI,UAAU,WAAW,IAAI,UAAU;EACnD,WAAW,CAAC,GAAG,SAAS,CAAC,CAAC,KAAK;EAC/B;CACF;AACF;AAEA,SAAS,eAAe,QAA2C;CAEjE,QADiB,MAAM,QAAQ,QAAQ,QAAQ,IAAI,OAAO,WAAW,CAAC,EAAA,CACtD,KAAI,SAAS,OAAO,SAAS,WAAW,EAAE,MAAM,KAAK,IAAI,IAAK,CAAC,CAC5E,QAAO,SAAQ,OAAO,MAAM,SAAS,YAAY,KAAK,KAAK,SAAS,CAAC;AAC1E;AAEA,SAAS,oBAAoB,QAAgB,aAA6B;CACxE,MAAM,UAAU,cAAc,MAAM;CACpC,IAAI;EACF,OAAO,QAAQ,QAAQ,QAAQ,GAAG,YAAY,cAAc,CAAC;CAC/D,QAAQ;EAKN,KAAK,MAAM,aAAa,QAAQ,QAAQ,MAAM,WAAW,KAAK,CAAC,GAAG;GAChE,MAAM,MAAM,KAAK,WAAW,WAAW;GACvC,IAAI,WAAW,KAAK,KAAK,cAAc,CAAC,GAAG,OAAO;EACpD;EACA,MAAM,IAAI,MAAM,qDAAqD,KAAK,UAAU,WAAW,EAAE,QAAQ,KAAK,UAAU,MAAM,GAAG;CACnI;AACF;;;;;;AAOA,eAAsB,YAAY,KAAc,QAAsB,QAAgC;CACpG,MAAM,aAAa,UAAU,cAAc,YAAY,GAAG;CAC1D,MAAM,SAAiD,CAAC;CACxD,KAAK,MAAM,QAAQ,eAAe,MAAM,GACtC,IAAI;EACF,MAAM,MAAM,oBAAoB,YAAY,KAAK,IAAI;EACrD,MAAM,MAAM,MAAM,iBAAiB,GAAG;EACtC,IAAI;GACF,MAAM,WAAW,MAAM,qBAAqB,GAAG;GAC/C,MAAM,eAAe,KAAK;IACxB,SAAS,cAAc,GAAG,IAAI,QAAQ,EAAE;IACxC;IACA,GAAI,KAAK,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO;GAC7D,CAAC;EACH,UAAU;GACR,MAAM,IAAI,QAAQ;EACpB;CACF,SAAS,OAAO;EACd,OAAO,KAAK;GAAE,MAAM,KAAK;GAAM,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAAE,CAAC;CAChG;CAEF,KAAK,MAAM,WAAW,QAAQ;EAC5B,MAAM,MAAO,IAAiE;EAE9E,CADa,KAAK,MAAM,KAAK,GAAG,KAAK,QAAQ,KAAA,CACxC,iCAAiC,QAAQ,KAAK,IAAI,QAAQ,OAAO;CACxE;CACA,IAAI,OAAO,SAAS,KAAK,OAAO,WAAW,eAAe,MAAM,CAAC,CAAC,QAChE,MAAM,IAAI,MAAM,mDAAmD,OAAO,EAAE,CAAE,KAAK,IAAI,OAAO,EAAE,CAAE,OAAO;AAE7G;AAaA,SAAS,UAAU,MAA+C;CAChE,MAAM,KAAK,KAAK,YAAY,GAAG;CAC/B,IAAI,KAAK,GAAG,OAAO;EAAE,MAAM,KAAK,MAAM,GAAG,EAAE;EAAG,OAAO,KAAK,MAAM,KAAK,CAAC;CAAE;CACxE,OAAO;EAAE,MAAM;EAAM,OAAO;CAAI;AAClC;AAEA,eAAe,cAAc,OAAkC;CAC7D,KAAK,MAAM,QAAQ,OACjB,IAAI;EACF,MAAM,KAAK,IAAI;EACf,OAAO;CACT,QAAQ,CAER;CAEF,MAAM,IAAI,MAAM,iDAAiD,MAAM,KAAK,IAAI,GAAG;AACrF;AAEA,eAAe,wBAAwB,QAA+B;CACpE,MAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;CACxD,MAAM,aAAa,MAAM,cAAc,CACrC,KAAK,WAAW,UAAU,GAC1B,KAAK,WAAW,kBAAkB,CACpC,CAAC;CACD,MAAM,WAAW,QAAQ,UAAU;CACnC,MAAM,aAAa,KAAK,QAAQ,SAAS;CACzC,MAAM,MAAM,KAAK,YAAY,UAAU,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;CACrE,KAAK,MAAM,SAAS,MAAM,QAAQ,QAAQ,GACxC,IAAI,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,QAAQ,GACnD,MAAM,GAAG,KAAK,UAAU,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC;CAG3D,KAAK,MAAM,OAAO,CAAC,UAAU,KAAK,UAAU,QAAQ,CAAC,GAAG;EACtD,MAAM,MAAM,KAAK,UAAU,GAAG;EAC9B,IAAI;GACF,KAAK,MAAM,SAAS,MAAM,QAAQ,GAAG,GACnC,IAAI,MAAM,SAAS,MAAM,GAAG,MAAM,GAAG,KAAK,KAAK,KAAK,GAAG,KAAK,YAAY,KAAK,KAAK,CAAC;EAEvF,QAAQ,CAER;CACF;AACF;AAEA,eAAsB,mBAAmB,SAA8E;CACrH,MAAM,QAAQ,QAAQ,SAAS,IAAI,SAAS;CAC5C,IAAI,MAAM,WAAW,GAAG,MAAM,IAAI,MAAM,mDAAmD;CAC3F,MAAM,cAAc,QAAQ,cAAc;CAC1C,MAAM,MAAM,QAAQ,QAAQ,EAAE,WAAW,KAAK,CAAC;CAC/C,MAAM,wBAAwB,QAAQ,MAAM;CAE5C,MAAM,cAAc;EAClB,MAAM;EACN,SAAS;EACT,aAAa,+BAA+B,MAAM,KAAI,SAAQ,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE;EACpF,MAAM;EACN,MAAM;EACN,OAAO;GAAC;GAAY;GAAoB;GAAW;GAAkB;EAAW;EAChF,cAAc;GACZ,GAAG,OAAO,YAAY,MAAM,KAAI,SAAQ,CAAC,KAAK,MAAM,KAAK,KAAK,CAAC,CAAC;GAChE,MAAM;GACN,wBAAwB;GACxB,QAAQ;GACR,SAAS;GACT,YAAY;GAIZ,eAAe;GACf,MAAM;GACN,qCAAqC;GAMrC,QAAQ;EACV;EACA,kBAAkB;GAChB,wBAAwB;GACxB,kCAAkC;EACpC;EACA,UAAU;GAAC;GAAc;GAAoB;GAAc;GAAU;EAAS;EAC9E,SAAS;EACT,KAAK,EAAE,QAAQ,EAAE,OAAO,qBAAqB,EAAE;CACjD;CACA,MAAM,UAAU,KAAK,QAAQ,QAAQ,cAAc,GAAG,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,EAAE,GAAG;CAEjG,MAAM,aAA2B,EAAE,UAAU,MAAM,KAAI,SAAQ,KAAK,IAAI,EAAE;CAC1E,MAAM,cAAc,2EACO,KAAK,UAAU,WAAW,EAAE,0BAC1B,KAAK,UAAU;EAAC;EAAS;EAAgB;EAAY;CAAQ,CAAC,EAAE,yBACnE,KAAK,UAAU,YAAY,MAAM,CAAC,EAAE;CAI9D,MAAM,UAAU,KAAK,QAAQ,QAAQ,UAAU,GAAG,WAAW;CAE7D,MAAM,UAAU,KAAK,QAAQ,QAAQ,kBAAkB,GACrD,wBAAwB,YAAY,gBAAgB,KAAK,UAAU,WAAW,EAAE,GAAG;CAErF,MAAM,gBAAgB,MAAM,cAAc,CACxC,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,0BAA0B,GACxE,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,iCAAiC,CACjF,CAAC;CACD,MAAM,GAAG,eAAe,KAAK,QAAQ,QAAQ,gBAAgB,CAAC;CAE9D,MAAM,UAAU,KAAK,QAAQ,QAAQ,WAAW,GAC9C,KAAK,YAAY,8NAEf,MAAM,KAAI,SAAQ,OAAO,KAAK,KAAK,GAAG,KAAK,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,IAC/D,8SACmM;CAEvM,OAAO;EAAE,QAAQ,QAAQ;EAAQ;CAAY;AAC/C"}
|
|
1
|
+
{"version":3,"file":"host.mjs","names":[],"sources":["../src/host.ts"],"sourcesContent":["// PiHostOnDSH: one DSH plugin that hosts unmodified Pi packages.\n//\n// Instead of converting each package into a vendored bundle, the host bundle\n// declares Pi packages as ordinary npm dependencies; DSH's plugin manager\n// (pnpm) installs them, and at load time this module resolves each installed\n// package, discovers its Pi entry points, and mounts it through the same\n// package-agnostic runtime as converted bundles. One host, any package —\n// there is deliberately no per-package branching here.\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { readdir, readFile, stat, writeFile, mkdir, cp } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { basename, dirname, join, relative } from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { applyPiPackage, registerVisionCompanions } from './runtime.js'\nimport { resolvePiPackage } from './source.js'\nimport type { GeneratedRuntimeManifest, ResolvedPiPackage } from './types.js'\n\ntype UnknownRecord = Record<string, unknown>\n\nexport interface PiHostPackageSpec {\n /** npm package name as installed in the host bundle's node_modules. */\n name: string\n /** Optional per-package config forwarded to the runtime. */\n config?: UnknownRecord\n}\n\nexport interface PiHostConfig {\n packages: Array<string | PiHostPackageSpec>\n /** Image-admission companion routes (host-level): `{ <existingRoute>: [modelIds] }`. */\n visionCompanions?: Record<string, readonly string[]>\n}\n\nfunction parseFrontmatter(text: string): { attributes: Record<string, string>; body: string } {\n const normalized = text.replace(/\\r\\n?/gu, '\\n')\n if (!normalized.startsWith('---')) return { attributes: {}, body: normalized }\n const endIndex = normalized.indexOf('\\n---', 3)\n if (endIndex === -1) return { attributes: {}, body: normalized }\n const attributes: Record<string, string> = {}\n for (const line of normalized.slice(4, endIndex).split('\\n')) {\n const separator = line.indexOf(':')\n if (separator === -1) continue\n const key = line.slice(0, separator).trim()\n let value = line.slice(separator + 1).trim()\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1)\n }\n if (key.length > 0) attributes[key] = value\n }\n return { attributes, body: normalized.slice(endIndex + 4).trim() }\n}\n\n/** Build a runtime manifest in place over an installed Pi package directory. */\nexport async function manifestForInstalled(pkg: ResolvedPiPackage): Promise<GeneratedRuntimeManifest> {\n const relativeTo = (file: string): string => relative(pkg.rootDir, file).replaceAll('\\\\', '/')\n\n const skillDirs = new Set<string>()\n for (const file of pkg.resources.skills) {\n // <dir>/<name>/SKILL.md contributes <dir>; a flat <dir>/<name>.md contributes <dir>.\n skillDirs.add(relativeTo(basename(file) === 'SKILL.md' ? dirname(dirname(file)) : dirname(file)))\n }\n\n const prompts: GeneratedRuntimeManifest['prompts'] = []\n const promptNames = new Set<string>()\n for (const source of pkg.resources.prompts) {\n const name = basename(source, '.md').toLowerCase().replace(/[^a-z0-9_-]+/gu, '-')\n if (promptNames.has(name)) throw new Error(`prompt command name collision in ${pkg.identity.name}: ${name}`)\n promptNames.add(name)\n const { attributes, body } = parseFrontmatter(await readFile(source, 'utf8'))\n const firstLine = body.split(/\\r?\\n/u).map(line => line.trim()).find(Boolean)\n prompts.push({\n name,\n description: attributes.description ?? firstLine ?? `Run migrated Pi prompt ${name}`,\n ...(attributes['argument-hint'] !== undefined ? { argumentHint: attributes['argument-hint'] } : {}),\n path: relativeTo(source),\n })\n }\n\n return {\n schemaVersion: 1,\n package: pkg.identity,\n extensions: pkg.resources.extensions.map(relativeTo),\n skillDirs: [...skillDirs].sort(),\n prompts,\n }\n}\n\nfunction normalizeSpecs(config: PiHostConfig): PiHostPackageSpec[] {\n const packages = Array.isArray(config?.packages) ? config.packages : []\n return packages.map(spec => (typeof spec === 'string' ? { name: spec } : spec))\n .filter(spec => typeof spec?.name === 'string' && spec.name.length > 0)\n}\n\nfunction resolveInstalledDir(anchor: string, packageName: string): string {\n const require = createRequire(anchor)\n try {\n return dirname(require.resolve(`${packageName}/package.json`))\n } catch {\n // Modern strict `exports` maps refuse the package.json subpath, and pure\n // ESM packages (no \"require\" condition) refuse CJS entry resolution too.\n // Locate the installed directory on the filesystem instead: probe every\n // node_modules candidate on the resolution path — no exports involved.\n for (const candidate of require.resolve.paths(packageName) ?? []) {\n const dir = join(candidate, packageName)\n if (existsSync(join(dir, 'package.json'))) return dir\n }\n throw new Error(`cannot locate the installed package directory for ${JSON.stringify(packageName)} near ${JSON.stringify(anchor)}`)\n }\n}\n\n/**\n * Mount every configured Pi package from the host bundle's own node_modules.\n * Packages that fail to mount report their error and do not take down the\n * host or their siblings — matching Pi's own per-extension error isolation.\n */\nexport async function applyPiHost(ctx: Context, config: PiHostConfig, anchor?: string): Promise<void> {\n const anchorPath = anchor ?? fileURLToPath(import.meta.url)\n registerVisionCompanions(ctx, config.visionCompanions)\n const errors: Array<{ name: string; error: string }> = []\n for (const spec of normalizeSpecs(config)) {\n try {\n const dir = resolveInstalledDir(anchorPath, spec.name)\n const pkg = await resolvePiPackage(dir)\n try {\n const manifest = await manifestForInstalled(pkg)\n await applyPiPackage(ctx, {\n rootUrl: pathToFileURL(`${pkg.rootDir}/`),\n manifest,\n ...(spec.config === undefined ? {} : { config: spec.config }),\n })\n } finally {\n await pkg.dispose()\n }\n } catch (error) {\n errors.push({ name: spec.name, error: error instanceof Error ? error.message : String(error) })\n }\n }\n for (const failure of errors) {\n const log = (ctx as unknown as { logger?: { warn?(message: string): void } }).logger\n const warn = log?.warn?.bind(log) ?? console.warn\n warn(`[pi2dsh host] failed to mount ${failure.name}: ${failure.error}`)\n }\n if (errors.length > 0 && errors.length === normalizeSpecs(config).length) {\n throw new Error(`pi2dsh host mounted no packages; first failure: ${errors[0]!.name}: ${errors[0]!.error}`)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Host bundle generation\n// ---------------------------------------------------------------------------\n\nexport interface HostBundleOptions {\n outDir: string\n /** npm specs, e.g. \"@narumitw/pi-lsp@0.49.4\" or \"pi-ask-user\". */\n packages: string[]\n bundleName?: string\n}\n\nfunction splitSpec(spec: string): { name: string; range: string } {\n const at = spec.lastIndexOf('@')\n if (at > 0) return { name: spec.slice(0, at), range: spec.slice(at + 1) }\n return { name: spec, range: '*' }\n}\n\nasync function firstExisting(paths: string[]): Promise<string> {\n for (const path of paths) {\n try {\n await stat(path)\n return path\n } catch {\n // Try the next layout.\n }\n }\n throw new Error(`cannot locate pi2dsh runtime artifact; tried: ${paths.join(', ')}`)\n}\n\nasync function copyEmbeddedHostRuntime(outDir: string): Promise<void> {\n const moduleDir = dirname(fileURLToPath(import.meta.url))\n const hostSource = await firstExisting([\n join(moduleDir, 'host.mjs'),\n join(moduleDir, '../dist/host.mjs'),\n ])\n const distRoot = dirname(hostSource)\n const targetRoot = join(outDir, 'runtime')\n await mkdir(join(targetRoot, 'compat', 'vendor'), { recursive: true })\n for (const entry of await readdir(distRoot)) {\n if (entry.endsWith('.mjs') || entry.endsWith('.d.mts')) {\n await cp(join(distRoot, entry), join(targetRoot, entry))\n }\n }\n for (const sub of ['compat', join('compat', 'vendor')]) {\n const dir = join(distRoot, sub)\n try {\n for (const entry of await readdir(dir)) {\n if (entry.endsWith('.mjs')) await cp(join(dir, entry), join(targetRoot, sub, entry))\n }\n } catch {\n // dist layout without that subdirectory\n }\n }\n}\n\nexport async function generateHostBundle(options: HostBundleOptions): Promise<{ outDir: string; packageName: string }> {\n const specs = options.packages.map(splitSpec)\n if (specs.length === 0) throw new Error('host bundle requires at least one Pi package spec')\n const packageName = options.bundleName ?? 'dsh-pi-host'\n await mkdir(options.outDir, { recursive: true })\n await copyEmbeddedHostRuntime(options.outDir)\n\n const packageJson = {\n name: packageName,\n version: '0.1.0',\n description: `pi2dsh host bundle mounting ${specs.map(spec => spec.name).join(', ')} as native DSH plugins`,\n type: 'module',\n main: './index.js',\n files: ['index.js', 'cordis.patch.yml', 'runtime', 'PI2DSH-LICENSE', 'README.md'],\n dependencies: {\n ...Object.fromEntries(specs.map(spec => [spec.name, spec.range])),\n jiti: '^2.7.0',\n 'get-east-asian-width': '^1.6.0',\n marked: '^16.4.1',\n typebox: '^1.0.4',\n tinyglobby: '^0.2.15',\n // The vendored Pi built-in tool constructors spawn through cross-spawn\n // and diff exactly as Pi does — same runtime set the convert bundle\n // carries (generator.ts keeps the sibling list).\n 'cross-spawn': '^7.0.6',\n diff: '^9.0.0',\n '@deepseek-ai/dsh-skill-filesystem': '^0.1.0-rc.6',\n // The bridge's own openai-completions client (openai SDK) serves the\n // common gateway protocol; rarer apis lazily use a real pi-ai from\n // the mounted packages' own dependency trees. A direct pi-ai\n // dependency would drag @google/genai → protobufjs, whose blocked\n // install script fails `dsh plugin add` for transitive dependencies.\n openai: '^6.40.0',\n },\n peerDependencies: {\n '@deepseek-ai/dsh-llm': '^0.1.0-rc.6',\n '@deepseek-ai/dsh-system-prompt': '^0.1.0-rc.6',\n },\n keywords: ['dsh-plugin', 'deepseek-harness', 'pi-package', 'pi2dsh', 'pi-host'],\n license: 'MIT',\n dsh: { bundle: { patch: './cordis.patch.yml' } },\n }\n await writeFile(join(options.outDir, 'package.json'), `${JSON.stringify(packageJson, null, 2)}\\n`)\n\n const hostConfig: PiHostConfig = { packages: specs.map(spec => spec.name) }\n const indexSource = `import { applyPiHost } from './runtime/host.mjs'\\n\\n`\n + `export const name = ${JSON.stringify(packageName)}\\n`\n + `export const inject = ${JSON.stringify(['tools', 'systemPrompt', 'commands', 'skills'])}\\n\\n`\n + `const hostConfig = ${JSON.stringify(hostConfig, null, 2)}\\n\\n`\n + `export async function apply(ctx, config = {}) {\\n`\n + ` await applyPiHost(ctx, { ...hostConfig, ...config }, new URL(import.meta.url).pathname)\\n`\n + `}\\n`\n await writeFile(join(options.outDir, 'index.js'), indexSource)\n\n await writeFile(join(options.outDir, 'cordis.patch.yml'),\n `- insert:\\n - id: ${packageName}\\n name: ${JSON.stringify(packageName)}\\n`)\n\n const licenseSource = await firstExisting([\n join(dirname(fileURLToPath(import.meta.url)), 'compat/vendor/PI-LICENSE'),\n join(dirname(fileURLToPath(import.meta.url)), '../src/compat/vendor/PI-LICENSE'),\n ])\n await cp(licenseSource, join(options.outDir, 'PI2DSH-LICENSE'))\n\n await writeFile(join(options.outDir, 'README.md'),\n `# ${packageName}\\n\\n`\n + `A [pi2dsh](https://github.com/weijiafu14/pi2dsh) host bundle. The Pi packages below are installed as ordinary npm dependencies and mounted at load time — no per-package conversion, no vendored source snapshots.\\n\\n`\n + specs.map(spec => `- \\`${spec.name}@${spec.range}\\`\\n`).join('')\n + `\\nInstall:\\n\\n\\`\\`\\`sh\\ndsh plugin --profile headless add file:$PWD\\ndsh --profile headless --dump-config\\n\\`\\`\\`\\n`\n + `\\nThe packages execute their original Pi extension source inside the pi2dsh Host ABI; install only sources you trust. Run \\`pi2dsh inspect <package>\\` for each package's compatibility report.\\n`)\n\n return { outDir: options.outDir, packageName }\n}\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -2,12 +2,26 @@
|
|
|
2
2
|
import { a as GeneratedRuntimeManifest, c as ResourceInventory, i as GenerateOptions, n as CompatibilityLevel, o as PackageIdentity, r as CompatibilityReport, s as ResolvedPiPackage, t as CompatibilityFinding } from "./types-7IWJPPvS.mjs";
|
|
3
3
|
import { applyPiHost, generateHostBundle, manifestForInstalled } from "./host.mjs";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
5
|
+
//#region src/generator.d.ts
|
|
6
|
+
declare function generateBundle$1(pkg: ResolvedPiPackage, options: GenerateOptions): Promise<{
|
|
7
|
+
outDir: string;
|
|
8
|
+
report: CompatibilityReport;
|
|
9
|
+
packageName: string;
|
|
10
|
+
}>;
|
|
11
|
+
//#endregion
|
|
5
12
|
//#region src/engine.d.ts
|
|
6
13
|
interface EngineConfig {
|
|
7
14
|
/** Mount exactly these packages (skips discovery). */
|
|
8
15
|
packages?: string[];
|
|
9
16
|
/** Never mount these packages even when discovered. */
|
|
10
17
|
exclude?: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Image-admission companion routes: `{ <existingRoute>: [modelIds] }`
|
|
20
|
+
* registers `<route>-vision` — it admits pasted images, hands them to a
|
|
21
|
+
* mounted vision extension through the turn's entering messages, and
|
|
22
|
+
* forwards text-only to the original route.
|
|
23
|
+
*/
|
|
24
|
+
visionCompanions?: Record<string, readonly string[]>;
|
|
11
25
|
}
|
|
12
26
|
/** Locate the DSH profile root: the nearest ancestor holding cordis.yml. */
|
|
13
27
|
declare function findProfileRoot(start: string): string | undefined;
|
|
@@ -30,9 +44,6 @@ declare const name = "pi2dsh";
|
|
|
30
44
|
declare const inject: string[];
|
|
31
45
|
declare function apply(ctx: Context, config?: EngineConfig): Promise<void>;
|
|
32
46
|
//#endregion
|
|
33
|
-
//#region src/analyzer.d.ts
|
|
34
|
-
declare function analyzePackage(pkg: ResolvedPiPackage): Promise<CompatibilityReport>;
|
|
35
|
-
//#endregion
|
|
36
47
|
//#region src/compatibility.d.ts
|
|
37
48
|
interface Rule {
|
|
38
49
|
level: CompatibilityLevel;
|
|
@@ -52,13 +63,6 @@ declare function ruleForHostImport(packageName: string, importedName: string): R
|
|
|
52
63
|
declare function ruleForContextProperty(property: string): Rule | undefined;
|
|
53
64
|
declare function ruleForUiContextProperty(property: string): Rule | undefined;
|
|
54
65
|
//#endregion
|
|
55
|
-
//#region src/generator.d.ts
|
|
56
|
-
declare function generateBundle(pkg: ResolvedPiPackage, options: GenerateOptions): Promise<{
|
|
57
|
-
outDir: string;
|
|
58
|
-
report: CompatibilityReport;
|
|
59
|
-
packageName: string;
|
|
60
|
-
}>;
|
|
61
|
-
//#endregion
|
|
62
66
|
//#region src/mcp-config.d.ts
|
|
63
67
|
type UnknownRecord = Record<string, unknown>;
|
|
64
68
|
interface PiMcpServer {
|
|
@@ -94,5 +98,19 @@ declare function renderMcpPatch(result: McpConversionResult): string;
|
|
|
94
98
|
//#region src/source.d.ts
|
|
95
99
|
declare function resolvePiPackage(source: string, cwd?: string): Promise<ResolvedPiPackage>;
|
|
96
100
|
//#endregion
|
|
101
|
+
//#region src/index.d.ts
|
|
102
|
+
/**
|
|
103
|
+
* Static compatibility analysis of one resolved Pi package (CLI `inspect`).
|
|
104
|
+
* @param pkg - the resolved package.
|
|
105
|
+
* @returns the compatibility report.
|
|
106
|
+
*/
|
|
107
|
+
declare function analyzePackage(pkg: ResolvedPiPackage): Promise<CompatibilityReport>;
|
|
108
|
+
/**
|
|
109
|
+
* Generate a vendored per-package bundle (CLI `convert`).
|
|
110
|
+
* @param options - generation options (see the generator module).
|
|
111
|
+
* @returns the generation result.
|
|
112
|
+
*/
|
|
113
|
+
declare function generateBundle(...args: Parameters<typeof generateBundle$1>): ReturnType<typeof generateBundle$1>;
|
|
114
|
+
//#endregion
|
|
97
115
|
export { API_RULES, CONTEXT_RULES, type CompatibilityFinding, type CompatibilityLevel, type CompatibilityReport, EVENT_RULES, type EngineConfig, type GenerateOptions, type GeneratedRuntimeManifest, HOST_IMPORT_RULES, PI_AI_PACKAGES, PI_CODING_AGENT_PACKAGES, PI_TUI_PACKAGES, type PackageIdentity, type ResolvedPiPackage, type ResourceInventory, UI_CONTEXT_RULES, analyzePackage, apply, applyPiHost, collectPiMcpServers, convertPiMcpConfig, discoverProfilePiPackages, findProfileRoot, generateBundle, generateHostBundle, inject, manifestForInstalled, name, renderMcpPatch, resolvePiPackage, ruleForApi, ruleForContextProperty, ruleForEvent, ruleForHostImport, ruleForUiContextProperty };
|
|
98
116
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/generator.ts","../src/engine.ts","../src/compatibility.ts","../src/mcp-config.ts","../src/source.ts","../src/index.ts"],"mappings":";;;;;iBAwVsB,iBACpB,KAAK,mBACL,SAAS,kBACR;EAAU;EAAgB,QAAQ;EAAqB;;;;UC9TzC;;EAEf;;EAEA;;;;;;;EAOA,mBAAmB;;;iBAIL,gBAAgB;UAUtB;EACR;EACA;;;;;;;;iBAgBoB,0BACpB,qBACA;EAAW;EAAoB,QAAQ;IACtC,QAAQ;;cA4CE;cACA;iBAES,MAAM,KAAK,SAAS,SAAQ,eAAoB;;;UCxH5D;EACR,OAAO;EACP;;cAKW;cAKA;cAKA;cAWA,mBAAmB,SAAS,eAAe,SAAS,eAAe;cAmNnE,eAAe,SAAS,eAAe;cA4BvC,kBAAkB,SAAS,eAAe;cA+B1C,WAAW,SAAS,eAAe;cAgHnC,aAAa,SAAS,eAAe;iBA6FlC,WAAW,iBAAiB;iBAI5B,aAAa,gBAAgB;iBAO7B,kBAAkB,qBAAqB,uBAAuB;iBAS9D,uBAAuB,mBAAmB;iBAI1C,yBAAyB,mBAAmB;;;KCpgBvD,gBAAgB;UAEJ;EACf;EACA;EACA;EACA;EACA;EACA,MAAM;EACN;EACA;EACA,UAAU;EACV;;UAGe;EACf;EACA;;UAGe;EACf,SAAS;EACT,SAAS;EACT,UAAU;EACV;;iBA6Cc,oBAAoB,aAAa;EAA8B,SAAS,YAAY;EAAc;;iBAoElG,mBAAmB,aAAa,wBAA4B;;iBAsD5D,eAAe,QAAQ;;;iBC5EjB,iBAAiB,gBAAgB,eAAsB,QAAQ;;;;;;;;iBChH/D,eAAe,KAAK,oBAAoB,QAAQ;;;;;;iBAUhD,kBAAkB,MAAM,kBAAxB,oBAAqF,kBAA7D"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import { r as registerVisionCompanions } from "./runtime-B-Mun-jX.mjs";
|
|
3
3
|
import { t as resolvePiPackage } from "./source-0sA5z08z.mjs";
|
|
4
4
|
import { applyPiHost, generateHostBundle, manifestForInstalled } from "./host.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { a as CONTEXT_RULES, c as PI_AI_PACKAGES, d as UI_CONTEXT_RULES, f as ruleForApi, g as ruleForUiContextProperty, h as ruleForHostImport, i as API_RULES, l as PI_CODING_AGENT_PACKAGES, m as ruleForEvent, n as convertPiMcpConfig, o as EVENT_RULES, p as ruleForContextProperty, r as renderMcpPatch, s as HOST_IMPORT_RULES, t as collectPiMcpServers, u as PI_TUI_PACKAGES } from "./mcp-config-Dlou-ZA-.mjs";
|
|
6
6
|
import { readFile } from "node:fs/promises";
|
|
7
7
|
import { existsSync } from "node:fs";
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
@@ -96,12 +96,35 @@ async function apply(ctx, config = {}) {
|
|
|
96
96
|
warn
|
|
97
97
|
});
|
|
98
98
|
if (packages.length === 0) {
|
|
99
|
-
|
|
99
|
+
registerVisionCompanions(ctx, config.visionCompanions);
|
|
100
100
|
info("[pi2dsh engine] no Pi packages installed in this profile yet — add one with: dsh plugin --profile <p> add <pi-package>");
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
info(`[pi2dsh engine] mounting ${packages.length} Pi package(s): ${packages.map((pkg) => pkg.name).join(", ")}`);
|
|
104
|
-
await applyPiHost(ctx, {
|
|
104
|
+
await applyPiHost(ctx, {
|
|
105
|
+
packages: packages.map((pkg) => ({ name: pkg.name })),
|
|
106
|
+
...config.visionCompanions === void 0 ? {} : { visionCompanions: config.visionCompanions }
|
|
107
|
+
}, join(profileRoot, "package.json"));
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/index.ts
|
|
111
|
+
/**
|
|
112
|
+
* Static compatibility analysis of one resolved Pi package (CLI `inspect`).
|
|
113
|
+
* @param pkg - the resolved package.
|
|
114
|
+
* @returns the compatibility report.
|
|
115
|
+
*/
|
|
116
|
+
async function analyzePackage(pkg) {
|
|
117
|
+
const { analyzePackage: run } = await import("./analyzer-CKTsWVzn.mjs").then((n) => n.n);
|
|
118
|
+
return run(pkg);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Generate a vendored per-package bundle (CLI `convert`).
|
|
122
|
+
* @param options - generation options (see the generator module).
|
|
123
|
+
* @returns the generation result.
|
|
124
|
+
*/
|
|
125
|
+
async function generateBundle(...args) {
|
|
126
|
+
const { generateBundle: run } = await import("./generator-eyViezvs.mjs").then((n) => n.n);
|
|
127
|
+
return run(...args);
|
|
105
128
|
}
|
|
106
129
|
//#endregion
|
|
107
130
|
export { API_RULES, CONTEXT_RULES, EVENT_RULES, HOST_IMPORT_RULES, PI_AI_PACKAGES, PI_CODING_AGENT_PACKAGES, PI_TUI_PACKAGES, UI_CONTEXT_RULES, analyzePackage, apply, applyPiHost, collectPiMcpServers, convertPiMcpConfig, discoverProfilePiPackages, findProfileRoot, generateBundle, generateHostBundle, inject, manifestForInstalled, name, renderMcpPatch, resolvePiPackage, ruleForApi, ruleForContextProperty, ruleForEvent, ruleForHostImport, ruleForUiContextProperty };
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/engine.ts"],"sourcesContent":["// The pi2dsh engine: ONE installed copy of the bridge that mounts every Pi\n// package the user has added to their DSH profile.\n//\n// dsh plugin --profile p add pi2dsh ← the engine (this plugin)\n// dsh plugin --profile p add @kassing/pi-vision ← plain npm dependency\n// dsh plugin --profile p add pi-vision-tool ← plain npm dependency\n//\n// DSH's plugin manager records only packages that declare `dsh.bundle` as\n// profile layers; everything else stays an ordinary dependency (\"a plain\n// library is fine\"). The engine reads the profile manifest's DIRECT\n// dependencies — every entry there was an explicit `dsh plugin add` — and\n// mounts each package that identifies as a Pi package, all through one\n// bridge instance: one model ledger, one command space, one upgrade unit.\n//\n// Discovery is manifest-driven, never a node_modules scan (the lesson from\n// Prettier 3 dropping directory-based plugin discovery): the dependency list\n// is the user's explicit intent, and package identification uses the same\n// Pi markers `resolvePiPackage` has always used (the `pi` manifest field,\n// with Pi's directory conventions as fallback).\n\nimport { readFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { applyPiHost } from './host.js'\nimport { ensureModelsJsonRoutes } from './runtime.js'\nimport { resolvePiPackage } from './source.js'\n\nexport interface EngineConfig {\n /** Mount exactly these packages (skips discovery). */\n packages?: string[]\n /** Never mount these packages even when discovered. */\n exclude?: string[]\n}\n\n/** Locate the DSH profile root: the nearest ancestor holding cordis.yml. */\nexport function findProfileRoot(start: string): string | undefined {\n let dir = start\n for (;;) {\n if (existsSync(join(dir, 'cordis.yml')) && existsSync(join(dir, 'package.json'))) return dir\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\ninterface DiscoveredPackage {\n name: string\n dir: string\n}\n\nfunction resolveDependencyDir(profileRoot: string, name: string): string | undefined {\n // Direct dependencies of the profile live under its node_modules by name\n // (pnpm links them there); resolving by path needs no exports gymnastics.\n const dir = join(profileRoot, 'node_modules', name)\n return existsSync(join(dir, 'package.json')) ? dir : undefined\n}\n\n/**\n * The profile's direct dependencies that identify as Pi packages: not the\n * engine itself, not a `dsh.bundle` (those are DSH plugins, not Pi\n * packages), carrying either Pi's `pi` manifest field or extension sources\n * under Pi's directory conventions.\n */\nexport async function discoverProfilePiPackages(\n profileRoot: string,\n options: { exclude?: string[], warn?: (message: string) => void } = {},\n): Promise<DiscoveredPackage[]> {\n const warn = options.warn ?? (() => {})\n const excluded = new Set(options.exclude ?? [])\n const manifestText = await readFile(join(profileRoot, 'package.json'), 'utf8')\n const manifest = JSON.parse(manifestText) as { dependencies?: Record<string, string> }\n const discovered: DiscoveredPackage[] = []\n for (const name of Object.keys(manifest.dependencies ?? {})) {\n if (name === 'pi2dsh' || excluded.has(name)) continue\n const dir = resolveDependencyDir(profileRoot, name)\n if (dir === undefined) {\n warn(`[pi2dsh engine] dependency ${JSON.stringify(name)} is not installed under the profile; skipping`)\n continue\n }\n let packageJson: Record<string, unknown>\n try {\n packageJson = JSON.parse(await readFile(join(dir, 'package.json'), 'utf8')) as Record<string, unknown>\n } catch (error) {\n warn(`[pi2dsh engine] cannot read ${name}/package.json (${error instanceof Error ? error.message : String(error)}); skipping`)\n continue\n }\n // A dsh.bundle-declaring package is a DSH plugin layer, never a Pi package.\n if ((packageJson.dsh as { bundle?: unknown } | undefined)?.bundle !== undefined) continue\n if (packageJson.pi !== undefined && typeof packageJson.pi === 'object') {\n discovered.push({ name, dir })\n continue\n }\n // No `pi` field: fall back to Pi's directory conventions via the same\n // resolver every other mount path uses (a package with zero extension\n // sources is a plain library and stays unmounted).\n try {\n const pkg = await resolvePiPackage(dir)\n try {\n if (pkg.resources.extensions.length > 0) discovered.push({ name, dir })\n } finally {\n await pkg.dispose()\n }\n } catch {\n // Not resolvable as a Pi package — a plain library.\n }\n }\n return discovered\n}\n\n/** Cordis plugin surface: `dsh plugin add pi2dsh` mounts this. */\nexport const name = 'pi2dsh'\nexport const inject = ['tools', 'systemPrompt', 'commands', 'skills']\n\nexport async function apply(ctx: Context, config: EngineConfig = {}): Promise<void> {\n // Same emission as the runtime's logger helper: the cordis logger AND the\n // console — profile logger levels must never hide what the engine mounted.\n const log = (ctx as unknown as { logger?: { info?(m: string): void, warn?(m: string): void } }).logger\n const warn = (message: string): void => { log?.warn?.(message); console.warn(message) }\n const info = (message: string): void => { log?.info?.(message); console.log(message) }\n\n // The loader resolves plugins against the profile's baseUrl; that IS the\n // profile root. The ancestor walk from the installed engine is the\n // fallback for compositions without a loader (tests, hand-built hosts).\n const baseUrl = (ctx as unknown as { baseUrl?: string }).baseUrl\n const profileRoot = (baseUrl !== undefined ? findProfileRoot(fileURLToPath(new URL('.', baseUrl))) : undefined)\n ?? findProfileRoot(dirname(fileURLToPath(import.meta.url)))\n if (profileRoot === undefined) {\n throw new Error('pi2dsh engine: no DSH profile root (cordis.yml + package.json) above the installed engine — is pi2dsh installed via `dsh plugin add pi2dsh`?')\n }\n\n const packages = Array.isArray(config.packages) && config.packages.length > 0\n ? config.packages.map(name => ({ name }))\n : await discoverProfilePiPackages(profileRoot, {\n ...(Array.isArray(config.exclude) ? { exclude: config.exclude } : {}),\n warn,\n })\n if (packages.length === 0) {\n // The single-directory capability (models.json providers + companion\n // routes in the DSH picker) is the bridge's own — it works with zero\n // Pi packages installed.\n await ensureModelsJsonRoutes(ctx)\n info('[pi2dsh engine] no Pi packages installed in this profile yet — add one with: dsh plugin --profile <p> add <pi-package>')\n return\n }\n info(`[pi2dsh engine] mounting ${packages.length} Pi package(s): ${packages.map(pkg => pkg.name).join(', ')}`)\n await applyPiHost(\n ctx,\n { packages: packages.map(pkg => ({ name: pkg.name })) },\n join(profileRoot, 'package.json'),\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/engine.ts","../src/index.ts"],"sourcesContent":["// The pi2dsh engine: ONE installed copy of the bridge that mounts every Pi\n// package the user has added to their DSH profile.\n//\n// dsh plugin --profile p add pi2dsh ← the engine (this plugin)\n// dsh plugin --profile p add @kassing/pi-vision ← plain npm dependency\n// dsh plugin --profile p add pi-vision-tool ← plain npm dependency\n//\n// DSH's plugin manager records only packages that declare `dsh.bundle` as\n// profile layers; everything else stays an ordinary dependency (\"a plain\n// library is fine\"). The engine reads the profile manifest's DIRECT\n// dependencies — every entry there was an explicit `dsh plugin add` — and\n// mounts each package that identifies as a Pi package, all through one\n// bridge instance: one model ledger, one command space, one upgrade unit.\n//\n// Discovery is manifest-driven, never a node_modules scan (the lesson from\n// Prettier 3 dropping directory-based plugin discovery): the dependency list\n// is the user's explicit intent, and package identification uses the same\n// Pi markers `resolvePiPackage` has always used (the `pi` manifest field,\n// with Pi's directory conventions as fallback).\n\nimport { readFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { applyPiHost } from './host.js'\nimport { registerVisionCompanions } from './runtime.js'\nimport { resolvePiPackage } from './source.js'\n\nexport interface EngineConfig {\n /** Mount exactly these packages (skips discovery). */\n packages?: string[]\n /** Never mount these packages even when discovered. */\n exclude?: string[]\n /**\n * Image-admission companion routes: `{ <existingRoute>: [modelIds] }`\n * registers `<route>-vision` — it admits pasted images, hands them to a\n * mounted vision extension through the turn's entering messages, and\n * forwards text-only to the original route.\n */\n visionCompanions?: Record<string, readonly string[]>\n}\n\n/** Locate the DSH profile root: the nearest ancestor holding cordis.yml. */\nexport function findProfileRoot(start: string): string | undefined {\n let dir = start\n for (;;) {\n if (existsSync(join(dir, 'cordis.yml')) && existsSync(join(dir, 'package.json'))) return dir\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\ninterface DiscoveredPackage {\n name: string\n dir: string\n}\n\nfunction resolveDependencyDir(profileRoot: string, name: string): string | undefined {\n // Direct dependencies of the profile live under its node_modules by name\n // (pnpm links them there); resolving by path needs no exports gymnastics.\n const dir = join(profileRoot, 'node_modules', name)\n return existsSync(join(dir, 'package.json')) ? dir : undefined\n}\n\n/**\n * The profile's direct dependencies that identify as Pi packages: not the\n * engine itself, not a `dsh.bundle` (those are DSH plugins, not Pi\n * packages), carrying either Pi's `pi` manifest field or extension sources\n * under Pi's directory conventions.\n */\nexport async function discoverProfilePiPackages(\n profileRoot: string,\n options: { exclude?: string[], warn?: (message: string) => void } = {},\n): Promise<DiscoveredPackage[]> {\n const warn = options.warn ?? (() => {})\n const excluded = new Set(options.exclude ?? [])\n const manifestText = await readFile(join(profileRoot, 'package.json'), 'utf8')\n const manifest = JSON.parse(manifestText) as { dependencies?: Record<string, string> }\n const discovered: DiscoveredPackage[] = []\n for (const name of Object.keys(manifest.dependencies ?? {})) {\n if (name === 'pi2dsh' || excluded.has(name)) continue\n const dir = resolveDependencyDir(profileRoot, name)\n if (dir === undefined) {\n warn(`[pi2dsh engine] dependency ${JSON.stringify(name)} is not installed under the profile; skipping`)\n continue\n }\n let packageJson: Record<string, unknown>\n try {\n packageJson = JSON.parse(await readFile(join(dir, 'package.json'), 'utf8')) as Record<string, unknown>\n } catch (error) {\n warn(`[pi2dsh engine] cannot read ${name}/package.json (${error instanceof Error ? error.message : String(error)}); skipping`)\n continue\n }\n // A dsh.bundle-declaring package is a DSH plugin layer, never a Pi package.\n if ((packageJson.dsh as { bundle?: unknown } | undefined)?.bundle !== undefined) continue\n if (packageJson.pi !== undefined && typeof packageJson.pi === 'object') {\n discovered.push({ name, dir })\n continue\n }\n // No `pi` field: fall back to Pi's directory conventions via the same\n // resolver every other mount path uses (a package with zero extension\n // sources is a plain library and stays unmounted).\n try {\n const pkg = await resolvePiPackage(dir)\n try {\n if (pkg.resources.extensions.length > 0) discovered.push({ name, dir })\n } finally {\n await pkg.dispose()\n }\n } catch {\n // Not resolvable as a Pi package — a plain library.\n }\n }\n return discovered\n}\n\n/** Cordis plugin surface: `dsh plugin add pi2dsh` mounts this. */\nexport const name = 'pi2dsh'\nexport const inject = ['tools', 'systemPrompt', 'commands', 'skills']\n\nexport async function apply(ctx: Context, config: EngineConfig = {}): Promise<void> {\n // Same emission as the runtime's logger helper: the cordis logger AND the\n // console — profile logger levels must never hide what the engine mounted.\n const log = (ctx as unknown as { logger?: { info?(m: string): void, warn?(m: string): void } }).logger\n const warn = (message: string): void => { log?.warn?.(message); console.warn(message) }\n const info = (message: string): void => { log?.info?.(message); console.log(message) }\n\n // The loader resolves plugins against the profile's baseUrl; that IS the\n // profile root. The ancestor walk from the installed engine is the\n // fallback for compositions without a loader (tests, hand-built hosts).\n const baseUrl = (ctx as unknown as { baseUrl?: string }).baseUrl\n const profileRoot = (baseUrl !== undefined ? findProfileRoot(fileURLToPath(new URL('.', baseUrl))) : undefined)\n ?? findProfileRoot(dirname(fileURLToPath(import.meta.url)))\n if (profileRoot === undefined) {\n throw new Error('pi2dsh engine: no DSH profile root (cordis.yml + package.json) above the installed engine — is pi2dsh installed via `dsh plugin add pi2dsh`?')\n }\n\n const packages = Array.isArray(config.packages) && config.packages.length > 0\n ? config.packages.map(name => ({ name }))\n : await discoverProfilePiPackages(profileRoot, {\n ...(Array.isArray(config.exclude) ? { exclude: config.exclude } : {}),\n warn,\n })\n if (packages.length === 0) {\n // Companion routes are the bridge's own capability — they work with\n // zero Pi packages installed.\n registerVisionCompanions(ctx, config.visionCompanions)\n info('[pi2dsh engine] no Pi packages installed in this profile yet — add one with: dsh plugin --profile <p> add <pi-package>')\n return\n }\n info(`[pi2dsh engine] mounting ${packages.length} Pi package(s): ${packages.map(pkg => pkg.name).join(', ')}`)\n await applyPiHost(\n ctx,\n {\n packages: packages.map(pkg => ({ name: pkg.name })),\n ...(config.visionCompanions === undefined ? {} : { visionCompanions: config.visionCompanions }),\n },\n join(profileRoot, 'package.json'),\n )\n}\n","// Engine surface: `dsh plugin add pi2dsh` resolves this entry as a cordis\n// plugin (named exports, no default — a default export would make the\n// loader discard the function-plugin namespace).\nexport { apply, inject, name, discoverProfilePiPackages, findProfileRoot, type EngineConfig } from './engine.js'\n\n// CLI-only analysis surfaces load lazily: their static-analysis dependency\n// (the 23 MB typescript compiler, an optional peer) must never be pulled\n// into a profile that installs the ENGINE. The dynamic imports below keep\n// analyzer/generator in their own chunks, off the engine's load path.\nimport type { CompatibilityReport, ResolvedPiPackage } from './types.js'\n\n/**\n * Static compatibility analysis of one resolved Pi package (CLI `inspect`).\n * @param pkg - the resolved package.\n * @returns the compatibility report.\n */\nexport async function analyzePackage(pkg: ResolvedPiPackage): Promise<CompatibilityReport> {\n const { analyzePackage: run } = await import('./analyzer.js')\n return run(pkg)\n}\n\n/**\n * Generate a vendored per-package bundle (CLI `convert`).\n * @param options - generation options (see the generator module).\n * @returns the generation result.\n */\nexport async function generateBundle(...args: Parameters<typeof import('./generator.js').generateBundle>): ReturnType<typeof import('./generator.js').generateBundle> {\n const { generateBundle: run } = await import('./generator.js')\n return run(...args)\n}\nexport {\n API_RULES,\n CONTEXT_RULES,\n EVENT_RULES,\n HOST_IMPORT_RULES,\n PI_AI_PACKAGES,\n PI_CODING_AGENT_PACKAGES,\n PI_TUI_PACKAGES,\n UI_CONTEXT_RULES,\n ruleForApi,\n ruleForContextProperty,\n ruleForEvent,\n ruleForHostImport,\n ruleForUiContextProperty,\n} from './compatibility.js'\nexport { applyPiHost, generateHostBundle, manifestForInstalled } from './host.js'\nexport { collectPiMcpServers, convertPiMcpConfig, renderMcpPatch } from './mcp-config.js'\nexport { resolvePiPackage } from './source.js'\nexport type * from './types.js'\n"],"mappings":"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"}
|