feat(pi): add persistent Mosaic /goal controller (#1152)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful

This commit was merged in pull request #1152.
This commit is contained in:
mos-dt-0
2026-08-10 22:54:43 +00:00
parent b0f7d26dd9
commit 722163671f
17 changed files with 2474 additions and 20 deletions
@@ -5,6 +5,7 @@ import { tmpdir } from 'node:os';
import { join } from 'node:path';
import {
buildPiSkillArgs,
discoverPiExtensionArgs,
enumerateSkillDirs,
piForceSkillNames,
registerRuntimeLaunchers,
@@ -178,6 +179,52 @@ describe('buildPiSkillArgs', () => {
});
});
describe('discoverPiExtensionArgs', () => {
it('loads the core and goal extensions in deterministic order from Mosaic home', () => {
const root = mkdtempSync(join(tmpdir(), 'mosaic-pi-extensions-'));
const runtimeDir = join(root, 'runtime', 'pi');
mkdirSync(runtimeDir, { recursive: true });
writeFileSync(join(runtimeDir, 'goal-extension.ts'), '// goal\n');
writeFileSync(join(runtimeDir, 'mosaic-extension.ts'), '// core\n');
try {
expect(discoverPiExtensionArgs(root)).toEqual([
'--extension',
join(runtimeDir, 'mosaic-extension.ts'),
'--extension',
join(runtimeDir, 'goal-extension.ts'),
]);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
it('remains backward-compatible when the optional goal extension is absent', () => {
const root = mkdtempSync(join(tmpdir(), 'mosaic-pi-extensions-'));
const runtimeDir = join(root, 'runtime', 'pi');
mkdirSync(runtimeDir, { recursive: true });
writeFileSync(join(runtimeDir, 'mosaic-extension.ts'), '// core\n');
try {
expect(discoverPiExtensionArgs(root)).toEqual([
'--extension',
join(runtimeDir, 'mosaic-extension.ts'),
]);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
it('emits no extension arguments when Mosaic runtime assets are absent', () => {
const root = mkdtempSync(join(tmpdir(), 'mosaic-pi-extensions-'));
try {
expect(discoverPiExtensionArgs(root)).toEqual([]);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
});
describe('enumerateSkillDirs (real FS)', () => {
let root: string;
+10 -4
View File
@@ -715,9 +715,15 @@ export function buildPiSkillArgs(
return ['--no-skills', ...forcedSkillArgs];
}
function discoverPiExtension(): string[] {
const ext = join(MOSAIC_HOME, 'runtime', 'pi', 'mosaic-extension.ts');
return existsSync(ext) ? ['--extension', ext] : [];
const PI_EXTENSION_FILES = ['mosaic-extension.ts', 'goal-extension.ts'] as const;
export function discoverPiExtensionArgs(mosaicHome: string = MOSAIC_HOME): string[] {
const args: string[] = [];
for (const fileName of PI_EXTENSION_FILES) {
const extensionPath = join(mosaicHome, 'runtime', 'pi', fileName);
if (existsSync(extensionPath)) args.push('--extension', extensionPath);
}
return args;
}
// ─── Launch functions ────────────────────────────────────────────────────────
@@ -792,7 +798,7 @@ function launchRuntime(runtime: RuntimeName, args: string[], yolo: boolean): nev
const prompt = buildRuntimePrompt('pi');
const cliArgs = ['--append-system-prompt', prompt];
cliArgs.push(...buildPiSkillArgs(args));
cliArgs.push(...discoverPiExtension());
cliArgs.push(...discoverPiExtensionArgs());
if (hasMissionNoArgs) {
cliArgs.push(missionPrompt);
} else {