fix(config pi): embed extension sources so installed binary is self-contained

- add scripts/generate-pi-extension.ts to embed src/pi-ext sources as
  string constants (mirrors prime-agent's embedded switcher pattern).
- config pi now writes the embedded sources by default, so it works from
  an /usr/bin install with no source tree (--extension-dir overrides for
  dev). Verified installed binary writes files byte-identical to source.
- add installEmbeddedExtension test.
This commit is contained in:
Michal
2026-08-08 17:03:03 +01:00
parent f90e23d000
commit f1d84b0952
5 changed files with 116 additions and 20 deletions

View File

@@ -6,6 +6,7 @@ import { agentInstallRoot } from '../../src/commands/skills.js';
import {
registerWithPi,
installExtensionFiles,
installEmbeddedExtension,
} from '../../src/utils/pi-settings.js';
describe('skills agentInstallRoot', () => {
@@ -89,4 +90,20 @@ describe('pi-settings util', () => {
expect(readFileSync(join(destDir, 'mcpctl-pi.ts'), 'utf-8')).toBe('// extension\n');
expect(readFileSync(join(destDir, 'mcp-http.ts'), 'utf-8')).toBe('// client\n');
});
it('writes the embedded extension sources (self-contained, no source tree)', async () => {
const destDir = join(tmp, 'embedded-ext');
const written = await installEmbeddedExtension(destDir);
expect(written).toHaveLength(2);
// Both filenames must be written.
expect(written.map((w) => w.replace(destDir + '/', ''))).toEqual(['mcpctl-pi.ts', 'mcp-http.ts']);
// The main file must be non-empty and import the sibling client.
const main = readFileSync(join(destDir, 'mcpctl-pi.ts'), 'utf-8');
expect(main.length).toBeGreaterThan(1000);
expect(main).toContain('./mcp-http.js');
const http = readFileSync(join(destDir, 'mcp-http.ts'), 'utf-8');
expect(http).toContain('McpHttpSession');
});
});