@hyperdreamer/pi-webui 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -0
- package/README.md +148 -0
- package/dist/cli.js +975 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/apple-touch-icon.png +0 -0
- package/dist/client/assets/CodeViewer-aB4ZVzEu.js +4 -0
- package/dist/client/assets/UnifiedDiffViewer-f8X7aTkU.js +39 -0
- package/dist/client/assets/index-Cffeusjy.js +6022 -0
- package/dist/client/assets/vendor-editor-core-vUi74DnD.js +12 -0
- package/dist/client/assets/vendor-editor-languages-DoaXUodB.js +46 -0
- package/dist/client/assets/vendor-editor-legacy-CYBnW6ZU.js +1 -0
- package/dist/client/assets/vendor-terminal-BrP-ENHg.css +1 -0
- package/dist/client/assets/vendor-terminal-D8k4UKM2.js +35 -0
- package/dist/client/favicon.svg +8 -0
- package/dist/client/index.html +65 -0
- package/dist/client/manifest.webmanifest +24 -0
- package/dist/client/pwa-icon-192.png +0 -0
- package/dist/client/pwa-icon-512.png +0 -0
- package/dist/config.js +417 -0
- package/dist/config.js.map +1 -0
- package/dist/docker/piWebUiDockerCommandPlan.js +211 -0
- package/dist/docker/piWebUiDockerCommandPlan.js.map +1 -0
- package/dist/nativeServices/serviceDoctor.js +480 -0
- package/dist/nativeServices/serviceDoctor.js.map +1 -0
- package/dist/nativeServices/serviceInstall.js +35 -0
- package/dist/nativeServices/serviceInstall.js.map +1 -0
- package/dist/nativeServices/servicePlan.js +358 -0
- package/dist/nativeServices/servicePlan.js.map +1 -0
- package/dist/nativeServices/serviceProbe.js +447 -0
- package/dist/nativeServices/serviceProbe.js.map +1 -0
- package/dist/nativeServices/serviceRendering.js +122 -0
- package/dist/nativeServices/serviceRendering.js.map +1 -0
- package/dist/pi-webui-plugins/info/package.json +9 -0
- package/dist/pi-webui-plugins/info/pi-webui-plugin.js +51 -0
- package/dist/pi-webui-plugins/updates/package.json +9 -0
- package/dist/pi-webui-plugins/updates/pi-webui-plugin.js +185 -0
- package/dist/pi-webui-plugins/updates/updatesLogic.js +97 -0
- package/dist/pi-webui-plugins/workspace-tasks/config.js +91 -0
- package/dist/pi-webui-plugins/workspace-tasks/package.json +9 -0
- package/dist/pi-webui-plugins/workspace-tasks/pi-webui-plugin.js +48 -0
- package/dist/pi-webui-plugins/workspace-tasks/taskRunner.js +12 -0
- package/dist/pi-webui-plugins/workspace-tasks/tasksPanelElement.js +288 -0
- package/dist/pi-webui-plugins/workspace-tasks/workspaceTasksClient.js +47 -0
- package/dist/piWebUiVersionReport.js +225 -0
- package/dist/piWebUiVersionReport.js.map +1 -0
- package/dist/plugin-api/unstable.d.ts +22 -0
- package/dist/plugin-api.d.ts +199 -0
- package/dist/server/activeAgentProfileProvider.js +25 -0
- package/dist/server/activeAgentProfileProvider.js.map +1 -0
- package/dist/server/activity/workspaceActivityRoutes.js +4 -0
- package/dist/server/activity/workspaceActivityRoutes.js.map +1 -0
- package/dist/server/activity/workspaceActivityService.js +98 -0
- package/dist/server/activity/workspaceActivityService.js.map +1 -0
- package/dist/server/app.js +211 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/browserMessageProjection.js +56 -0
- package/dist/server/browserMessageProjection.js.map +1 -0
- package/dist/server/configRoutes.js +309 -0
- package/dist/server/configRoutes.js.map +1 -0
- package/dist/server/diagnostics/nodePtyNativeModule.js +36 -0
- package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -0
- package/dist/server/diagnostics/nodePtySpawnHelper.js +135 -0
- package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -0
- package/dist/server/git/gitEnv.js +15 -0
- package/dist/server/git/gitEnv.js.map +1 -0
- package/dist/server/git/gitService.js +123 -0
- package/dist/server/git/gitService.js.map +1 -0
- package/dist/server/gitRoutes.js +23 -0
- package/dist/server/gitRoutes.js.map +1 -0
- package/dist/server/index.js +7 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/machines/machineClient.js +172 -0
- package/dist/server/machines/machineClient.js.map +1 -0
- package/dist/server/machines/machinePluginProxyRoutes.js +190 -0
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -0
- package/dist/server/machines/machineProxyRoutes.js +172 -0
- package/dist/server/machines/machineProxyRoutes.js.map +1 -0
- package/dist/server/machines/machineRoutes.js +56 -0
- package/dist/server/machines/machineRoutes.js.map +1 -0
- package/dist/server/machines/machineService.js +238 -0
- package/dist/server/machines/machineService.js.map +1 -0
- package/dist/server/machines/machineStore.js +128 -0
- package/dist/server/machines/machineStore.js.map +1 -0
- package/dist/server/models/modelsConfigRoutes.js +40 -0
- package/dist/server/models/modelsConfigRoutes.js.map +1 -0
- package/dist/server/models/modelsConfigService.js +339 -0
- package/dist/server/models/modelsConfigService.js.map +1 -0
- package/dist/server/piPackagePluginsConfigRoutes.js +86 -0
- package/dist/server/piPackagePluginsConfigRoutes.js.map +1 -0
- package/dist/server/piPackagePluginsConfigService.js +311 -0
- package/dist/server/piPackagePluginsConfigService.js.map +1 -0
- package/dist/server/piPackageRoutes.js +91 -0
- package/dist/server/piPackageRoutes.js.map +1 -0
- package/dist/server/piPackageService.js +101 -0
- package/dist/server/piPackageService.js.map +1 -0
- package/dist/server/piWebUiPluginService.js +326 -0
- package/dist/server/piWebUiPluginService.js.map +1 -0
- package/dist/server/piWebUiReleaseLookupCache.js +37 -0
- package/dist/server/piWebUiReleaseLookupCache.js.map +1 -0
- package/dist/server/piWebUiStatus.js +622 -0
- package/dist/server/piWebUiStatus.js.map +1 -0
- package/dist/server/piWebUiStatusCache.js +45 -0
- package/dist/server/piWebUiStatusCache.js.map +1 -0
- package/dist/server/projects/directorySuggestions.js +37 -0
- package/dist/server/projects/directorySuggestions.js.map +1 -0
- package/dist/server/projects/projectService.js +31 -0
- package/dist/server/projects/projectService.js.map +1 -0
- package/dist/server/realtime/sessionEventHub.js +70 -0
- package/dist/server/realtime/sessionEventHub.js.map +1 -0
- package/dist/server/sessiond/sessionDaemonStartup.js +49 -0
- package/dist/server/sessiond/sessionDaemonStartup.js.map +1 -0
- package/dist/server/sessiond/sessionProxyRoutes.js +87 -0
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -0
- package/dist/server/sessiond/skillsGithubToken.js +7 -0
- package/dist/server/sessiond/skillsGithubToken.js.map +1 -0
- package/dist/server/sessiond.js +152 -0
- package/dist/server/sessiond.js.map +1 -0
- package/dist/server/sessions/attachmentService.js +119 -0
- package/dist/server/sessions/attachmentService.js.map +1 -0
- package/dist/server/sessions/authProviderOptions.js +50 -0
- package/dist/server/sessions/authProviderOptions.js.map +1 -0
- package/dist/server/sessions/authRoutes.js +69 -0
- package/dist/server/sessions/authRoutes.js.map +1 -0
- package/dist/server/sessions/authService.js +134 -0
- package/dist/server/sessions/authService.js.map +1 -0
- package/dist/server/sessions/builtinCommands.js +27 -0
- package/dist/server/sessions/builtinCommands.js.map +1 -0
- package/dist/server/sessions/editPreview.js +196 -0
- package/dist/server/sessions/editPreview.js.map +1 -0
- package/dist/server/sessions/messagePaging.js +43 -0
- package/dist/server/sessions/messagePaging.js.map +1 -0
- package/dist/server/sessions/oauthLoginFlowService.js +349 -0
- package/dist/server/sessions/oauthLoginFlowService.js.map +1 -0
- package/dist/server/sessions/piSessionManagerGateway.js +115 -0
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -0
- package/dist/server/sessions/piSessionService.js +3230 -0
- package/dist/server/sessions/piSessionService.js.map +1 -0
- package/dist/server/sessions/plainTextTheme.js +112 -0
- package/dist/server/sessions/plainTextTheme.js.map +1 -0
- package/dist/server/sessions/sessionArchiveMigration.js +590 -0
- package/dist/server/sessions/sessionArchiveMigration.js.map +1 -0
- package/dist/server/sessions/sessionArchiveStore.js +262 -0
- package/dist/server/sessions/sessionArchiveStore.js.map +1 -0
- package/dist/server/sessions/sessionArchiveTree.js +35 -0
- package/dist/server/sessions/sessionArchiveTree.js.map +1 -0
- package/dist/server/sessions/sessionCleanup.js +157 -0
- package/dist/server/sessions/sessionCleanup.js.map +1 -0
- package/dist/server/sessions/sessionCommandService.js +313 -0
- package/dist/server/sessions/sessionCommandService.js.map +1 -0
- package/dist/server/sessions/sessionDefaultsRoutes.js +65 -0
- package/dist/server/sessions/sessionDefaultsRoutes.js.map +1 -0
- package/dist/server/sessions/sessionDefaultsService.js +90 -0
- package/dist/server/sessions/sessionDefaultsService.js.map +1 -0
- package/dist/server/sessions/sessionHistoryExport.js +115 -0
- package/dist/server/sessions/sessionHistoryExport.js.map +1 -0
- package/dist/server/sessions/sessionMetadataStore.js +102 -0
- package/dist/server/sessions/sessionMetadataStore.js.map +1 -0
- package/dist/server/sessions/sessionNameGenerator.js +90 -0
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -0
- package/dist/server/sessions/sessionNotificationStore.js +484 -0
- package/dist/server/sessions/sessionNotificationStore.js.map +1 -0
- package/dist/server/sessions/sessionRoutes.js +590 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -0
- package/dist/server/sessions/sessionRuntimeStore.js +2 -0
- package/dist/server/sessions/sessionRuntimeStore.js.map +1 -0
- package/dist/server/sessions/sessionService.js +2 -0
- package/dist/server/sessions/sessionService.js.map +1 -0
- package/dist/server/sessions/sessionTreeProjection.js +250 -0
- package/dist/server/sessions/sessionTreeProjection.js.map +1 -0
- package/dist/server/sessions/sessionUnreadStore.js +520 -0
- package/dist/server/sessions/sessionUnreadStore.js.map +1 -0
- package/dist/server/sessions/spawnSessionTool.js +41 -0
- package/dist/server/sessions/spawnSessionTool.js.map +1 -0
- package/dist/server/sessions/spawnSubsessionTool.js +214 -0
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -0
- package/dist/server/sessions/spawnTargetResolver.js +36 -0
- package/dist/server/sessions/spawnTargetResolver.js.map +1 -0
- package/dist/server/sessions/subsessionTranscript.js +235 -0
- package/dist/server/sessions/subsessionTranscript.js.map +1 -0
- package/dist/server/skills/runNpx.js +30 -0
- package/dist/server/skills/runNpx.js.map +1 -0
- package/dist/server/skills/skillLock.js +115 -0
- package/dist/server/skills/skillLock.js.map +1 -0
- package/dist/server/skills/skillUpdates.js +194 -0
- package/dist/server/skills/skillUpdates.js.map +1 -0
- package/dist/server/skills/skillsConfigRoutes.js +64 -0
- package/dist/server/skills/skillsConfigRoutes.js.map +1 -0
- package/dist/server/skills/skillsConfigService.js +391 -0
- package/dist/server/skills/skillsConfigService.js.map +1 -0
- package/dist/server/storage/projectStore.js +88 -0
- package/dist/server/storage/projectStore.js.map +1 -0
- package/dist/server/systemInfoRoutes.js +265 -0
- package/dist/server/systemInfoRoutes.js.map +1 -0
- package/dist/server/terminalProxyRoutes.js +140 -0
- package/dist/server/terminalProxyRoutes.js.map +1 -0
- package/dist/server/terminals/terminalRoutes.js +155 -0
- package/dist/server/terminals/terminalRoutes.js.map +1 -0
- package/dist/server/terminals/terminalService.js +305 -0
- package/dist/server/terminals/terminalService.js.map +1 -0
- package/dist/server/terminals/terminalSize.js +17 -0
- package/dist/server/terminals/terminalSize.js.map +1 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/webSocketBridge.js +32 -0
- package/dist/server/webSocketBridge.js.map +1 -0
- package/dist/server/workingDirectory.js +44 -0
- package/dist/server/workingDirectory.js.map +1 -0
- package/dist/server/workspaceExplorerRoutes.js +109 -0
- package/dist/server/workspaceExplorerRoutes.js.map +1 -0
- package/dist/server/workspaces/effectivePathAccess.js +27 -0
- package/dist/server/workspaces/effectivePathAccess.js.map +1 -0
- package/dist/server/workspaces/fileContentService.js +181 -0
- package/dist/server/workspaces/fileContentService.js.map +1 -0
- package/dist/server/workspaces/fileSuggestions.js +520 -0
- package/dist/server/workspaces/fileSuggestions.js.map +1 -0
- package/dist/server/workspaces/fileTreeService.js +35 -0
- package/dist/server/workspaces/fileTreeService.js.map +1 -0
- package/dist/server/workspaces/gitWorktreeDiscovery.js +34 -0
- package/dist/server/workspaces/gitWorktreeDiscovery.js.map +1 -0
- package/dist/server/workspaces/imagePreviewService.js +40 -0
- package/dist/server/workspaces/imagePreviewService.js.map +1 -0
- package/dist/server/workspaces/pathAccessPolicy.js +90 -0
- package/dist/server/workspaces/pathAccessPolicy.js.map +1 -0
- package/dist/server/workspaces/pathSafety.js +45 -0
- package/dist/server/workspaces/pathSafety.js.map +1 -0
- package/dist/server/workspaces/projectPiWebUiConfig.js +61 -0
- package/dist/server/workspaces/projectPiWebUiConfig.js.map +1 -0
- package/dist/server/workspaces/workspaceContext.js +8 -0
- package/dist/server/workspaces/workspaceContext.js.map +1 -0
- package/dist/server/workspaces/workspaceDeletionRoutes.js +113 -0
- package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -0
- package/dist/server/workspaces/workspaceService.js +39 -0
- package/dist/server/workspaces/workspaceService.js.map +1 -0
- package/dist/sessiond/activeAgentProfile.js +31 -0
- package/dist/sessiond/activeAgentProfile.js.map +1 -0
- package/dist/sessiond/config.js +9 -0
- package/dist/sessiond/config.js.map +1 -0
- package/dist/sessiond/sessionDaemonClient.js +103 -0
- package/dist/sessiond/sessionDaemonClient.js.map +1 -0
- package/dist/shared/activeAgentProfile.js +76 -0
- package/dist/shared/activeAgentProfile.js.map +1 -0
- package/dist/shared/activity.js +11 -0
- package/dist/shared/activity.js.map +1 -0
- package/dist/shared/apiTypes.d.ts +1212 -0
- package/dist/shared/apiTypes.js +25 -0
- package/dist/shared/apiTypes.js.map +1 -0
- package/dist/shared/capabilities.js +69 -0
- package/dist/shared/capabilities.js.map +1 -0
- package/dist/shared/federatedRoutes.js +109 -0
- package/dist/shared/federatedRoutes.js.map +1 -0
- package/dist/shared/machinePluginIds.js +41 -0
- package/dist/shared/machinePluginIds.js.map +1 -0
- package/dist/shared/piWebUiStatusParsing.js +108 -0
- package/dist/shared/piWebUiStatusParsing.js.map +1 -0
- package/dist/shared/pluginIds.js +5 -0
- package/dist/shared/pluginIds.js.map +1 -0
- package/dist/shared/promptAttachments.js +92 -0
- package/dist/shared/promptAttachments.js.map +1 -0
- package/dist/shared/thinkingLevels.d.ts +27 -0
- package/dist/shared/thinkingLevels.js +31 -0
- package/dist/shared/thinkingLevels.js.map +1 -0
- package/dist/shared/workspaceDeletion.js +12 -0
- package/dist/shared/workspaceDeletion.js.map +1 -0
- package/dist/shared/workspaceFiles.js +3 -0
- package/dist/shared/workspaceFiles.js.map +1 -0
- package/docs/assets/favicon.svg +8 -0
- package/docs/assets/pi-webui-banner.png +0 -0
- package/docs/assets/pi-webui-desktop.png +0 -0
- package/docs/assets/pi-webui-mobile.png +0 -0
- package/docs/assets/pi-webui-tablet.png +0 -0
- package/docs/config.md +265 -0
- package/docs/plugins.md +988 -0
- package/extensions/pi-webui.ts +133 -0
- package/package.json +143 -0
- package/plugin-api/unstable.d.ts +1 -0
- package/plugin-api.d.ts +1 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** Register daemon-owned models.json editing and connection-test endpoints. */
|
|
2
|
+
export function registerModelsConfigRoutes(app, models, prefix = "") {
|
|
3
|
+
app.get(`${prefix}/models-config`, async (_request, reply) => {
|
|
4
|
+
try {
|
|
5
|
+
return await models.read();
|
|
6
|
+
}
|
|
7
|
+
catch (error) {
|
|
8
|
+
return reply.code(500).send({ error: errorMessage(error) });
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
app.put(`${prefix}/models-config`, async (request, reply) => {
|
|
12
|
+
try {
|
|
13
|
+
return await models.save(request.body);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
return reply.code(400).send({ error: errorMessage(error) });
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
app.post(`${prefix}/models-config/test`, async (request, reply) => {
|
|
20
|
+
try {
|
|
21
|
+
const result = await models.test(request.body);
|
|
22
|
+
return await reply.code(result.ok ? 200 : 400).send(result);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
return reply.code(400).send({ ok: false, error: errorMessage(error) });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
app.post(`${prefix}/models-config/discover`, async (request, reply) => {
|
|
29
|
+
try {
|
|
30
|
+
return await models.discover(request.body);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return reply.code(400).send({ error: errorMessage(error) });
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function errorMessage(error) {
|
|
38
|
+
return error instanceof Error ? error.message : String(error);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=modelsConfigRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelsConfigRoutes.js","sourceRoot":"","sources":["../../../src/server/models/modelsConfigRoutes.ts"],"names":[],"mappings":"AAGA,+EAA+E;AAC/E,MAAM,UAAU,0BAA0B,CAAC,GAAoB,EAAE,MAA2B,EAAE,MAAM,GAAG,EAAE;IACvG,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,gBAAgB,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;QAC3D,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAoB,GAAG,MAAM,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC7E,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAoB,GAAG,MAAM,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACnF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC/C,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAoB,GAAG,MAAM,yBAAyB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvF,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { ModelRuntime } from "@earendil-works/pi-coding-agent";
|
|
5
|
+
const MODEL_CONNECTION_TEST_TIMEOUT_MS = 20_000;
|
|
6
|
+
const MODEL_DISCOVERY_TIMEOUT_MS = 20_000;
|
|
7
|
+
/**
|
|
8
|
+
* Owns the active profile's editable `models.json` document and isolated model
|
|
9
|
+
* connection checks. It intentionally lives with sessiond so file ownership and
|
|
10
|
+
* credentials stay aligned with the long-lived Pi runtime.
|
|
11
|
+
*/
|
|
12
|
+
export class ModelsConfigService {
|
|
13
|
+
constructor({ agentDir, modelRuntime, createConnectionRuntime = createConnectionRuntimeForProfile }) {
|
|
14
|
+
this.modelsPath = join(agentDir, "models.json");
|
|
15
|
+
this.authPath = join(agentDir, "auth.json");
|
|
16
|
+
this.modelRuntime = modelRuntime;
|
|
17
|
+
this.createConnectionRuntime = createConnectionRuntime;
|
|
18
|
+
}
|
|
19
|
+
async read() {
|
|
20
|
+
try {
|
|
21
|
+
return normalizeModelsConfigDocument(JSON.parse(await readFile(this.modelsPath, "utf8")));
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (isMissingFile(error) || error instanceof SyntaxError)
|
|
25
|
+
return emptyModelsConfigDocument();
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async save(value) {
|
|
30
|
+
const document = parseModelsConfigDocument(value);
|
|
31
|
+
await mkdir(dirname(this.modelsPath), { recursive: true });
|
|
32
|
+
await writeFile(this.modelsPath, `${JSON.stringify(document, null, 2)}\n`, "utf8");
|
|
33
|
+
await this.modelRuntime?.reloadConfig();
|
|
34
|
+
return { success: true };
|
|
35
|
+
}
|
|
36
|
+
async test(value) {
|
|
37
|
+
const request = parseModelConnectionTestRequest(value);
|
|
38
|
+
let temporaryDirectory;
|
|
39
|
+
try {
|
|
40
|
+
temporaryDirectory = await mkdtemp(join(tmpdir(), "pi-webui-model-test-"));
|
|
41
|
+
const temporaryModelsPath = join(temporaryDirectory, "models.json");
|
|
42
|
+
await writeFile(temporaryModelsPath, JSON.stringify(modelsDocumentForConnectionTest(request), null, 2), "utf8");
|
|
43
|
+
const runtime = await this.createConnectionRuntime({ modelsPath: temporaryModelsPath, authPath: this.authPath });
|
|
44
|
+
const loadError = runtime.getError();
|
|
45
|
+
if (loadError !== undefined)
|
|
46
|
+
return { ok: false, error: loadError };
|
|
47
|
+
const model = runtime.getModel(request.providerName, request.model.id);
|
|
48
|
+
if (model === undefined)
|
|
49
|
+
return { ok: false, error: `Model not found: ${request.providerName}/${request.model.id}` };
|
|
50
|
+
const resolved = await runtime.getAuth(model);
|
|
51
|
+
if (resolved?.auth.apiKey === undefined || resolved.auth.apiKey === "") {
|
|
52
|
+
return { ok: false, error: `No API key found for "${request.providerName}"` };
|
|
53
|
+
}
|
|
54
|
+
return await runModelConnectionTest(runtime, model, resolved.auth.apiKey, resolved.auth.headers);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
return { ok: false, error: errorMessage(error) };
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
if (temporaryDirectory !== undefined)
|
|
61
|
+
await rm(temporaryDirectory, { recursive: true, force: true });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async discover(value) {
|
|
65
|
+
const request = parseModelDiscoveryRequest(value);
|
|
66
|
+
let temporaryDirectory;
|
|
67
|
+
try {
|
|
68
|
+
temporaryDirectory = await mkdtemp(join(tmpdir(), "pi-webui-model-discovery-"));
|
|
69
|
+
const temporaryModelsPath = join(temporaryDirectory, "models.json");
|
|
70
|
+
await writeFile(temporaryModelsPath, JSON.stringify(modelsDocumentForDiscovery(request), null, 2), "utf8");
|
|
71
|
+
const runtime = await this.createConnectionRuntime({ modelsPath: temporaryModelsPath, authPath: this.authPath });
|
|
72
|
+
const loadError = runtime.getError();
|
|
73
|
+
if (loadError !== undefined)
|
|
74
|
+
throw new Error(loadError);
|
|
75
|
+
const resolved = await runtime.getAuth(request.providerName);
|
|
76
|
+
if (resolved === undefined)
|
|
77
|
+
throw new Error(`No API key found for "${request.providerName}"`);
|
|
78
|
+
const endpoint = modelDiscoveryEndpoint(request.provider.baseUrl, request.provider.api, resolved.auth.apiKey);
|
|
79
|
+
const response = await fetchModels(endpoint, request.provider.api, resolved.auth.apiKey, resolved.auth.headers);
|
|
80
|
+
if (!response.ok)
|
|
81
|
+
throw new Error(`Model discovery request failed with HTTP ${String(response.status)}`);
|
|
82
|
+
return { models: parseDiscoveredModels(await response.json(), request.provider.api) };
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
if (temporaryDirectory !== undefined)
|
|
86
|
+
await rm(temporaryDirectory, { recursive: true, force: true });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export function emptyModelsConfigDocument() {
|
|
91
|
+
return { providers: {} };
|
|
92
|
+
}
|
|
93
|
+
export function normalizeModelsConfigDocument(value) {
|
|
94
|
+
if (!isRecord(value))
|
|
95
|
+
return emptyModelsConfigDocument();
|
|
96
|
+
const providers = value["providers"];
|
|
97
|
+
if (providers !== undefined && !isRecord(providers))
|
|
98
|
+
return { ...value, providers: {} };
|
|
99
|
+
return { ...value, ...(providers === undefined ? { providers: {} } : {}) };
|
|
100
|
+
}
|
|
101
|
+
export function parseModelsConfigDocument(value) {
|
|
102
|
+
if (!isRecord(value))
|
|
103
|
+
throw new Error("models.json must be a JSON object");
|
|
104
|
+
const providers = value["providers"];
|
|
105
|
+
if (providers !== undefined && !isRecord(providers))
|
|
106
|
+
throw new Error("models.json providers must be an object");
|
|
107
|
+
return { ...value };
|
|
108
|
+
}
|
|
109
|
+
export function parseModelConnectionTestRequest(value) {
|
|
110
|
+
if (!isRecord(value))
|
|
111
|
+
throw new Error("Model test request must be an object");
|
|
112
|
+
const providerName = requiredTrimmedString(value, "providerName");
|
|
113
|
+
const provider = requiredRecord(value, "provider");
|
|
114
|
+
const model = requiredRecord(value, "model");
|
|
115
|
+
const modelId = requiredTrimmedString(model, "id");
|
|
116
|
+
return {
|
|
117
|
+
providerName,
|
|
118
|
+
provider: { ...provider },
|
|
119
|
+
model: { ...model, id: modelId },
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function parseModelDiscoveryRequest(value) {
|
|
123
|
+
if (!isRecord(value))
|
|
124
|
+
throw new Error("Model discovery request must be an object");
|
|
125
|
+
const providerName = requiredTrimmedString(value, "providerName");
|
|
126
|
+
const provider = requiredRecord(value, "provider");
|
|
127
|
+
return {
|
|
128
|
+
providerName,
|
|
129
|
+
provider: { ...provider, baseUrl: requiredTrimmedString(provider, "baseUrl") },
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function modelsDocumentForConnectionTest(request) {
|
|
133
|
+
return {
|
|
134
|
+
providers: {
|
|
135
|
+
[request.providerName]: {
|
|
136
|
+
...request.provider,
|
|
137
|
+
models: [{ ...request.model, id: request.model.id.trim() }],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function modelsDocumentForDiscovery(request) {
|
|
143
|
+
return { providers: { [request.providerName]: providerWithoutModels(request.provider) } };
|
|
144
|
+
}
|
|
145
|
+
function providerWithoutModels(provider) {
|
|
146
|
+
const result = {};
|
|
147
|
+
for (const [name, value] of Object.entries(provider)) {
|
|
148
|
+
if (name !== "models")
|
|
149
|
+
result[name] = value;
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
async function createConnectionRuntimeForProfile(options) {
|
|
154
|
+
return await ModelRuntime.create({
|
|
155
|
+
modelsPath: options.modelsPath,
|
|
156
|
+
authPath: options.authPath,
|
|
157
|
+
// Isolated checks resolve the profile's credentials but do not refresh
|
|
158
|
+
// unrelated provider catalogs before issuing their request.
|
|
159
|
+
allowModelNetwork: false,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function modelDiscoveryEndpoint(baseUrl, api, apiKey) {
|
|
163
|
+
if (baseUrl === undefined)
|
|
164
|
+
throw new Error("baseUrl is required");
|
|
165
|
+
const endpoint = new URL("models", baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
166
|
+
if (endpoint.protocol !== "http:" && endpoint.protocol !== "https:")
|
|
167
|
+
throw new Error("Provider base URL must use HTTP or HTTPS");
|
|
168
|
+
if (api === "google-generative-ai") {
|
|
169
|
+
if (apiKey === undefined || apiKey === "")
|
|
170
|
+
throw new Error("No API key found for Google model discovery");
|
|
171
|
+
endpoint.searchParams.set("key", apiKey);
|
|
172
|
+
}
|
|
173
|
+
return endpoint;
|
|
174
|
+
}
|
|
175
|
+
async function fetchModels(endpoint, api, apiKey, configuredHeaders) {
|
|
176
|
+
const controller = new AbortController();
|
|
177
|
+
const timeout = setTimeout(() => { controller.abort(); }, MODEL_DISCOVERY_TIMEOUT_MS);
|
|
178
|
+
const suppressedHeaders = new Set();
|
|
179
|
+
const headers = new Headers({ accept: "application/json" });
|
|
180
|
+
for (const [name, value] of Object.entries(configuredHeaders ?? {})) {
|
|
181
|
+
if (value === null) {
|
|
182
|
+
suppressedHeaders.add(name.toLowerCase());
|
|
183
|
+
headers.delete(name);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
headers.set(name, value);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (api === "google-generative-ai") {
|
|
190
|
+
// Google accepts the resolved key in the query string above.
|
|
191
|
+
}
|
|
192
|
+
else if (api === "anthropic-messages") {
|
|
193
|
+
setDefaultDiscoveryHeader(headers, suppressedHeaders, "x-api-key", apiKey);
|
|
194
|
+
setDefaultDiscoveryHeader(headers, suppressedHeaders, "anthropic-version", "2023-06-01");
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
setDefaultDiscoveryHeader(headers, suppressedHeaders, "authorization", apiKey === undefined || apiKey === "" ? undefined : `Bearer ${apiKey}`);
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
return await fetch(endpoint, { headers, signal: controller.signal });
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
if (controller.signal.aborted)
|
|
204
|
+
throw new Error("Model discovery timed out", { cause: error });
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
clearTimeout(timeout);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function setDefaultDiscoveryHeader(headers, suppressedHeaders, name, value) {
|
|
212
|
+
if (value === undefined || headers.has(name) || suppressedHeaders.has(name.toLowerCase()))
|
|
213
|
+
return;
|
|
214
|
+
headers.set(name, value);
|
|
215
|
+
}
|
|
216
|
+
function parseDiscoveredModels(value, api) {
|
|
217
|
+
const entries = modelDiscoveryEntries(value);
|
|
218
|
+
const models = [];
|
|
219
|
+
const knownIds = new Set();
|
|
220
|
+
for (const entry of entries) {
|
|
221
|
+
const model = parseDiscoveredModel(entry, api);
|
|
222
|
+
if (model === undefined || knownIds.has(model.id))
|
|
223
|
+
continue;
|
|
224
|
+
knownIds.add(model.id);
|
|
225
|
+
models.push(model);
|
|
226
|
+
}
|
|
227
|
+
return models;
|
|
228
|
+
}
|
|
229
|
+
function modelDiscoveryEntries(value) {
|
|
230
|
+
if (Array.isArray(value))
|
|
231
|
+
return value;
|
|
232
|
+
if (!isRecord(value))
|
|
233
|
+
throw new Error("Model discovery response must be an object or array");
|
|
234
|
+
const data = value["data"];
|
|
235
|
+
if (Array.isArray(data))
|
|
236
|
+
return data;
|
|
237
|
+
const models = value["models"];
|
|
238
|
+
if (Array.isArray(models))
|
|
239
|
+
return models;
|
|
240
|
+
throw new Error("Model discovery response did not contain a model list");
|
|
241
|
+
}
|
|
242
|
+
function parseDiscoveredModel(value, api) {
|
|
243
|
+
if (typeof value === "string")
|
|
244
|
+
return discoveredModel(value);
|
|
245
|
+
if (!isRecord(value))
|
|
246
|
+
return undefined;
|
|
247
|
+
const rawId = typeof value["id"] === "string" ? value["id"] : value["name"];
|
|
248
|
+
if (typeof rawId !== "string")
|
|
249
|
+
return undefined;
|
|
250
|
+
const id = api === "google-generative-ai" ? rawId.replace(/^models\//u, "") : rawId;
|
|
251
|
+
const name = firstString(value["displayName"], value["display_name"], typeof value["id"] === "string" ? value["name"] : undefined);
|
|
252
|
+
return discoveredModel(id, name);
|
|
253
|
+
}
|
|
254
|
+
function discoveredModel(id, name) {
|
|
255
|
+
const trimmedId = id.trim();
|
|
256
|
+
if (trimmedId === "")
|
|
257
|
+
return undefined;
|
|
258
|
+
const trimmedName = name?.trim();
|
|
259
|
+
return trimmedName === undefined || trimmedName === "" || trimmedName === trimmedId
|
|
260
|
+
? { id: trimmedId }
|
|
261
|
+
: { id: trimmedId, name: trimmedName };
|
|
262
|
+
}
|
|
263
|
+
function firstString(...values) {
|
|
264
|
+
return values.find((value) => typeof value === "string");
|
|
265
|
+
}
|
|
266
|
+
async function runModelConnectionTest(runtime, model, apiKey, headers) {
|
|
267
|
+
const controller = new AbortController();
|
|
268
|
+
const timeout = setTimeout(() => { controller.abort(); }, MODEL_CONNECTION_TEST_TIMEOUT_MS);
|
|
269
|
+
const startedAt = Date.now();
|
|
270
|
+
let status;
|
|
271
|
+
try {
|
|
272
|
+
const message = await runtime.completeSimple(model, {
|
|
273
|
+
messages: [{
|
|
274
|
+
role: "user",
|
|
275
|
+
content: "Reply with OK only.",
|
|
276
|
+
timestamp: Date.now(),
|
|
277
|
+
}],
|
|
278
|
+
}, {
|
|
279
|
+
apiKey,
|
|
280
|
+
...(headers === undefined ? {} : { headers }),
|
|
281
|
+
maxTokens: 16,
|
|
282
|
+
timeoutMs: MODEL_CONNECTION_TEST_TIMEOUT_MS,
|
|
283
|
+
maxRetries: 0,
|
|
284
|
+
cacheRetention: "none",
|
|
285
|
+
signal: controller.signal,
|
|
286
|
+
onResponse: (response) => { status = response.status; },
|
|
287
|
+
});
|
|
288
|
+
const latencyMs = Date.now() - startedAt;
|
|
289
|
+
if (message.stopReason === "error" || message.stopReason === "aborted") {
|
|
290
|
+
return {
|
|
291
|
+
ok: false,
|
|
292
|
+
error: message.errorMessage ?? (controller.signal.aborted ? "Test timed out" : "Model returned an error"),
|
|
293
|
+
latencyMs,
|
|
294
|
+
...(status === undefined ? {} : { status }),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
ok: true,
|
|
299
|
+
latencyMs,
|
|
300
|
+
...(status === undefined ? {} : { status }),
|
|
301
|
+
responseText: assistantText(message.content),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
finally {
|
|
305
|
+
clearTimeout(timeout);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function assistantText(content) {
|
|
309
|
+
return content
|
|
310
|
+
.filter(isTextContent)
|
|
311
|
+
.map((block) => block.text)
|
|
312
|
+
.join("")
|
|
313
|
+
.slice(0, 300);
|
|
314
|
+
}
|
|
315
|
+
function isTextContent(value) {
|
|
316
|
+
return isRecord(value) && value["type"] === "text" && typeof value["text"] === "string";
|
|
317
|
+
}
|
|
318
|
+
function requiredTrimmedString(record, field) {
|
|
319
|
+
const value = record[field];
|
|
320
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
321
|
+
throw new Error(`${field} is required`);
|
|
322
|
+
return value.trim();
|
|
323
|
+
}
|
|
324
|
+
function requiredRecord(record, field) {
|
|
325
|
+
const value = record[field];
|
|
326
|
+
if (!isRecord(value))
|
|
327
|
+
throw new Error(`${field} is required`);
|
|
328
|
+
return value;
|
|
329
|
+
}
|
|
330
|
+
function isRecord(value) {
|
|
331
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
332
|
+
}
|
|
333
|
+
function isMissingFile(error) {
|
|
334
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
335
|
+
}
|
|
336
|
+
function errorMessage(error) {
|
|
337
|
+
return error instanceof Error ? error.message : String(error);
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=modelsConfigService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelsConfigService.js","sourceRoot":"","sources":["../../../src/server/models/modelsConfigService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ActiveAgentProfileAccessError } from "./activeAgentProfileProvider.js";
|
|
2
|
+
class PiPackagePluginsRequestError extends Error {
|
|
3
|
+
}
|
|
4
|
+
/** Register workspace-aware Pi package Plugins routes at the browser/API edge. */
|
|
5
|
+
export function registerPiPackagePluginsConfigRoutes(app, service, prefix = "/api") {
|
|
6
|
+
const routePrefix = normalizeRoutePrefix(prefix);
|
|
7
|
+
app.get(`${routePrefix}/package-plugins`, async (request, reply) => {
|
|
8
|
+
try {
|
|
9
|
+
return await service.list(requiredCwd(request.query.cwd));
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
return sendError(reply, error);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
app.post(`${routePrefix}/package-plugins`, async (request, reply) => {
|
|
16
|
+
try {
|
|
17
|
+
return await service.mutate(parseMutationRequest(request.body));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
return sendError(reply, error);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function normalizeRoutePrefix(prefix) {
|
|
25
|
+
const normalized = prefix.replace(/\/+$/u, "");
|
|
26
|
+
return normalized === "" ? "/api" : normalized;
|
|
27
|
+
}
|
|
28
|
+
function parseMutationRequest(value) {
|
|
29
|
+
const body = requireObject(value);
|
|
30
|
+
const actionValue = body["action"];
|
|
31
|
+
if (!isPiPackagePluginAction(actionValue)) {
|
|
32
|
+
throw new PiPackagePluginsRequestError(`Unsupported Pi package plugin action: ${typeof actionValue === "string" ? actionValue : String(actionValue)}`);
|
|
33
|
+
}
|
|
34
|
+
const source = optionalSource(body["source"]);
|
|
35
|
+
if (actionValue !== "update" && source === undefined)
|
|
36
|
+
throw new PiPackagePluginsRequestError("source is required");
|
|
37
|
+
const scope = parseScope(body["scope"]);
|
|
38
|
+
return {
|
|
39
|
+
action: actionValue,
|
|
40
|
+
cwd: requiredCwd(body["cwd"]),
|
|
41
|
+
scope,
|
|
42
|
+
...(source === undefined ? {} : { source }),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function requiredCwd(value) {
|
|
46
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
47
|
+
throw new PiPackagePluginsRequestError("cwd is required");
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
function optionalSource(value) {
|
|
51
|
+
if (value === undefined)
|
|
52
|
+
return undefined;
|
|
53
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
54
|
+
throw new PiPackagePluginsRequestError("source is required");
|
|
55
|
+
return value.trim();
|
|
56
|
+
}
|
|
57
|
+
function parseScope(value) {
|
|
58
|
+
if (value === undefined)
|
|
59
|
+
return "global";
|
|
60
|
+
if (value === "global" || value === "project")
|
|
61
|
+
return value;
|
|
62
|
+
throw new PiPackagePluginsRequestError("Pi package plugin scope must be \"global\" or \"project\"");
|
|
63
|
+
}
|
|
64
|
+
function isPiPackagePluginAction(value) {
|
|
65
|
+
return value === "install" || value === "remove" || value === "update" || value === "disable" || value === "enable";
|
|
66
|
+
}
|
|
67
|
+
function requireObject(value) {
|
|
68
|
+
if (!isRecord(value))
|
|
69
|
+
throw new PiPackagePluginsRequestError("Pi package plugin request body must be an object");
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
function isRecord(value) {
|
|
73
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
74
|
+
}
|
|
75
|
+
function sendError(reply, error) {
|
|
76
|
+
const status = error instanceof PiPackagePluginsRequestError
|
|
77
|
+
? 400
|
|
78
|
+
: error instanceof ActiveAgentProfileAccessError
|
|
79
|
+
? 503
|
|
80
|
+
: 500;
|
|
81
|
+
return reply.code(status).send({ error: errorMessage(error) });
|
|
82
|
+
}
|
|
83
|
+
function errorMessage(error) {
|
|
84
|
+
return error instanceof Error ? error.message : String(error);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=piPackagePluginsConfigRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piPackagePluginsConfigRoutes.js","sourceRoot":"","sources":["../../src/server/piPackagePluginsConfigRoutes.ts"],"names":[],"mappings":"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"}
|