fix(pi): load installed device extensions
This commit is contained in:
@@ -177,11 +177,12 @@ async function createThreadRuntime(channel, rawOptions) {
|
||||
const appendSystemPrompts = optionValues(args, '--append-system-prompt');
|
||||
const sessionId = requiredString(optionValue(args, '--session-id'), 'Thread session id');
|
||||
const forkSessionId = optionValue(args, '--fork');
|
||||
const extensionPaths = optionValues(args, '--extension').map((value) => path.resolve(value));
|
||||
const [makeloreExtensionPath, ...additionalExtensionPaths] = optionValues(args, '--extension')
|
||||
.map((value) => path.resolve(value));
|
||||
const skillPaths = optionValues(args, '--skill').map((value) => path.resolve(value));
|
||||
if (extensionPaths.length !== 1) throw new Error('Thread requires exactly one Makelore extension');
|
||||
if (!makeloreExtensionPath) throw new Error('Thread requires a Makelore extension');
|
||||
if (appendSystemPrompts.length !== 1) throw new Error('Thread requires exactly one Makelore language prompt');
|
||||
const extensionModule = await import(pathToFileURL(extensionPaths[0]).href);
|
||||
const extensionModule = await import(pathToFileURL(makeloreExtensionPath).href);
|
||||
if (typeof extensionModule.createMakeloreRuntime !== 'function') {
|
||||
throw new Error('Makelore runtime extension factory is unavailable');
|
||||
}
|
||||
@@ -215,6 +216,7 @@ async function createThreadRuntime(channel, rawOptions) {
|
||||
cwd: runtimeCwd,
|
||||
})),
|
||||
}],
|
||||
additionalExtensionPaths,
|
||||
additionalSkillPaths: skillPaths,
|
||||
noExtensions: true,
|
||||
noSkills: true,
|
||||
|
||||
@@ -196,6 +196,22 @@ describe('Pi Agent Server real process', () => {
|
||||
writeFile(languagePromptPath, MAKELORE_DEFAULT_LANGUAGE_PROMPT),
|
||||
]);
|
||||
const extensionPath = await materializeMakelorePiExtension(extensionDir);
|
||||
const firstDeviceExtensionPath = path.join(extensionDir, 'first-device-extension.mjs');
|
||||
const secondDeviceExtensionPath = path.join(extensionDir, 'second-device-extension.mjs');
|
||||
await Promise.all([
|
||||
writeFile(firstDeviceExtensionPath, [
|
||||
'export default function (pi) {',
|
||||
" pi.registerCommand('first-device-ping', { description: 'First device ping', handler: async () => {} });",
|
||||
'}',
|
||||
'',
|
||||
].join('\n')),
|
||||
writeFile(secondDeviceExtensionPath, [
|
||||
'export default function (pi) {',
|
||||
" pi.registerCommand('second-device-ping', { description: 'Second device ping', handler: async () => {} });",
|
||||
'}',
|
||||
'',
|
||||
].join('\n')),
|
||||
]);
|
||||
const runtimeRoot = path.resolve('node_modules/@earendil-works/pi-coding-agent');
|
||||
const server = new PiAgentServerProcess({
|
||||
executablePath: process.execPath,
|
||||
@@ -221,6 +237,8 @@ describe('Pi Agent Server real process', () => {
|
||||
'--system-prompt', promptPath,
|
||||
'--append-system-prompt', languagePromptPath,
|
||||
'--extension', extensionPath,
|
||||
'--extension', firstDeviceExtensionPath,
|
||||
'--extension', secondDeviceExtensionPath,
|
||||
'--session-id', `session-${conversationId}`,
|
||||
],
|
||||
env: {
|
||||
@@ -261,6 +279,15 @@ describe('Pi Agent Server real process', () => {
|
||||
.resolves.toMatchObject({
|
||||
data: { models: expect.arrayContaining([expect.objectContaining({ id: 'test-model' })]) },
|
||||
});
|
||||
await expect(left.request<{ commands: Array<{ name: string; source: string }> }>({ type: 'get_commands' }))
|
||||
.resolves.toMatchObject({
|
||||
data: {
|
||||
commands: expect.arrayContaining([
|
||||
expect.objectContaining({ name: 'first-device-ping', source: 'extension' }),
|
||||
expect.objectContaining({ name: 'second-device-ping', source: 'extension' }),
|
||||
]),
|
||||
},
|
||||
});
|
||||
|
||||
const settled = (worker: typeof left) => new Promise<void>((resolve) => {
|
||||
const unsubscribe = worker.subscribe((event) => {
|
||||
|
||||
Reference in New Issue
Block a user