pi2dsh 0.12.0 → 0.12.2

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.
@@ -1,5 +1,6 @@
1
1
 
2
2
  import { a as GeneratedRuntimeManifest } from "./types-7IWJPPvS.mjs";
3
+ import { ContentBlock } from "@deepseek-ai/dsh-llm";
3
4
  import { Context } from "@deepseek-ai/cordis";
4
5
  //#region src/runtime.d.ts
5
6
  type UnknownRecord = Record<string, unknown>;
@@ -17,6 +18,35 @@ declare function normalizeToolSchema(schema: unknown): {
17
18
  schema: UnknownRecord;
18
19
  warnings: string[];
19
20
  };
21
+ declare function isSubagentOrigin(subject: UnknownRecord | undefined): boolean;
22
+ /**
23
+ * What triggered a compaction, in Pi's vocabulary.
24
+ *
25
+ * DSH's durable lifecycle events say two things about the trigger: a manual
26
+ * compaction runs with no open turn (`turn: null`), and one a command drove
27
+ * cites that command. Both are Pi's "manual".
28
+ *
29
+ * The limit, stated rather than papered over: DSH's automatic trigger is
30
+ * `'pressure' | 'context-overflow'` at the call site but is NOT written to the
31
+ * log, so Pi's `threshold` and `overflow` cannot be told apart after the fact.
32
+ * Automatic compactions report `threshold`, the far more common of the two —
33
+ * and `willRetry` stays false for the same reason. A package keying behavior
34
+ * on `overflow` specifically will not see it.
35
+ * @param data - the `compaction/start` or `compaction/summary` event data.
36
+ */
37
+ declare function compactionReason(data: UnknownRecord): 'manual' | 'threshold' | 'overflow';
38
+ /**
39
+ * DSH content → the Pi content blocks packages read.
40
+ *
41
+ * Asynchronous because Pi's image block carries the bytes inline while DSH's
42
+ * carries only an attachment reference, and the bytes come from the attachment
43
+ * service. The sync version this replaced projected an image as a bare
44
+ * `{type:'image'}` — a block that announces an image and contains none, which
45
+ * is the exact shape a package cannot tell from a real one.
46
+ * @param ctx - context used to reach the attachment service.
47
+ * @param content - the DSH blocks to project.
48
+ */
49
+ declare function dshToPiContent(ctx: Context, content: readonly ContentBlock[]): Promise<Array<UnknownRecord>>;
20
50
  /** Companion configuration: default (auto), `false` (off), or an explicit narrow map. */
21
51
  type VisionCompanionsConfig = false | Record<string, readonly string[]> | undefined;
22
52
  /**
@@ -41,7 +71,10 @@ declare function splitArguments(input: string): string[];
41
71
  declare function expandPrompt(text: string, rawInput: string): string;
42
72
  declare function applyPiPackage(ctx: Context, options: RuntimeOptions): Promise<void>;
43
73
  declare const runtimeInternals: {
74
+ compactionReason: typeof compactionReason;
75
+ dshToPiContent: typeof dshToPiContent;
44
76
  expandPrompt: typeof expandPrompt;
77
+ isSubagentOrigin: typeof isSubagentOrigin;
45
78
  normalizeToolResult: typeof normalizeToolResult;
46
79
  splitArguments: typeof splitArguments;
47
80
  textBlocks: typeof textBlocks;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/runtime.ts"],"mappings":";;;;KAkCK,gBAAgB;UAGX;EACR,SAAS;EACT,UAAU;EACV,SAAS;;iBAuJF,WAAW,mBAAmB;EAAQ;EAAc;;iBAcpD,oBAAoB,kBAAkB;iBAuH/B,oBAAoB;EAAoB,QAAQ;EAAe;;;KA+xCnE,iCAAiC;;;;;;;;;;;;;;;;;;iBAmB7B,yBAAyB,KAAK,SAAS,QAAQ;iBAmrBtD,eAAe;iBA+Bf,aAAa,cAAc;iBA2Id,eAAe,KAAK,SAAS,SAAS,iBAAiB;cAsKhE"}
1
+ {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/runtime.ts"],"mappings":";;;;;KAmCK,gBAAgB;UAGX;EACR,SAAS;EACT,UAAU;EACV,SAAS;;iBAkLF,WAAW,mBAAmB;EAAQ;EAAc;;iBAcpD,oBAAoB,kBAAkB;iBAuH/B,oBAAoB;EAAoB,QAAQ;EAAe;;iBA8EtE,iBAAiB,SAAS;;;;;;;;;;;;;;;;iBAquB1B,iBAAiB,MAAM;;;;;;;;;;;;iBAgBjB,eAAe,KAAK,SAAS,kBAAkB,iBAAiB,QAAQ,MAAM;;KA2tBjF,iCAAiC;;;;;;;;;;;;;;;;;;iBAmB7B,yBAAyB,KAAK,SAAS,QAAQ;iBAo6BtD,eAAe;iBA+Bf,aAAa,cAAc;iBA2Id,eAAe,KAAK,SAAS,SAAS,iBAAiB;cA4KhE"}
package/dist/runtime.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
 
2
- import { i as runtimeInternals, n as normalizeToolSchema, r as registerVisionCompanions, t as applyPiPackage } from "./runtime-Bh5k4Kjt.mjs";
2
+ import { i as runtimeInternals, n as normalizeToolSchema, r as registerVisionCompanions, t as applyPiPackage } from "./runtime-DsPaznXJ.mjs";
3
3
  export { applyPiPackage, normalizeToolSchema, registerVisionCompanions, runtimeInternals };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi2dsh",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "description": "Bridge the Pi and DeepSeek Harness ecosystems: a general Pi Host ABI that runs unmodified Pi extensions as native DSH plugins, plus per-package conversion and MCP config translation.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -39,19 +39,21 @@
39
39
  "LICENSE"
40
40
  ],
41
41
  "scripts": {
42
+ "audit:community": "pnpm build && node scripts/audit-community.mjs",
42
43
  "build": "tsdown",
43
- "prepare": "tsdown",
44
44
  "check": "tsc --noEmit",
45
+ "check:docs": "pnpm build && node scripts/generate-capability-docs.mjs --check",
46
+ "check:pack": "pnpm build && publint && node scripts/check-pack.mjs",
47
+ "docs:capabilities": "node scripts/generate-capability-docs.mjs",
48
+ "prepare": "tsdown",
45
49
  "test": "pnpm build && vitest run",
50
+ "test:community": "pnpm build && node scripts/verify-community.mjs --generate community/runtime-results.json",
46
51
  "test:coverage": "pnpm build && vitest run --coverage",
47
52
  "test:dsh": "pnpm build && vitest run tests/dsh-runtime.spec.ts tests/generated-bundle.spec.ts",
48
- "audit:community": "pnpm build && node scripts/audit-community.mjs",
49
- "test:community": "pnpm build && node scripts/verify-community.mjs --generate community/runtime-results.json",
53
+ "test:examples": "pnpm build && node scripts/verify-examples-e2e.mjs",
50
54
  "test:live": "pnpm build && node scripts/verify-live-deepseek.mjs community/live-deepseek-results.json",
51
- "check:pack": "pnpm build && publint && node scripts/check-pack.mjs",
52
- "verify": "pnpm check && pnpm test:coverage && pnpm check:docs && pnpm check:pack",
53
- "docs:capabilities": "node scripts/generate-capability-docs.mjs",
54
- "check:docs": "pnpm build && node scripts/generate-capability-docs.mjs --check"
55
+ "test:seams": "pnpm build && node scripts/verify-step-seams-e2e.mjs",
56
+ "verify": "pnpm check && pnpm test:coverage && pnpm check:docs && pnpm check:pack"
55
57
  },
56
58
  "keywords": [
57
59
  "deepseek-harness",
@@ -95,6 +97,7 @@
95
97
  "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6",
96
98
  "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
97
99
  "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
100
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
98
101
  "@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.6",
99
102
  "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6",
100
103
  "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
@@ -1,298 +0,0 @@
1
-
2
- import { analyzePackage, n as collectLocalClosure, r as runtimeExternalPackages, t as SCRIPT_EXTENSIONS } from "./analyzer-CsrBeS8r.mjs";
3
- import { cp, lstat, mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
4
- import { basename, dirname, extname, join, relative, resolve } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import { parse } from "yaml";
7
- //#region src/generator.ts
8
- const SHIMMED_PI_HOST_PACKAGES = /* @__PURE__ */ new Set([
9
- "@earendil-works/pi-coding-agent",
10
- "@mariozechner/pi-coding-agent",
11
- "@earendil-works/pi-tui",
12
- "@mariozechner/pi-tui",
13
- "@earendil-works/pi-ai",
14
- "@mariozechner/pi-ai",
15
- "typebox",
16
- "@sinclair/typebox"
17
- ]);
18
- function packageSlug(name) {
19
- return name.replace(/^@/u, "").replaceAll("/", "-").replace(/[^a-zA-Z0-9._-]+/gu, "-").toLowerCase().replace(/^-+|-+$/gu, "") || "package";
20
- }
21
- function stringRecord(value) {
22
- if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
23
- return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string"));
24
- }
25
- async function assertEmptyOrMissing(path) {
26
- try {
27
- if (!(await stat(path)).isDirectory()) throw new Error(`output exists and is not a directory: ${path}`);
28
- if ((await readdir(path)).length > 0) throw new Error(`output directory is not empty: ${path}`);
29
- } catch (error) {
30
- if (error.code !== "ENOENT") throw error;
31
- }
32
- }
33
- function parseFrontmatter(text) {
34
- const normalized = text.replace(/\r\n?/gu, "\n");
35
- if (!normalized.startsWith("---")) return {
36
- attributes: {},
37
- body: normalized
38
- };
39
- const endIndex = normalized.indexOf("\n---", 3);
40
- if (endIndex === -1) return {
41
- attributes: {},
42
- body: normalized
43
- };
44
- const raw = parse(normalized.slice(4, endIndex));
45
- return {
46
- attributes: typeof raw === "object" && raw !== null && !Array.isArray(raw) ? stringRecord(raw) : {},
47
- body: normalized.slice(endIndex + 4).trim()
48
- };
49
- }
50
- async function assertNoSymlinks(path) {
51
- const info = await lstat(path);
52
- if (info.isSymbolicLink()) throw new Error(`refusing to copy symbolic link from Pi package: ${path}`);
53
- if (!info.isDirectory()) return;
54
- for (const entry of await readdir(path)) await assertNoSymlinks(join(path, entry));
55
- }
56
- async function copyExtensions(pkg, outDir) {
57
- const copied = [];
58
- const runtimePackages = /* @__PURE__ */ new Set();
59
- const closure = await collectLocalClosure(pkg.rootDir, pkg.resources.extensions);
60
- for (const issue of closure.issues) 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"})`);
61
- for (const source of closure.files) {
62
- if (SCRIPT_EXTENSIONS.has(extname(source))) {
63
- const text = await readFile(source, "utf8");
64
- const lazyFile = !closure.loadTimeFiles.has(source);
65
- for (const use of runtimeExternalPackages(source, text)) if (!use.lazy && !lazyFile || use.name in stringRecord(pkg.packageJson.dependencies)) runtimePackages.add(use.name);
66
- }
67
- const targetRelative = `vendor/${relative(pkg.rootDir, source).replaceAll("\\", "/")}`;
68
- const target = join(outDir, targetRelative);
69
- await mkdir(dirname(target), { recursive: true });
70
- await cp(source, target, { dereference: false });
71
- if (pkg.resources.extensions.map((entry) => resolve(entry)).includes(source)) copied.push(targetRelative);
72
- }
73
- const skillScriptPackages = /* @__PURE__ */ new Set();
74
- for (const source of pkg.resources.skills) {
75
- if (!SCRIPT_EXTENSIONS.has(extname(source))) continue;
76
- const text = await readFile(source, "utf8");
77
- for (const use of runtimeExternalPackages(source, text)) skillScriptPackages.add(use.name);
78
- }
79
- return {
80
- entries: copied,
81
- runtimePackages,
82
- skillScriptPackages
83
- };
84
- }
85
- async function copySkills(pkg, outDir) {
86
- const entryFiles = pkg.resources.skills.filter((file) => basename(file) === "SKILL.md" || file.endsWith(".md"));
87
- if (entryFiles.length === 0) return [];
88
- const names = /* @__PURE__ */ new Set();
89
- for (const entry of entryFiles) {
90
- const isBundle = basename(entry) === "SKILL.md";
91
- let name = isBundle ? basename(dirname(entry)) : basename(entry, ".md");
92
- if (names.has(name)) {
93
- const candidate = `${basename(dirname(isBundle ? dirname(entry) : entry))}-${name}`.replace(/[^a-zA-Z0-9._-]+/gu, "-");
94
- name = names.has(candidate) ? `${candidate}-${names.size}` : candidate;
95
- }
96
- names.add(name);
97
- const target = join(outDir, "skills", isBundle ? name : `${name}.md`);
98
- await mkdir(dirname(target), { recursive: true });
99
- const source = isBundle ? dirname(entry) : entry;
100
- await assertNoSymlinks(source);
101
- await cp(source, target, {
102
- recursive: isBundle,
103
- dereference: false
104
- });
105
- }
106
- return ["skills"];
107
- }
108
- async function copyPrompts(pkg, outDir) {
109
- const prompts = [];
110
- const names = /* @__PURE__ */ new Set();
111
- for (const source of pkg.resources.prompts) {
112
- const name = basename(source, ".md").toLowerCase().replace(/[^a-z0-9_-]+/gu, "-");
113
- if (names.has(name)) throw new Error(`prompt command name collision while flattening Pi package: ${name}`);
114
- names.add(name);
115
- const targetRelative = `prompts/${name}.md`;
116
- const target = join(outDir, targetRelative);
117
- await mkdir(dirname(target), { recursive: true });
118
- await assertNoSymlinks(source);
119
- await cp(source, target, { dereference: false });
120
- const { attributes, body } = parseFrontmatter(await readFile(source, "utf8"));
121
- const firstLine = body.split(/\r?\n/u).map((line) => line.trim()).find(Boolean);
122
- prompts.push({
123
- name,
124
- description: attributes.description ?? firstLine ?? `Run migrated Pi prompt ${name}`,
125
- ...attributes["argument-hint"] !== void 0 ? { argumentHint: attributes["argument-hint"] } : {},
126
- path: targetRelative
127
- });
128
- }
129
- return prompts;
130
- }
131
- async function copyNotices(pkg, outDir) {
132
- const copied = [];
133
- for (const entry of await readdir(pkg.rootDir)) {
134
- if (!/^(?:licen[cs]e|notice|copying)(?:[._-].*)?$/iu.test(entry)) continue;
135
- const source = join(pkg.rootDir, entry);
136
- const info = await lstat(source);
137
- if (info.isSymbolicLink()) throw new Error(`refusing to copy symbolic link from Pi package: ${source}`);
138
- if (!info.isFile()) continue;
139
- await cp(source, join(outDir, entry), { dereference: false });
140
- copied.push(entry);
141
- }
142
- return copied.sort();
143
- }
144
- function generatedPackageJson(pkg, generatedName, runtimeSpec, runtimePackages, hasSkills) {
145
- const declaredDependencies = {
146
- ...stringRecord(pkg.packageJson.dependencies),
147
- ...stringRecord(pkg.packageJson.optionalDependencies),
148
- ...stringRecord(pkg.packageJson.peerDependencies)
149
- };
150
- const externalRuntimePackages = [...runtimePackages].filter((name) => !SHIMMED_PI_HOST_PACKAGES.has(name));
151
- const missing = externalRuntimePackages.filter((name) => declaredDependencies[name] === void 0);
152
- if (missing.length > 0) throw new Error(`runtime dependencies are imported but not declared by the Pi package: ${missing.join(", ")}`);
153
- const declaredRuntime = {
154
- ...stringRecord(pkg.packageJson.dependencies),
155
- ...stringRecord(pkg.packageJson.optionalDependencies)
156
- };
157
- const dependencies = {
158
- ...Object.fromEntries(Object.entries(declaredRuntime).filter(([name]) => !SHIMMED_PI_HOST_PACKAGES.has(name))),
159
- ...Object.fromEntries(externalRuntimePackages.sort().map((name) => [name, declaredDependencies[name]])),
160
- ...runtimeSpec === void 0 ? {
161
- jiti: "^2.7.0",
162
- "get-east-asian-width": "^1.6.0",
163
- marked: "^16.4.1",
164
- typebox: "^1.0.4",
165
- "cross-spawn": "^7.0.6",
166
- diff: "^9.0.0"
167
- } : {},
168
- openai: "^6.40.0",
169
- ...hasSkills ? { "@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.6" } : {},
170
- ...runtimeSpec !== void 0 ? { pi2dsh: runtimeSpec } : {}
171
- };
172
- const remapImports = (value) => {
173
- if (typeof value === "string") return value.startsWith("./") ? `./vendor/${value.slice(2)}` : value;
174
- if (typeof value === "object" && value !== null && !Array.isArray(value)) return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, remapImports(entry)]));
175
- return value;
176
- };
177
- const sourceImports = pkg.packageJson.imports;
178
- return {
179
- name: generatedName,
180
- version: pkg.identity.version,
181
- description: `DeepSeek Harness adapter generated from ${pkg.identity.name}`,
182
- type: "module",
183
- main: "./index.js",
184
- ...typeof sourceImports === "object" && sourceImports !== null ? { imports: remapImports(sourceImports) } : {},
185
- files: [
186
- "index.js",
187
- "cordis.patch.yml",
188
- "pi2dsh.manifest.json",
189
- "pi2dsh.report.json",
190
- "README.md",
191
- "LICENSE*",
192
- "NOTICE*",
193
- "COPYING*",
194
- "PI2DSH-LICENSE",
195
- "runtime",
196
- "vendor",
197
- "skills",
198
- "prompts"
199
- ],
200
- dependencies,
201
- ...runtimeSpec === void 0 ? { peerDependencies: {
202
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
203
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6"
204
- } } : {},
205
- keywords: [
206
- "dsh-plugin",
207
- "deepseek-harness",
208
- "pi-package",
209
- "pi2dsh"
210
- ],
211
- license: typeof pkg.packageJson.license === "string" ? pkg.packageJson.license : "UNLICENSED",
212
- dsh: { bundle: { patch: "./cordis.patch.yml" } }
213
- };
214
- }
215
- function generatedReadme(pkg, packageName, report) {
216
- return `# ${packageName}\n\nGenerated by [pi2dsh](https://github.com/weijiafu14/pi2dsh) from \`${pkg.identity.name}@${pkg.identity.version}\`.\n\nCompatibility verdict: **${report.verdict}** (full ${report.summary.full}, partial ${report.summary.partial}, unsupported ${report.summary.unsupported}).\n\nReview \`pi2dsh.report.json\` before installation. This bundle executes the original Pi extension source and should only be installed when that source is trusted.\n\nInstall with DeepSeek Harness (keep the \`file:\` prefix so pnpm installs this bundle's dependencies instead of creating a bare link):\n\n\`\`\`sh\ndsh plugin --profile headless add file:$PWD\ndsh --profile headless --dump-config\n\`\`\`\n\nIf 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`;
217
- }
218
- function pluginSource(manifest, runtimeImport) {
219
- const injections = ["tools", "systemPrompt"];
220
- if (manifest.prompts.length > 0 || manifest.report?.findings.some((item) => item.capability === "registerCommand") === true) injections.push("commands");
221
- if (manifest.skillDirs.length > 0) injections.push("skills");
222
- return `import { applyPiPackage } from ${JSON.stringify(runtimeImport)}\n\nexport const name = ${JSON.stringify(`pi2dsh:${packageSlug(manifest.package.name)}`)}\nexport const inject = ${JSON.stringify(injections)}\n\nconst manifest = ${JSON.stringify(manifest, null, 2)}\n\nexport async function apply(ctx, config = {}) {\n await applyPiPackage(ctx, { rootUrl: new URL('.', import.meta.url), manifest, config })\n}\n`;
223
- }
224
- async function firstExisting(paths) {
225
- for (const path of paths) try {
226
- await stat(path);
227
- return path;
228
- } catch {}
229
- throw new Error(`cannot locate pi2dsh runtime artifact; tried: ${paths.join(", ")}`);
230
- }
231
- async function copyEmbeddedRuntime(outDir) {
232
- const moduleDir = dirname(fileURLToPath(import.meta.url));
233
- const runtimeSource = await firstExisting([join(moduleDir, "runtime.mjs"), join(moduleDir, "../dist/runtime.mjs")]);
234
- const runtimeRoot = dirname(runtimeSource);
235
- const targetRoot = join(outDir, "runtime");
236
- await mkdir(targetRoot, { recursive: true });
237
- for (const entry of await readdir(runtimeRoot)) if (entry.endsWith(".mjs")) await cp(join(runtimeRoot, entry), join(targetRoot, entry));
238
- for (const sub of ["compat", join("compat", "vendor")]) {
239
- const sourceDir = join(runtimeRoot, sub);
240
- try {
241
- const entries = await readdir(sourceDir);
242
- await mkdir(join(targetRoot, sub), { recursive: true });
243
- for (const entry of entries) if (entry.endsWith(".mjs")) await cp(join(sourceDir, entry), join(targetRoot, sub, entry));
244
- } catch {}
245
- }
246
- await cp(join(targetRoot, "runtime.mjs"), join(targetRoot, "pi2dsh-runtime.mjs"));
247
- const license = await firstExisting([join(moduleDir, "../LICENSE"), join(moduleDir, "../../LICENSE")]);
248
- await cp(license, join(outDir, "PI2DSH-LICENSE"));
249
- }
250
- function patchSource(generatedName, slug) {
251
- return `- insert:\n - id: pi2dsh-${slug}\n name: ${JSON.stringify(generatedName)}\n`;
252
- }
253
- function enforceReport(report, options) {
254
- if (report.summary.fatal > 0) throw new Error(`conversion blocked: ${report.summary.fatal} fatal finding(s) — the bundle cannot be built or trusted; run inspect for details`);
255
- if (options.strict && (report.summary.partial > 0 || report.summary.unsupported > 0)) throw new Error("strict conversion requires every detected Pi API use to have full compatibility");
256
- }
257
- async function generateBundle(pkg, options) {
258
- const outDir = resolve(options.outDir);
259
- const report = await analyzePackage(pkg);
260
- enforceReport(report, options);
261
- await assertEmptyOrMissing(outDir);
262
- await mkdir(outDir, { recursive: true });
263
- const slug = packageSlug(pkg.identity.name);
264
- const packageName = `dsh-pi-${slug}`;
265
- const extensionSnapshot = await copyExtensions(pkg, outDir);
266
- const skillDirs = await copySkills(pkg, outDir);
267
- const prompts = await copyPrompts(pkg, outDir);
268
- await copyNotices(pkg, outDir);
269
- const manifest = {
270
- schemaVersion: 1,
271
- package: pkg.identity,
272
- extensions: extensionSnapshot.entries,
273
- skillDirs,
274
- prompts,
275
- report
276
- };
277
- const runtimeSpec = options.runtimeSpec;
278
- if (runtimeSpec === void 0) await copyEmbeddedRuntime(outDir);
279
- const optionalSkillDeps = [...extensionSnapshot.skillScriptPackages].filter((name) => !SHIMMED_PI_HOST_PACKAGES.has(name) && !(name in stringRecord(pkg.packageJson.dependencies)));
280
- if (optionalSkillDeps.length > 0) console.warn(`pi2dsh: skill helper scripts reference ${optionalSkillDeps.join(", ")}; install them only if you use those skills`);
281
- await Promise.all([
282
- writeFile(join(outDir, "package.json"), `${JSON.stringify(generatedPackageJson(pkg, packageName, runtimeSpec, extensionSnapshot.runtimePackages, skillDirs.length > 0), null, 2)}\n`),
283
- writeFile(join(outDir, "pi2dsh.manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`),
284
- writeFile(join(outDir, "pi2dsh.report.json"), `${JSON.stringify(report, null, 2)}\n`),
285
- writeFile(join(outDir, "index.js"), pluginSource(manifest, runtimeSpec === void 0 ? "./runtime/pi2dsh-runtime.mjs" : "pi2dsh/runtime")),
286
- writeFile(join(outDir, "cordis.patch.yml"), patchSource(packageName, slug)),
287
- writeFile(join(outDir, "README.md"), generatedReadme(pkg, packageName, report))
288
- ]);
289
- return {
290
- outDir,
291
- report,
292
- packageName
293
- };
294
- }
295
- //#endregion
296
- export { generateBundle };
297
-
298
- //# sourceMappingURL=generator-CSOv6wYT.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generator-CSOv6wYT.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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mcp-config-Cn5gWemZ.mjs","names":[],"sources":["../src/compatibility.ts","../src/mcp-config.ts"],"sourcesContent":["import type { CompatibilityLevel } from './types.js'\n\ninterface Rule {\n level: CompatibilityLevel\n detail: string\n}\n\nconst rule = (level: CompatibilityLevel, detail: string): Rule => ({ level, detail })\n\nexport const PI_CODING_AGENT_PACKAGES = Object.freeze([\n '@earendil-works/pi-coding-agent',\n '@mariozechner/pi-coding-agent',\n] as const)\n\nexport const PI_TUI_PACKAGES = Object.freeze([\n '@earendil-works/pi-tui',\n '@mariozechner/pi-tui',\n] as const)\n\nexport const PI_AI_PACKAGES = Object.freeze([\n '@earendil-works/pi-ai',\n '@mariozechner/pi-ai',\n] as const)\n\nconst VENDORED = 'Vendored byte-identical from Pi, so semantics match Pi exactly.'\nconst HEADLESS_COMPONENT = 'Constructible headless component with Pi-exact signatures; renders plain text, never a terminal.'\nconst VENDORED_TOOL = 'Pi\\'s built-in tool constructor, vendored byte-identical with its pure-logic closure.'\nconst EVENT_GUARD = 'Pi\\'s exact one-line tool-event guard, reimplemented verbatim.'\nconst VENDORED_SUMMARIZER = 'Vendored Pi logic; the model call fills Pi\\'s own streamFn injection point with the DSH llm bridge when the caller passes none, so summarization runs on the ONE model path. Without a mounted llm service it fails explicitly.'\n\nexport const HOST_IMPORT_RULES: Readonly<Record<string, Readonly<Record<string, Rule>>>> = Object.freeze({\n 'pi-coding-agent': Object.freeze({\n defineTool: rule('full', 'Identity helper, preserved.'),\n CONFIG_DIR_NAME: rule('partial', 'The conventional config directory name is preserved, while DSH owns the actual profile layout.'),\n DEFAULT_MAX_LINES: rule('full', VENDORED),\n DEFAULT_MAX_BYTES: rule('full', VENDORED),\n VERSION: rule('partial', 'Reports a pi2dsh compatibility marker instead of a Pi release version.'),\n CURRENT_SESSION_VERSION: rule('full', VENDORED),\n getAgentDir: rule('partial', 'Redirected to an isolated DSH-owned pi2dsh directory instead of Pi global state.'),\n getPackageDir: rule('partial', 'Resolves inside the DSH-owned pi2dsh agent directory.'),\n formatSize: rule('full', VENDORED),\n truncateHead: rule('full', VENDORED),\n truncateTail: rule('full', VENDORED),\n truncateLine: rule('full', VENDORED),\n withFileMutationQueue: rule('full', VENDORED),\n SessionManager: rule('full', `${VENDORED} Sessions live under the DSH-owned pi2dsh agent directory.`),\n parseSessionEntries: rule('full', VENDORED),\n migrateSessionEntries: rule('full', VENDORED),\n getLatestCompactionEntry: rule('full', VENDORED),\n sessionEntryToContextMessages: rule('full', VENDORED),\n buildContextEntries: rule('full', VENDORED),\n buildSessionContext: rule('full', VENDORED),\n loadEntriesFromFile: rule('full', VENDORED),\n findMostRecentSession: rule('full', VENDORED),\n getDefaultSessionDir: rule('full', VENDORED),\n assertValidSessionId: rule('full', VENDORED),\n convertToLlm: rule('full', VENDORED),\n createCustomMessage: rule('full', VENDORED),\n createBranchSummaryMessage: rule('full', VENDORED),\n createCompactionSummaryMessage: rule('full', VENDORED),\n bashExecutionToText: rule('full', VENDORED),\n estimateTokens: rule('full', VENDORED),\n calculateContextTokens: rule('full', `${VENDORED} Pi\\'s Usage-based total (an earlier reimplementation summed message estimates — same name, different meaning — and was replaced).`),\n DEFAULT_COMPACTION_SETTINGS: rule('full', VENDORED),\n serializeConversation: rule('full', VENDORED),\n shouldCompact: rule('full', `${VENDORED} The pure threshold check; DSH still owns automatic compaction scheduling.`),\n compact: rule('partial', VENDORED_SUMMARIZER),\n findCutPoint: rule('full', VENDORED),\n generateSummary: rule('partial', VENDORED_SUMMARIZER),\n generateSummaryWithUsage: rule('partial', VENDORED_SUMMARIZER),\n generateBranchSummary: rule('partial', VENDORED_SUMMARIZER),\n parseFrontmatter: rule('full', `${VENDORED} Returns Pi\\'s public { frontmatter, body } shape with YAML-parsed values (an earlier reimplementation returned { attributes } with string values and was replaced).`),\n stripFrontmatter: rule('full', VENDORED),\n copyToClipboard: rule('partial', 'Attempts the platform clipboard command (pbcopy/clip/wl-copy/xclip); resolves false when none succeeds.'),\n resizeImage: rule('partial', 'Passes images through un-resized; Pi resizes only to save tokens, so content is preserved.'),\n convertToPng: rule('partial', 'PNG input passes through; other formats fail explicitly without Pi\\'s wasm codec.'),\n getShellConfig: rule('partial', 'Standard shell detection without Pi\\'s managed-bin PATH handling.'),\n getBinDir: rule('partial', 'Reports the first PATH segment instead of Pi\\'s managed bin directory.'),\n Theme: rule('partial', 'Headless theme: styling calls return their input text unstyled.'),\n theme: rule('partial', 'A headless theme singleton; jiti-loaded Pi extensions must not rely on Pi global theme state anyway.'),\n initTheme: rule('partial', 'Accepted as a no-op; DSH surfaces own presentation.'),\n getSettingsListTheme: rule('partial', 'Returns an unstyled theme with Pi\\'s exact field shape.'),\n getSelectListTheme: rule('partial', 'Returns an unstyled theme with Pi\\'s exact field shape.'),\n getMarkdownTheme: rule('partial', 'Returns a plain-text headless theme; Pi terminal styling is intentionally discarded.'),\n getLanguageFromPath: rule('partial', 'Extension-based language detection covering common languages.'),\n highlightCode: rule('partial', 'Splits lines without terminal syntax colors.'),\n DynamicBorder: rule('full', 'Headless implementation of Pi\\'s one-line border component; pass an explicit color function as Pi itself recommends.'),\n SettingsManager: rule('partial', 'In-memory settings with Pi\\'s getter/setter surface; DSH owns real persisted configuration.'),\n InMemorySettingsStorage: rule('partial', 'In-memory storage stub honoring the withLock contract.'),\n FileSettingsStorage: rule('partial', 'Alias of the in-memory storage; DSH owns persisted settings.'),\n ModelRegistry: rule('partial', 'A local registry container; DSH llm adapters own real model routing.'),\n createEventBus: rule('full', 'Pi event-bus semantics: async handler isolation and unsubscribe functions.'),\n readStoredCredential: rule('partial', 'Reads Pi-style auth.json from the pi2dsh-owned agent directory; DSH credentials stay authoritative for DSH model calls.'),\n parseSkillBlock: rule('full', 'Pi\\'s skill_content block parser, reimplemented over the same wire shape.'),\n wrapRegisteredTool: rule('full', `${VENDORED} The runner argument is used exactly as Pi uses it (createContext + getActiveTools), which the pi2dsh projection provides.`),\n ProjectTrustStore: rule('partial', `${VENDORED} The store operates on trust.json under the caller\\'s agentDir — with the redirected getAgentDir convention that is package-visible state inside the DSH-owned pi2dsh directory. The DSH host never consults it; host trust stays a DSH decision (ctx.isProjectTrusted fails closed).`),\n DefaultResourceLoader: rule('partial', 'A headless resource loader honoring overrides, with empty discovery sets.'),\n DefaultPackageManager: rule('unsupported', 'Installing packages is owned by the DSH host and its security gates (dsh plugin add/remove behind pnpm\\'s build-script approval). Importing it is flagged at mount time (startup check); constructing it throws a structured PiCapabilityError, and doing so during entry setup marks the package unusable.'),\n ModelRuntime: rule('unsupported', 'Standalone model stacks are owned by the DSH host llm configuration; packages read the ONE directory through ctx.modelRegistry. Importing it is flagged at mount time (startup check); constructing it throws a structured PiCapabilityError, and doing so during entry setup marks the package unusable.'),\n createAgentSession: rule('partial', 'Bridged to a genuine DSH child agent through ctx.agents (a Pi model on the options routes the child); compositions without a loop factory fail explicitly.'),\n createCodingTools: rule('full', 'Pi\\'s exact tool set composed from the vendored built-in constructors.'),\n createReadOnlyTools: rule('full', 'Pi\\'s exact read-only tool set composed from the vendored built-in constructors.'),\n createBashTool: rule('full', VENDORED_TOOL),\n createReadTool: rule('full', VENDORED_TOOL),\n createEditTool: rule('full', VENDORED_TOOL),\n createWriteTool: rule('full', VENDORED_TOOL),\n createGrepTool: rule('full', VENDORED_TOOL),\n createFindTool: rule('full', VENDORED_TOOL),\n createLsTool: rule('full', VENDORED_TOOL),\n createBashToolDefinition: rule('full', VENDORED_TOOL),\n createReadToolDefinition: rule('full', VENDORED_TOOL),\n createEditToolDefinition: rule('full', VENDORED_TOOL),\n createWriteToolDefinition: rule('full', VENDORED_TOOL),\n createGrepToolDefinition: rule('full', VENDORED_TOOL),\n createFindToolDefinition: rule('full', VENDORED_TOOL),\n createLsToolDefinition: rule('full', VENDORED_TOOL),\n isToolCallEventType: rule('full', EVENT_GUARD),\n isBashToolResult: rule('full', EVENT_GUARD),\n isReadToolResult: rule('full', EVENT_GUARD),\n isEditToolResult: rule('full', EVENT_GUARD),\n isWriteToolResult: rule('full', EVENT_GUARD),\n isGrepToolResult: rule('full', EVENT_GUARD),\n isFindToolResult: rule('full', EVENT_GUARD),\n isLsToolResult: rule('full', EVENT_GUARD),\n loadSkills: rule('partial', `${VENDORED} Real directory discovery with Pi\\'s exact rules; default locations resolve through the redirected getAgentDir, i.e. inside the DSH-owned pi2dsh directory.`),\n loadSkillsFromDir: rule('full', `${VENDORED} Real directory discovery: SKILL.md roots, direct .md children, ignore files, symlink dedup, and Pi\\'s name/description validation.`),\n formatSkillsForPrompt: rule('full', 'Pi\\'s skill prompt formatter, vendored with logic unchanged.'),\n CustomEditor: rule('partial', HEADLESS_COMPONENT),\n ToolExecutionComponent: rule('partial', HEADLESS_COMPONENT),\n FooterComponent: rule('partial', HEADLESS_COMPONENT),\n BorderedLoader: rule('partial', HEADLESS_COMPONENT),\n CustomMessageComponent: rule('partial', HEADLESS_COMPONENT),\n AssistantMessageComponent: rule('partial', HEADLESS_COMPONENT),\n UserMessageComponent: rule('partial', HEADLESS_COMPONENT),\n ExtensionSelectorComponent: rule('partial', HEADLESS_COMPONENT),\n ExtensionInputComponent: rule('partial', HEADLESS_COMPONENT),\n ExtensionEditorComponent: rule('partial', HEADLESS_COMPONENT),\n SettingsSelectorComponent: rule('partial', HEADLESS_COMPONENT),\n renderDiff: rule('partial', 'Plain unified-style diff lines without terminal colors.'),\n truncateToVisualLines: rule('partial', 'Visual-line truncation backed by Pi\\'s vendored width math.'),\n keyHint: rule('partial', 'Plain-text key hint without theme styling.'),\n keyText: rule('partial', 'Plain-text key name without theme styling.'),\n rawKeyHint: rule('partial', 'Plain-text key hint without theme styling.'),\n }),\n 'pi-tui': Object.freeze({\n visibleWidth: rule('full', VENDORED),\n truncateToWidth: rule('full', VENDORED),\n wrapTextWithAnsi: rule('full', VENDORED),\n sliceByColumn: rule('full', VENDORED),\n sliceWithWidth: rule('full', VENDORED),\n stripTerminalSequences: rule('full', VENDORED),\n getOsc8LinkAtColumn: rule('full', VENDORED),\n normalizeTerminalOutput: rule('full', VENDORED),\n extractAnsiCode: rule('full', VENDORED),\n getGraphemeCellRange: rule('full', VENDORED),\n getGraphemeSegmenter: rule('full', VENDORED),\n getWordSegmenter: rule('full', VENDORED),\n applyBackgroundToLine: rule('full', VENDORED),\n isWhitespaceChar: rule('full', VENDORED),\n isPunctuationChar: rule('full', VENDORED),\n cjkBreakRegex: rule('full', VENDORED),\n PUNCTUATION_REGEX: rule('full', VENDORED),\n fuzzyMatch: rule('full', VENDORED),\n fuzzyFilter: rule('full', VENDORED),\n parseKey: rule('full', VENDORED),\n matchesKey: rule('full', VENDORED),\n isKeyRelease: rule('full', VENDORED),\n isKeyRepeat: rule('full', VENDORED),\n decodeKittyPrintable: rule('full', VENDORED),\n isKittyProtocolActive: rule('full', VENDORED),\n setKittyProtocolActive: rule('full', VENDORED),\n Key: rule('full', VENDORED),\n getKeybindings: rule('full', `${VENDORED} Bindings only match when a surface feeds terminal input, which DSH does not.`),\n setKeybindings: rule('full', VENDORED),\n KeybindingsManager: rule('full', VENDORED),\n TUI_KEYBINDINGS: rule('full', VENDORED),\n parseOsc11BackgroundColor: rule('full', VENDORED),\n parseTerminalColorSchemeReport: rule('full', VENDORED),\n renderLatex: rule('full', VENDORED),\n getPngDimensions: rule('full', VENDORED),\n getJpegDimensions: rule('full', VENDORED),\n getGifDimensions: rule('full', VENDORED),\n getWebpDimensions: rule('full', VENDORED),\n getImageDimensions: rule('full', VENDORED),\n calculateImageRows: rule('full', VENDORED),\n allocateImageId: rule('full', VENDORED),\n encodeKitty: rule('partial', `${VENDORED} No DSH surface consumes the escape sequences.`),\n encodeITerm2: rule('partial', `${VENDORED} No DSH surface consumes the escape sequences.`),\n deleteKittyImage: rule('partial', `${VENDORED} No DSH surface consumes the escape sequences.`),\n deleteAllKittyImages: rule('partial', `${VENDORED} No DSH surface consumes the escape sequences.`),\n detectCapabilities: rule('partial', `${VENDORED} Headless environments report no image protocol.`),\n getCapabilities: rule('partial', VENDORED),\n setCapabilities: rule('partial', VENDORED),\n resetCapabilitiesCache: rule('partial', VENDORED),\n getCellDimensions: rule('partial', VENDORED),\n setCellDimensions: rule('partial', VENDORED),\n hyperlink: rule('full', VENDORED),\n imageFallback: rule('full', VENDORED),\n CombinedAutocompleteProvider: rule('partial', `${VENDORED} Suggestions surface only if a DSH UI asks for them.`),\n Marked: rule('full', 'Re-exported from the same marked dependency Pi uses.'),\n CURSOR_MARKER: rule('full', 'Pi\\'s exact APC marker; vendored width math treats it as zero-width.'),\n Text: rule('partial', HEADLESS_COMPONENT),\n Spacer: rule('partial', HEADLESS_COMPONENT),\n Container: rule('partial', HEADLESS_COMPONENT),\n Box: rule('partial', HEADLESS_COMPONENT),\n Markdown: rule('partial', HEADLESS_COMPONENT),\n TruncatedText: rule('partial', HEADLESS_COMPONENT),\n Editor: rule('partial', `${HEADLESS_COMPONENT} Text editing state works; interactive keyboard flows do not.`),\n Input: rule('partial', `${HEADLESS_COMPONENT} Value state and submit/escape callbacks work; kill-ring editing does not.`),\n SelectList: rule('partial', `${HEADLESS_COMPONENT} Filtering and selection state work; keyboard interaction does not.`),\n SettingsList: rule('partial', `${HEADLESS_COMPONENT} Value updates work; keyboard interaction does not.`),\n ScrollView: rule('partial', HEADLESS_COMPONENT),\n VStack: rule('partial', HEADLESS_COMPONENT),\n HStack: rule('partial', HEADLESS_COMPONENT),\n Loader: rule('partial', HEADLESS_COMPONENT),\n CancellableLoader: rule('partial', HEADLESS_COMPONENT),\n Image: rule('partial', `${HEADLESS_COMPONENT} Renders a text placeholder; image bytes flow through DSH attachments instead.`),\n isFocusable: rule('full', 'Structural check preserved.'),\n isViewportTUI: rule('partial', 'Always false: no viewport TUI exists in DSH surfaces.'),\n }),\n 'pi-ai': Object.freeze({\n StringEnum: rule('full', 'Preserves Pi flat string-enum JSON Schema generation without loading provider SDKs.'),\n registerProvider: rule('partial', 'Recorded in a bridge-local registry; DSH llm adapters own real routing.'),\n getProviders: rule('partial', 'Returns the bridge-local registry contents.'),\n getProvider: rule('partial', 'Reads the bridge-local registry.'),\n getModel: rule('partial', 'Resolves no Pi model objects; DSH owns model routing.'),\n getModels: rule('partial', 'Returns an empty list; DSH owns model routing.'),\n complete: rule('partial', 'Real model calls through the DSH llm bridge (the host installs it at mount); without a mounted llm service the call fails explicitly. Provider SDKs are never loaded.'),\n stream: rule('partial', 'Real streaming model calls through the DSH llm bridge (the host installs it at mount); without a mounted llm service the call fails explicitly. Provider SDKs are never loaded.'),\n Type: rule('full', 'Re-exported from the same typebox dependency Pi resolves for extensions.'),\n uuidv7: rule('full', VENDORED),\n isContextOverflow: rule('full', VENDORED),\n isRecoverableLength: rule('full', VENDORED),\n isRetryableAssistantError: rule('full', VENDORED),\n contentText: rule('full', 'Pi\\'s text-block joiner, reimplemented with identical semantics.'),\n clampThinkingLevel: rule('full', 'Pi\\'s clamping walk over the extended thinking-level ladder.'),\n getSupportedThinkingLevels: rule('full', 'Pi\\'s thinkingLevelMap filter, preserved.'),\n modelsAreEqual: rule('full', 'Id+provider equality, preserved.'),\n }),\n})\n\nexport const CONTEXT_RULES: Readonly<Record<string, Rule>> = Object.freeze({\n cwd: rule('full', 'Mapped to the active DSH agent session working directory.'),\n signal: rule('full', 'Mapped to the active DSH cancellation signal when one is available.'),\n hasUI: rule('full', 'Reports whether the native DSH userQuestions service is available to back Pi dialogs.'),\n mode: rule('partial', 'Reports rpc mode so Pi extensions can choose their documented headless fallback.'),\n isIdle: rule('partial', 'Command contexts report idle; tool/lifecycle contexts conservatively report non-idle.'),\n isProjectTrusted: rule('partial', 'Fails closed as untrusted because DSH does not expose Pi project-trust state.'),\n hasPendingMessages: rule('partial', 'Conservatively reports no Pi-specific pending-message queue.'),\n getContextUsage: rule('partial', 'Returns no Pi token-usage projection.'),\n getSystemPrompt: rule('full', 'Returns the system prompt currently assembled by the bridge.'),\n getSystemPromptOptions: rule('partial', 'Returns an empty Pi option projection in command contexts.'),\n waitForIdle: rule('partial', 'Mapped to the DSH agent idle boundary when available.'),\n sessionManager: rule('partial', 'A real read-only projection: DSH durable messages plus pi2dsh sidecar entries, exposed through Pi\\'s exact 14-method surface as a single-branch tree.'),\n modelRegistry: rule('partial', 'A live registry over the ONE model directory — the DSH llm directory — projected exactly into Pi vocabulary; package-registered Pi-native routes keep api/baseUrl and the full Model shape through the round trip. Custom gateways are HOST configuration (the official llm-pi-ai adapter\\'s settings), never a Pi-side file: Pi\\'s ~/.pi/agent/models.json is deliberately NOT read — user-facing configuration is DSH-shaped only. getProviderAuth/getApiKeyAndHeaders run Pi\\'s full credential chain for package-registered providers and the host\\'s configurable-provider + credentials seams for DSH routes. Host configuration may declare \"<route>-vision\" image-admission companions: real DSH routes that admit images, replace image blocks with explicit path-carrying notices (materialized attachment files any path-taking tool can read), and forward text-only to the original route; Pi\\'s ctx.model reports the original route for a companion selection.'),\n model: rule('partial', 'The agent\\'s real provider/model route (a setModel() override wins), enriched from the projected catalog. When the selected route is an image-admission companion, ctx.model reports the ORIGINAL route with its true modalities — the generating model is the original text-only one, which is the truth extensions branching on input modalities (a vision bridge\\'s activation check) need.'),\n scopedModels: rule('partial', 'The projected model catalog (DSH llm directory plus package-registered providers).'),\n hasConfiguredAuth: rule('partial', 'Configuration check on the projected registry: true when the model\\'s provider has a live route or package registration (not a key-liveness probe).'),\n thinkingLevel: rule('partial', 'Reflects the level recorded by setThinkingLevel(); applied as reasoningEffort on the next request.'),\n abort: rule('partial', 'Mapped to agent.cancel({ kind: \"hook\" }) on the live DSH agent.'),\n shutdown: rule('partial', 'Pi defines shutdown behavior as host-provided (runner.ts bindExtensions); this host absorbs the request — the user owns DSH process exit — and informs the user once. The package keeps running.'),\n compact: rule('partial', 'Pi\\'s fire-and-forget trigger, translated to DSH\\'s official manual compaction (ctx.compaction.compactNow on the live agent). onComplete receives the real summary text and the shadowed-content token estimate as tokensBefore; firstKeptEntryId is empty because the DSH log has no Pi entry ids. Without a compaction service the gap flows through Pi\\'s onError callback and the capability ledger.'),\n newSession: rule('partial', 'Really creates a DSH session (ctx.sessions.create) with parent lineage; withSession runs against a projection context bound to it. DSH has no host-level \"current session pointer\" a plugin could move — which session the surface shows stays a host choice, announced once.'),\n fork: rule('partial', 'Really forks on DSH\\'s official prefix-fork surface (ctx.sessions.fork with lineage metadata). Anchors are durable-log entries (projected ids \"dsh-<seq>\"); Pi\\'s default position \"before\" is honored, and the boundary shrinks to the nearest completed-turn edge because DSH seeds must not split an open turn. Sidecar entries cannot anchor a fork.'),\n navigateTree: rule('partial', 'Expressed through DSH\\'s session model: the DSH tree lives BETWEEN sessions (fork lineage), not inside one log, so navigation forks at the target boundary. summarize runs Pi\\'s vendored branch summarizer over the abandoned durable slice (model call on the DSH llm bridge) and lands the summary as a branch_summary entry in the new session\\'s projection; label lands as a label entry.'),\n switchSession: rule('partial', 'Targets a LIVE DSH session by id (or a Pi-style path whose basename is \"<id>.jsonl\"); withSession runs against its projection. Switching to persisted sessions is host-owned — resume them from the DSH surface first. Which session the surface shows stays a host choice.'),\n reload: rule('partial', 'Really remounts every mounted package\\'s extension entries through a fresh loader (registrations replaced via the same-name path, event handlers reset), so edited plugin code takes effect. Skills, prompts, and themes are host-managed and reload with dsh itself.'),\n})\n\nexport const UI_CONTEXT_RULES: Readonly<Record<string, Rule>> = Object.freeze({\n notify: rule('full', 'Captured as a command result when applicable and emitted through DSH logging.'),\n setStatus: rule('partial', 'Accepted as a no-op because DSH owns status presentation.'),\n setWidget: rule('partial', 'Accepted as a no-op because Pi terminal widgets cannot render in DSH.'),\n select: rule('full', 'Mapped to one native DSH userQuestions single-select request.'),\n confirm: rule('full', 'Mapped to one native DSH userQuestions Yes/No request.'),\n input: rule('full', 'Mapped to one native DSH userQuestions free-text request.'),\n editor: rule('partial', 'Mapped to one DSH userQuestions free-text request; multi-line editing UX is not emulated.'),\n custom: rule('partial', 'Resolves undefined, exactly like Pi\\'s own rpc mode; guarded fallbacks keep working.'),\n onTerminalInput: rule('partial', 'Raw terminal input is absent; feature-detected listeners remain disabled.'),\n setWorkingMessage: rule('partial', 'Accepted as a no-op; DSH owns progress presentation.'),\n setWorkingVisible: rule('partial', 'Accepted as a no-op; DSH owns progress presentation.'),\n setWorkingIndicator: rule('partial', 'Accepted as a no-op; DSH owns progress presentation.'),\n setHiddenThinkingLabel: rule('partial', 'Accepted as a no-op; DSH owns thinking presentation.'),\n setFooter: rule('partial', 'Accepted as a no-op; DSH owns footer presentation.'),\n setHeader: rule('partial', 'Accepted as a no-op; DSH owns header presentation.'),\n setTitle: rule('partial', 'Accepted as a no-op; DSH owns window titles.'),\n pasteToEditor: rule('partial', 'Appends to a per-agent editor buffer readable through getEditorText().'),\n setEditorText: rule('partial', 'Stored in a per-agent editor buffer readable through getEditorText().'),\n getEditorText: rule('partial', 'Reads the per-agent editor buffer maintained by the bridge.'),\n addAutocompleteProvider: rule('partial', 'Registration is recorded; no DSH surface requests suggestions.'),\n setEditorComponent: rule('partial', 'Registration is recorded; no DSH surface mounts a Pi editor component.'),\n getEditorComponent: rule('partial', 'Returns the recorded factory.'),\n theme: rule('partial', 'A headless theme whose styling calls return unstyled text.'),\n getAllThemes: rule('partial', 'Lists the single headless theme.'),\n getTheme: rule('partial', 'Resolves only the headless theme.'),\n setTheme: rule('partial', 'Accepts the headless theme; other names report an explicit error result.'),\n getToolsExpanded: rule('partial', 'A bridge-local presentation flag.'),\n setToolsExpanded: rule('partial', 'A bridge-local presentation flag.'),\n})\n\nexport const API_RULES: Readonly<Record<string, Rule>> = Object.freeze({\n registerTool: {\n level: 'partial',\n detail: 'Registered as a native DSH tool. Text and image results use native DSH content/attachments; unsupported JSON Schema constraints and Pi-only error details are explicitly degraded.',\n },\n unregisterTool: {\n level: 'full',\n detail: 'Disposes the exact native DSH tool registration and removes it from the migrated package registry.',\n },\n registerCommand: {\n level: 'partial',\n detail: 'Registered in ctx.commands with Pi\\'s never-throw collision semantics: a package re-registering its own name replaces it, and cross-source collisions mount under Pi\\'s numbered scheme (/name-2 — the earlier registration keeps the bare name, where Pi renumbers both). ui.notify becomes the result, while interactive Pi TUI methods fail explicitly in headless DSH.',\n },\n registerShortcut: {\n level: 'partial',\n detail: 'Registration is recorded and introspectable; DSH surfaces feed no terminal key input, so handlers never fire — the same as Pi\\'s non-TUI modes.',\n },\n registerFlag: {\n level: 'partial',\n detail: 'The declared default is available through getFlag; Pi process flags cannot be added to the DSH launcher.',\n },\n getFlag: {\n level: 'partial',\n detail: 'Returns the migrated flag default because DSH cannot register the original Pi CLI flag.',\n },\n registerProvider: {\n level: 'partial',\n detail: 'The provider declaration is recorded and introspectable; model calls stay on native DSH llm adapters and credentials, which own transports and secrets.',\n },\n unregisterProvider: {\n level: 'partial',\n detail: 'Removes the recorded provider declaration.',\n },\n registerMessageRenderer: {\n level: 'partial',\n detail: 'Registration is accepted; DSH owns presentation, so the renderer is never invoked — matching Pi\\'s non-TUI surfaces.',\n },\n registerEntryRenderer: {\n level: 'partial',\n detail: 'Registration is accepted; DSH owns presentation, so the renderer is never invoked — matching Pi\\'s non-TUI surfaces.',\n },\n registerMarkdownTransformer: {\n level: 'partial',\n detail: 'Registration is accepted; DSH owns presentation, so the transformer is never invoked — matching Pi\\'s non-TUI surfaces.',\n },\n sendMessage: {\n level: 'partial',\n detail: 'Mapped to native DSH inject/steer/followup delivery with honest plugin provenance; Pi display/details metadata awaits the custom session-entry seam.',\n },\n sendUserMessage: {\n level: 'full',\n detail: 'Mapped to native DSH steer/followup delivery with text and attachment-backed image content.',\n },\n appendEntry: {\n level: 'partial',\n detail: 'Persisted in a pi2dsh sidecar next to the DSH session and replayed on session start; DSH\\'s main log stays untouched because it has no out-of-repo plugin-event channel yet.',\n },\n setSessionName: {\n level: 'partial',\n detail: 'Persisted in the pi2dsh sidecar and announced through session_info_changed; DSH\\'s own title events are also projected when present.',\n },\n getSessionName: {\n level: 'partial',\n detail: 'Reads the sidecar-persisted session name.',\n },\n setLabel: {\n level: 'partial',\n detail: 'Persisted in the pi2dsh sidecar and reflected by the sessionManager projection.',\n },\n exec: {\n level: 'partial',\n detail: 'Mapped to ctx.subprocess, so the selected local/E2B provider owns execution, isolation, cancellation, and tree cleanup; output is bounded to 64 MiB per stream.',\n },\n getActiveTools: {\n level: 'partial',\n detail: 'Returns every tool visible in the current DSH agent scope, including native and migrated tools; scope-local tools follow DSH composition rules.',\n },\n getAllTools: {\n level: 'partial',\n detail: 'Returns metadata for all tools visible in the current DSH scope, without Pi-specific prompt guidelines unavailable from DSH schemas.',\n },\n setActiveTools: {\n level: 'partial',\n detail: 'Mapped to the active DSH agent scope through tools.restrict({ allow }), preserving per-agent global-tool visibility without mutating other agents; DSH scope-local tools remain visible by design.',\n },\n getCommands: {\n level: 'partial',\n detail: 'Returns commands registered by this migrated Pi package, not every command visible in the DSH scope.',\n },\n setModel: {\n level: 'partial',\n detail: 'Recorded as a per-agent override applied through the agent/request waterfall on the next model call; DSH remains authoritative for provider routing.',\n },\n getThinkingLevel: {\n level: 'partial',\n detail: 'Returns the level recorded by setThinkingLevel (default off).',\n },\n setThinkingLevel: {\n level: 'partial',\n detail: 'Recorded per agent and applied as reasoningEffort through the agent/request waterfall; DSH validates the effort id at the request boundary.',\n },\n events: {\n level: 'full',\n detail: 'Package-local Pi extension event-bus emit/on semantics are preserved for migrated extensions in the same bundle.',\n },\n})\n\nconst OBSERVED_NEVER_FIRES = (moment: string): Rule => ({\n level: 'partial',\n detail: `Registration is accepted; ${moment} never occurs on DSH surfaces, so the handler never fires. Loading is unaffected.`,\n})\n\nexport const EVENT_RULES: Readonly<Record<string, Rule>> = Object.freeze({\n session_start: { level: 'full', detail: 'Mapped to agent/session-start.' },\n session_shutdown: { level: 'full', detail: 'Mapped to agent disposal and plugin teardown with duplicate suppression.' },\n session_info_changed: { level: 'partial', detail: 'Fired by setSessionName() and projected from DSH session/title events.' },\n agent_start: { level: 'full', detail: 'Mapped to the DSH turn/start boundary.' },\n agent_settled: { level: 'full', detail: 'Mapped to the DSH turn/end boundary.' },\n turn_start: { level: 'full', detail: 'Mapped from durable turn/start events.' },\n tool_execution_start: { level: 'full', detail: 'Mapped from durable tool/call events.' },\n tool_execution_end: { level: 'full', detail: 'Mapped from finalized tools/result events.' },\n tool_execution_update: {\n level: 'partial',\n detail: 'Fired from migrated Pi tools\\' own onUpdate callbacks; DSH-native tools expose no partial-result stream.',\n },\n tool_call: {\n level: 'partial',\n detail: 'Blocking is supported, and in-place argument mutation reaches migrated Pi tools; mutating a DSH-native tool\\'s arguments is rejected because DSH logs arguments before policy.',\n },\n tool_result: {\n level: 'partial',\n detail: 'Text replacement and success-to-error blocking are supported; arbitrary details and error recovery are not.',\n },\n before_agent_start: {\n level: 'full',\n detail: 'Fires at the turn\\'s first pre-step with the real prompt text and image attachments; returned custom messages enter the turn beside the user message, and a returned systemPrompt overrides this turn\\'s assembly.',\n },\n agent_end: {\n level: 'partial',\n detail: 'The lifecycle boundary is mapped, but the reconstructed Pi message history is intentionally minimal.',\n },\n turn_end: {\n level: 'partial',\n detail: 'The lifecycle boundary and tool results are mapped; the exact Pi final-message shape is not guaranteed.',\n },\n message_start: {\n level: 'partial',\n detail: 'Durable user, assistant, and tool-result messages are mapped without Pi-specific provider metadata.',\n },\n message_end: {\n level: 'partial',\n detail: 'Durable messages are observed, but message replacement is not supported.',\n },\n message_update: {\n level: 'partial',\n detail: 'Projected from DSH assistant/chunk events with accumulated text; Pi\\'s full AgentMessage accumulation state is approximated.',\n },\n session_before_compact: {\n level: 'partial',\n detail: 'Projected from DSH compaction/start as a notification; cancel/replace cannot reach DSH\\'s compactor.',\n },\n session_compact: {\n level: 'partial',\n detail: 'Projected from DSH compaction summary/end events.',\n },\n model_select: {\n level: 'partial',\n detail: 'Fired by setModel() and projected from request/header model changes in the durable log.',\n },\n thinking_level_select: {\n level: 'partial',\n detail: 'Fired by setThinkingLevel(); DSH-side reasoning changes surface through request/header projection.',\n },\n context: {\n level: 'partial',\n detail: 'Fires before each step with the full message projection; the transform applies to the step\\'s not-yet-entered messages (the slice packages rewrite), while already-entered history stays read-only under DSH\\'s append-only log.',\n },\n before_provider_request: {\n level: 'unsupported',\n detail: 'Provider payload mutation belongs in a native DSH LLM adapter; the handler is accepted but never fires.',\n },\n before_provider_headers: {\n level: 'unsupported',\n detail: 'Provider header mutation belongs in a native DSH LLM adapter; the handler is accepted but never fires.',\n },\n after_provider_response: {\n level: 'unsupported',\n detail: 'Provider response interception belongs in a native DSH LLM adapter; the handler is accepted but never fires.',\n },\n user_bash: OBSERVED_NEVER_FIRES('Pi\\'s ! command surface'),\n input: OBSERVED_NEVER_FIRES('raw Pi terminal input'),\n project_trust: {\n level: 'unsupported',\n detail: 'Project trust must remain owned by the DSH host; the handler is accepted but never consulted.',\n },\n resources_discover: {\n level: 'unsupported',\n detail: 'Dynamic resource discovery must be converted into DSH providers; the handler is accepted but never fires.',\n },\n session_before_switch: OBSERVED_NEVER_FIRES('Pi session switching'),\n session_before_fork: OBSERVED_NEVER_FIRES('Pi tree forking'),\n session_before_tree: OBSERVED_NEVER_FIRES('Pi session-tree navigation'),\n session_tree: OBSERVED_NEVER_FIRES('Pi session-tree navigation'),\n})\n\nexport function ruleForApi(method: string): Rule | undefined {\n return API_RULES[method]\n}\n\nexport function ruleForEvent(event: string): Rule {\n return EVENT_RULES[event] ?? {\n level: 'unsupported',\n detail: `Unknown Pi event ${JSON.stringify(event)} has no verified DSH mapping.`,\n }\n}\n\nexport function ruleForHostImport(packageName: string, importedName: string): Rule | undefined {\n const family = (PI_CODING_AGENT_PACKAGES as readonly string[]).includes(packageName)\n ? 'pi-coding-agent'\n : (PI_TUI_PACKAGES as readonly string[]).includes(packageName)\n ? 'pi-tui'\n : (PI_AI_PACKAGES as readonly string[]).includes(packageName) ? 'pi-ai' : undefined\n return family === undefined ? undefined : HOST_IMPORT_RULES[family]?.[importedName]\n}\n\nexport function ruleForContextProperty(property: string): Rule | undefined {\n return CONTEXT_RULES[property]\n}\n\nexport function ruleForUiContextProperty(property: string): Rule | undefined {\n return UI_CONTEXT_RULES[property]\n}\n","// Pi MCP configuration -> DSH mcp-client patch entries.\n//\n// Pi (via pi-mcp-adapter) reads the standard `mcpServers` files. DSH ships an\n// official MCP client (`@deepseek-ai/dsh-mcp-client`) configured through\n// cordis patch layers — so migration is config translation, not running Pi's\n// adapter code. This module reads Pi's documented six-layer precedence,\n// resolves `disabled` flags, and emits one patch entry per enabled server.\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { getAgentDir } from './compat/vendor/pi-config-shim.js'\n\ntype UnknownRecord = Record<string, unknown>\n\nexport interface PiMcpServer {\n name: string\n sourcePath: string\n transport: 'stdio' | 'streamable-http'\n command?: string\n args?: string[]\n env?: Record<string, string>\n cwd?: string\n url?: string\n headers?: Record<string, string>\n disabled: boolean\n}\n\nexport interface McpConversionWarning {\n server: string\n message: string\n}\n\nexport interface McpConversionResult {\n servers: PiMcpServer[]\n entries: UnknownRecord[]\n warnings: McpConversionWarning[]\n sources: string[]\n}\n\n/** Pi's documented config precedence, lowest to highest. */\nexport function piMcpConfigPaths(cwd: string): string[] {\n const home = homedir()\n return [\n join(home, '.config', 'mcp', 'mcp.json'),\n join(home, '.agents', 'mcp.json'),\n join(home, '.agents', 'mcp', 'mcp.json'),\n join(getAgentDir(), 'mcp.json'),\n join(cwd, '.mcp.json'),\n join(cwd, '.pi', 'mcp.json'),\n ]\n}\n\nfunction stringRecord(value: unknown): Record<string, string> | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n const entries = Object.entries(value).filter((entry): entry is [string, string] => typeof entry[1] === 'string')\n return entries.length === 0 ? undefined : Object.fromEntries(entries)\n}\n\nfunction parseServer(name: string, raw: unknown, sourcePath: string): PiMcpServer | undefined {\n if (typeof raw !== 'object' || raw === null) return undefined\n const record = raw as UnknownRecord\n const disabled = record.disabled === true\n if (typeof record.url === 'string') {\n return {\n name, sourcePath, transport: 'streamable-http', url: record.url,\n ...(stringRecord(record.headers) === undefined ? {} : { headers: stringRecord(record.headers)! }),\n disabled,\n }\n }\n if (typeof record.command === 'string') {\n return {\n name, sourcePath, transport: 'stdio', command: record.command,\n ...(Array.isArray(record.args) ? { args: record.args.map(String) } : {}),\n ...(stringRecord(record.env) === undefined ? {} : { env: stringRecord(record.env)! }),\n ...(typeof record.cwd === 'string' ? { cwd: record.cwd } : {}),\n disabled,\n }\n }\n return undefined\n}\n\nexport function collectPiMcpServers(cwd: string, extraPaths: string[] = []): { servers: Map<string, PiMcpServer>; sources: string[] } {\n const servers = new Map<string, PiMcpServer>()\n const sources: string[] = []\n for (const path of [...piMcpConfigPaths(cwd), ...extraPaths]) {\n if (!existsSync(path)) continue\n let parsed: unknown\n try {\n parsed = JSON.parse(readFileSync(path, 'utf8'))\n } catch {\n continue\n }\n const mcpServers = (parsed as UnknownRecord | undefined)?.mcpServers\n if (typeof mcpServers !== 'object' || mcpServers === null) continue\n sources.push(path)\n for (const [name, raw] of Object.entries(mcpServers)) {\n const record = raw as UnknownRecord | null\n const existing = servers.get(name)\n // Later (higher-precedence) layers override whole entries; a bare\n // `disabled` toggle updates the effective server from a lower layer.\n if (existing !== undefined && typeof record === 'object' && record !== null\n && record.command === undefined && record.url === undefined && typeof record.disabled === 'boolean') {\n servers.set(name, { ...existing, disabled: record.disabled, sourcePath: path })\n continue\n }\n const server = parseServer(name, raw, path)\n if (server !== undefined) servers.set(name, server)\n }\n }\n return { servers, sources }\n}\n\nconst SERVER_NAME_PATTERN = /^[A-Za-z0-9_-]{1,32}$/u\nconst ENV_REFERENCE_PATTERN = /^\\$\\{?([A-Za-z_][A-Za-z0-9_]*)\\}?$/u\nconst SECRETISH_KEY_PATTERN = /token|secret|key|password|credential/iu\n\ninterface JsExpression {\n __pi2dshJs: string\n}\n\nfunction js(expression: string): JsExpression {\n return { __pi2dshJs: expression }\n}\n\nfunction convertValueMap(\n server: string,\n kind: 'env' | 'headers',\n values: Record<string, string> | undefined,\n warnings: McpConversionWarning[],\n): Record<string, string | JsExpression> | undefined {\n if (values === undefined) return undefined\n const output: Record<string, string | JsExpression> = {}\n for (const [key, value] of Object.entries(values)) {\n const reference = ENV_REFERENCE_PATTERN.exec(value)\n if (reference !== null) {\n output[key] = js(`process.env.${reference[1]}`)\n continue\n }\n if (SECRETISH_KEY_PATTERN.test(key)) {\n warnings.push({\n server,\n message: `${kind}.${key} carries a literal value; move the secret to an environment variable and reference it as $NAME so the patch stays credential-free`,\n })\n }\n output[key] = value\n }\n return output\n}\n\nexport function convertPiMcpConfig(cwd: string, extraPaths: string[] = []): McpConversionResult {\n const { servers, sources } = collectPiMcpServers(cwd, extraPaths)\n const warnings: McpConversionWarning[] = []\n const entries: UnknownRecord[] = []\n for (const server of servers.values()) {\n if (server.disabled) {\n warnings.push({ server: server.name, message: 'skipped: disabled in Pi configuration' })\n continue\n }\n if (!SERVER_NAME_PATTERN.test(server.name)) {\n warnings.push({\n server: server.name,\n message: 'skipped: DSH serverName must match [A-Za-z0-9_-]{1,32}; rename the server in the Pi config',\n })\n continue\n }\n const config: UnknownRecord = { serverName: server.name, transport: server.transport }\n if (server.transport === 'stdio') {\n config.command = server.command\n if (server.args !== undefined) config.args = server.args\n const env = convertValueMap(server.name, 'env', server.env, warnings)\n if (env !== undefined) config.env = env\n if (server.cwd !== undefined) config.cwd = server.cwd\n } else {\n config.url = server.url\n const headers = convertValueMap(server.name, 'headers', server.headers, warnings)\n if (headers !== undefined) config.headers = headers\n }\n entries.push({ id: `mcp-${server.name}`, name: '@deepseek-ai/dsh-mcp-client', config })\n }\n return { servers: [...servers.values()], entries, warnings, sources }\n}\n\nfunction yamlScalar(value: unknown, indent: string): string {\n if (typeof value === 'object' && value !== null && '__pi2dshJs' in (value as JsExpression)) {\n return `!!js ${(value as JsExpression).__pi2dshJs}`\n }\n if (typeof value === 'string') {\n return /^[A-Za-z0-9@._\\/:-]+$/u.test(value) ? value : JSON.stringify(value)\n }\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]'\n return `\\n${value.map(item => `${indent} - ${yamlScalar(item, `${indent} `)}`).join('\\n')}`\n }\n if (typeof value === 'object' && value !== null) {\n const record = value as UnknownRecord\n const keys = Object.keys(record)\n if (keys.length === 0) return '{}'\n return `\\n${keys.map(key => `${indent} ${key}: ${yamlScalar(record[key], `${indent} `)}`).join('\\n')}`\n }\n return String(value)\n}\n\n/** Render the converted entries as a cordis.patch.yml `insert` block. */\nexport function renderMcpPatch(result: McpConversionResult): string {\n if (result.entries.length === 0) return '# no enabled MCP servers found in Pi configuration\\n'\n const lines: string[] = ['- insert:']\n for (const entry of result.entries) {\n lines.push(` - id: ${String(entry.id)}`)\n lines.push(` name: '@deepseek-ai/dsh-mcp-client'`)\n lines.push(` inject: [tools]`)\n lines.push(` config:${yamlScalar(entry.config, ' ')}`)\n }\n return `${lines.join('\\n')}\\n`\n}\n"],"mappings":"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"}