@things-factory/integration-label-studio 9.1.19

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.
Files changed (152) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/EXTERNAL_DATA_SOURCING.md +484 -0
  3. package/IMPLEMENTATION_GUIDE.md +469 -0
  4. package/INTEGRATION.md +279 -0
  5. package/README.md +1014 -0
  6. package/SETUP_GUIDE.md +577 -0
  7. package/TEST_GUIDE.md +387 -0
  8. package/UI_CUSTOMIZATION.md +395 -0
  9. package/USER_SYNC_GUIDE.md +514 -0
  10. package/client/bootstrap.ts +1 -0
  11. package/client/index.ts +1 -0
  12. package/client/label-studio-label-page.ts +52 -0
  13. package/client/label-studio-project-create.ts +216 -0
  14. package/client/label-studio-project-list.ts +214 -0
  15. package/client/label-studio-wrapper.ts +294 -0
  16. package/client/route.ts +15 -0
  17. package/client/tsconfig.json +13 -0
  18. package/config/config.development.js +124 -0
  19. package/config/config.production.js +182 -0
  20. package/dist-client/bootstrap.d.ts +1 -0
  21. package/dist-client/bootstrap.js +2 -0
  22. package/dist-client/bootstrap.js.map +1 -0
  23. package/dist-client/index.d.ts +1 -0
  24. package/dist-client/index.js +2 -0
  25. package/dist-client/index.js.map +1 -0
  26. package/dist-client/label-studio-label-page.d.ts +8 -0
  27. package/dist-client/label-studio-label-page.js +54 -0
  28. package/dist-client/label-studio-label-page.js.map +1 -0
  29. package/dist-client/label-studio-project-create.d.ts +16 -0
  30. package/dist-client/label-studio-project-create.js +235 -0
  31. package/dist-client/label-studio-project-create.js.map +1 -0
  32. package/dist-client/label-studio-project-list.d.ts +16 -0
  33. package/dist-client/label-studio-project-list.js +222 -0
  34. package/dist-client/label-studio-project-list.js.map +1 -0
  35. package/dist-client/label-studio-wrapper.d.ts +57 -0
  36. package/dist-client/label-studio-wrapper.js +304 -0
  37. package/dist-client/label-studio-wrapper.js.map +1 -0
  38. package/dist-client/route.d.ts +1 -0
  39. package/dist-client/route.js +14 -0
  40. package/dist-client/route.js.map +1 -0
  41. package/dist-client/tsconfig.tsbuildinfo +1 -0
  42. package/dist-server/controller/label-studio-role-mapper.d.ts +35 -0
  43. package/dist-server/controller/label-studio-role-mapper.js +65 -0
  44. package/dist-server/controller/label-studio-role-mapper.js.map +1 -0
  45. package/dist-server/controller/user-provisioning-service.d.ts +66 -0
  46. package/dist-server/controller/user-provisioning-service.js +264 -0
  47. package/dist-server/controller/user-provisioning-service.js.map +1 -0
  48. package/dist-server/index.d.ts +7 -0
  49. package/dist-server/index.js +19 -0
  50. package/dist-server/index.js.map +1 -0
  51. package/dist-server/route/label-studio-sso.d.ts +2 -0
  52. package/dist-server/route/label-studio-sso.js +156 -0
  53. package/dist-server/route/label-studio-sso.js.map +1 -0
  54. package/dist-server/route/webhook.d.ts +65 -0
  55. package/dist-server/route/webhook.js +248 -0
  56. package/dist-server/route/webhook.js.map +1 -0
  57. package/dist-server/route.d.ts +1 -0
  58. package/dist-server/route.js +21 -0
  59. package/dist-server/route.js.map +1 -0
  60. package/dist-server/service/ai-prediction-service.d.ts +27 -0
  61. package/dist-server/service/ai-prediction-service.js +222 -0
  62. package/dist-server/service/ai-prediction-service.js.map +1 -0
  63. package/dist-server/service/dataset-labeling-integration.d.ts +44 -0
  64. package/dist-server/service/dataset-labeling-integration.js +512 -0
  65. package/dist-server/service/dataset-labeling-integration.js.map +1 -0
  66. package/dist-server/service/external-data-source-service.d.ts +78 -0
  67. package/dist-server/service/external-data-source-service.js +415 -0
  68. package/dist-server/service/external-data-source-service.js.map +1 -0
  69. package/dist-server/service/index.d.ts +12 -0
  70. package/dist-server/service/index.js +27 -0
  71. package/dist-server/service/index.js.map +1 -0
  72. package/dist-server/service/label-studio-sso-service.d.ts +38 -0
  73. package/dist-server/service/label-studio-sso-service.js +98 -0
  74. package/dist-server/service/label-studio-sso-service.js.map +1 -0
  75. package/dist-server/service/ml/ml-backend-service.d.ts +23 -0
  76. package/dist-server/service/ml/ml-backend-service.js +153 -0
  77. package/dist-server/service/ml/ml-backend-service.js.map +1 -0
  78. package/dist-server/service/prediction/prediction-management.d.ts +32 -0
  79. package/dist-server/service/prediction/prediction-management.js +299 -0
  80. package/dist-server/service/prediction/prediction-management.js.map +1 -0
  81. package/dist-server/service/project/project-management.d.ts +36 -0
  82. package/dist-server/service/project/project-management.js +309 -0
  83. package/dist-server/service/project/project-management.js.map +1 -0
  84. package/dist-server/service/task/task-management.d.ts +42 -0
  85. package/dist-server/service/task/task-management.js +372 -0
  86. package/dist-server/service/task/task-management.js.map +1 -0
  87. package/dist-server/service/user-provisioning/user-sync-mutation.d.ts +28 -0
  88. package/dist-server/service/user-provisioning/user-sync-mutation.js +111 -0
  89. package/dist-server/service/user-provisioning/user-sync-mutation.js.map +1 -0
  90. package/dist-server/service/webhook/webhook-management.d.ts +21 -0
  91. package/dist-server/service/webhook/webhook-management.js +134 -0
  92. package/dist-server/service/webhook/webhook-management.js.map +1 -0
  93. package/dist-server/tsconfig.tsbuildinfo +1 -0
  94. package/dist-server/types/dataset-labeling-types.d.ts +71 -0
  95. package/dist-server/types/dataset-labeling-types.js +259 -0
  96. package/dist-server/types/dataset-labeling-types.js.map +1 -0
  97. package/dist-server/types/label-studio-types.d.ts +128 -0
  98. package/dist-server/types/label-studio-types.js +494 -0
  99. package/dist-server/types/label-studio-types.js.map +1 -0
  100. package/dist-server/types/prediction-types.d.ts +39 -0
  101. package/dist-server/types/prediction-types.js +121 -0
  102. package/dist-server/types/prediction-types.js.map +1 -0
  103. package/dist-server/utils/annotation-exporter.d.ts +104 -0
  104. package/dist-server/utils/annotation-exporter.js +261 -0
  105. package/dist-server/utils/annotation-exporter.js.map +1 -0
  106. package/dist-server/utils/label-config-builder.d.ts +117 -0
  107. package/dist-server/utils/label-config-builder.js +286 -0
  108. package/dist-server/utils/label-config-builder.js.map +1 -0
  109. package/dist-server/utils/label-studio-api-client.d.ts +180 -0
  110. package/dist-server/utils/label-studio-api-client.js +401 -0
  111. package/dist-server/utils/label-studio-api-client.js.map +1 -0
  112. package/dist-server/utils/media-url-extractor.d.ts +45 -0
  113. package/dist-server/utils/media-url-extractor.js +152 -0
  114. package/dist-server/utils/media-url-extractor.js.map +1 -0
  115. package/dist-server/utils/task-transformer.d.ts +108 -0
  116. package/dist-server/utils/task-transformer.js +260 -0
  117. package/dist-server/utils/task-transformer.js.map +1 -0
  118. package/package.json +47 -0
  119. package/server/SERVER_STRUCTURE.md +351 -0
  120. package/server/controller/label-studio-role-mapper.ts +76 -0
  121. package/server/controller/user-provisioning-service.ts +340 -0
  122. package/server/index.ts +19 -0
  123. package/server/route/label-studio-sso.ts +194 -0
  124. package/server/route/webhook.ts +304 -0
  125. package/server/route.ts +35 -0
  126. package/server/service/ai-prediction-service.ts +239 -0
  127. package/server/service/dataset-labeling-integration.ts +590 -0
  128. package/server/service/external-data-source-service.ts +438 -0
  129. package/server/service/index.ts +24 -0
  130. package/server/service/label-studio-sso-service.ts +108 -0
  131. package/server/service/labeling-scenario-service.ts.deprecated +566 -0
  132. package/server/service/ml/ml-backend-service.ts +127 -0
  133. package/server/service/prediction/prediction-management.ts +281 -0
  134. package/server/service/project/project-management.ts +284 -0
  135. package/server/service/task/task-management.ts +363 -0
  136. package/server/service/user-provisioning/user-sync-mutation.ts +80 -0
  137. package/server/service/webhook/webhook-management.ts +109 -0
  138. package/server/tsconfig.json +11 -0
  139. package/server/types/dataset-labeling-types.ts +181 -0
  140. package/server/types/global.d.ts +23 -0
  141. package/server/types/label-studio-types.ts +346 -0
  142. package/server/types/prediction-types.ts +86 -0
  143. package/server/types/scenario-types.ts.deprecated +362 -0
  144. package/server/utils/annotation-exporter.ts +340 -0
  145. package/server/utils/label-config-builder.ts +340 -0
  146. package/server/utils/label-studio-api-client.ts +487 -0
  147. package/server/utils/media-url-extractor.ts +193 -0
  148. package/server/utils/task-transformer.ts +342 -0
  149. package/test-ai-prediction.js +268 -0
  150. package/test-dataset-integration.js +449 -0
  151. package/test-simple.js +89 -0
  152. package/things-factory.config.js +12 -0
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LabelStudioSSOService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const axios_1 = tslib_1.__importDefault(require("axios"));
6
+ const env_1 = require("@things-factory/env");
7
+ /**
8
+ * Label Studio SSO Service
9
+ *
10
+ * Handles JWT token acquisition from Label Studio for SSO authentication.
11
+ * The client application requests JWT tokens from Label Studio's token API,
12
+ * then uses cookie-based authentication to automatically log users in.
13
+ */
14
+ class LabelStudioSSOService {
15
+ /**
16
+ * Get Label Studio SSO configuration
17
+ */
18
+ static getConfig() {
19
+ const labelStudioConfig = env_1.config.get('labelStudio', {
20
+ serverUrl: 'http://localhost:8080',
21
+ apiToken: ''
22
+ });
23
+ return {
24
+ serverUrl: labelStudioConfig.serverUrl,
25
+ apiToken: labelStudioConfig.apiToken
26
+ };
27
+ }
28
+ /**
29
+ * Request JWT token from Label Studio for SSO authentication
30
+ *
31
+ * @param email User email address
32
+ * @returns JWT token and expiry time, or null if failed
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const tokenData = await LabelStudioSSOService.getSSOToken('user@example.com')
37
+ * if (tokenData) {
38
+ * console.log('Token:', tokenData.token)
39
+ * console.log('Expires in:', tokenData.expires_in, 'seconds')
40
+ * }
41
+ * ```
42
+ */
43
+ static async getSSOToken(email) {
44
+ const { serverUrl, apiToken } = this.getConfig();
45
+ if (!apiToken) {
46
+ console.error('[LSS SSO] Label Studio API token not configured');
47
+ return null;
48
+ }
49
+ if (!email) {
50
+ console.error('[LSS SSO] Email is required');
51
+ return null;
52
+ }
53
+ try {
54
+ console.log(`[LSS SSO] Requesting JWT token for: ${email}`);
55
+ const response = await axios_1.default.post(`${serverUrl}/api/sso/token`, { email }, {
56
+ headers: {
57
+ 'Authorization': `Token ${apiToken}`,
58
+ 'Content-Type': 'application/json'
59
+ },
60
+ timeout: 5000
61
+ });
62
+ const { token, expires_in } = response.data;
63
+ console.log(`[LSS SSO] JWT token acquired for ${email} (expires in ${expires_in}s)`);
64
+ return { token, expires_in };
65
+ }
66
+ catch (error) {
67
+ if (error.response) {
68
+ console.error(`[LSS SSO] Label Studio API error: ${error.response.status}`, error.response.data);
69
+ }
70
+ else if (error.request) {
71
+ console.error('[LSS SSO] No response from Label Studio:', error.message);
72
+ }
73
+ else {
74
+ console.error('[LSS SSO] Request error:', error.message);
75
+ }
76
+ return null;
77
+ }
78
+ }
79
+ /**
80
+ * Verify SSO configuration is properly set up
81
+ *
82
+ * @returns True if configuration is valid
83
+ */
84
+ static verifyConfig() {
85
+ const { serverUrl, apiToken } = this.getConfig();
86
+ if (!serverUrl) {
87
+ console.error('[LSS SSO] Label Studio server URL not configured');
88
+ return false;
89
+ }
90
+ if (!apiToken) {
91
+ console.error('[LSS SSO] Label Studio API token not configured');
92
+ return false;
93
+ }
94
+ return true;
95
+ }
96
+ }
97
+ exports.LabelStudioSSOService = LabelStudioSSOService;
98
+ //# sourceMappingURL=label-studio-sso-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label-studio-sso-service.js","sourceRoot":"","sources":["../../server/service/label-studio-sso-service.ts"],"names":[],"mappings":";;;;AAAA,0DAAyB;AACzB,6CAA4C;AAE5C;;;;;;GAMG;AACH,MAAa,qBAAqB;IAChC;;OAEG;IACK,MAAM,CAAC,SAAS;QACtB,MAAM,iBAAiB,GAAG,YAAM,CAAC,GAAG,CAAC,aAAa,EAAE;YAClD,SAAS,EAAE,uBAAuB;YAClC,QAAQ,EAAE,EAAE;SACb,CAAC,CAAA;QAEF,OAAO;YACL,SAAS,EAAE,iBAAiB,CAAC,SAAS;YACtC,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;SACrC,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,KAAa;QACpC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAEhD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAA;YAChE,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;YAC5C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,uCAAuC,KAAK,EAAE,CAAC,CAAA;YAE3D,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAC/B,GAAG,SAAS,gBAAgB,EAC5B,EAAE,KAAK,EAAE,EACT;gBACE,OAAO,EAAE;oBACP,eAAe,EAAE,SAAS,QAAQ,EAAE;oBACpC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,OAAO,EAAE,IAAI;aACd,CACF,CAAA;YAED,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAA;YAE3C,OAAO,CAAC,GAAG,CAAC,oCAAoC,KAAK,gBAAgB,UAAU,IAAI,CAAC,CAAA;YAEpF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;QAC9B,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YAClG,CAAC;iBAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBACzB,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;YAC1E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;YAC1D,CAAC;YAED,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,YAAY;QACjB,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAEhD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAA;YACjE,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAA;YAChE,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAjGD,sDAiGC","sourcesContent":["import axios from 'axios'\nimport { config } from '@things-factory/env'\n\n/**\n * Label Studio SSO Service\n *\n * Handles JWT token acquisition from Label Studio for SSO authentication.\n * The client application requests JWT tokens from Label Studio's token API,\n * then uses cookie-based authentication to automatically log users in.\n */\nexport class LabelStudioSSOService {\n /**\n * Get Label Studio SSO configuration\n */\n private static getConfig() {\n const labelStudioConfig = config.get('labelStudio', {\n serverUrl: 'http://localhost:8080',\n apiToken: ''\n })\n\n return {\n serverUrl: labelStudioConfig.serverUrl,\n apiToken: labelStudioConfig.apiToken\n }\n }\n\n /**\n * Request JWT token from Label Studio for SSO authentication\n *\n * @param email User email address\n * @returns JWT token and expiry time, or null if failed\n *\n * @example\n * ```typescript\n * const tokenData = await LabelStudioSSOService.getSSOToken('user@example.com')\n * if (tokenData) {\n * console.log('Token:', tokenData.token)\n * console.log('Expires in:', tokenData.expires_in, 'seconds')\n * }\n * ```\n */\n static async getSSOToken(email: string): Promise<{ token: string; expires_in: number } | null> {\n const { serverUrl, apiToken } = this.getConfig()\n\n if (!apiToken) {\n console.error('[LSS SSO] Label Studio API token not configured')\n return null\n }\n\n if (!email) {\n console.error('[LSS SSO] Email is required')\n return null\n }\n\n try {\n console.log(`[LSS SSO] Requesting JWT token for: ${email}`)\n\n const response = await axios.post(\n `${serverUrl}/api/sso/token`,\n { email },\n {\n headers: {\n 'Authorization': `Token ${apiToken}`,\n 'Content-Type': 'application/json'\n },\n timeout: 5000\n }\n )\n\n const { token, expires_in } = response.data\n\n console.log(`[LSS SSO] JWT token acquired for ${email} (expires in ${expires_in}s)`)\n\n return { token, expires_in }\n } catch (error: any) {\n if (error.response) {\n console.error(`[LSS SSO] Label Studio API error: ${error.response.status}`, error.response.data)\n } else if (error.request) {\n console.error('[LSS SSO] No response from Label Studio:', error.message)\n } else {\n console.error('[LSS SSO] Request error:', error.message)\n }\n\n return null\n }\n }\n\n /**\n * Verify SSO configuration is properly set up\n *\n * @returns True if configuration is valid\n */\n static verifyConfig(): boolean {\n const { serverUrl, apiToken } = this.getConfig()\n\n if (!serverUrl) {\n console.error('[LSS SSO] Label Studio server URL not configured')\n return false\n }\n\n if (!apiToken) {\n console.error('[LSS SSO] Label Studio API token not configured')\n return false\n }\n\n return true\n }\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { MLBackend, AddMLBackendInput } from '../../types/label-studio-types.js';
2
+ export declare class MLBackendService {
3
+ /**
4
+ * Get ML backends for a project
5
+ */
6
+ labelStudioMLBackends(projectId: number, context: ResolverContext): Promise<MLBackend[]>;
7
+ /**
8
+ * Add ML backend to project
9
+ */
10
+ addMLBackendToProject(projectId: number, input: AddMLBackendInput, context: ResolverContext): Promise<MLBackend>;
11
+ /**
12
+ * Delete ML backend
13
+ */
14
+ deleteMLBackend(mlBackendId: number, context: ResolverContext): Promise<boolean>;
15
+ /**
16
+ * Trigger predictions for tasks
17
+ */
18
+ triggerLabelStudioPredictions(projectId: number, context: ResolverContext, taskIds?: number[]): Promise<boolean>;
19
+ /**
20
+ * Train ML model
21
+ */
22
+ trainLabelStudioModel(mlBackendId: number, context: ResolverContext): Promise<boolean>;
23
+ }
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MLBackendService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ const label_studio_api_client_js_1 = require("../../utils/label-studio-api-client.js");
7
+ const label_studio_types_js_1 = require("../../types/label-studio-types.js");
8
+ let MLBackendService = class MLBackendService {
9
+ /**
10
+ * Get ML backends for a project
11
+ */
12
+ async labelStudioMLBackends(projectId, context) {
13
+ try {
14
+ const backends = await label_studio_api_client_js_1.labelStudioApi.getMLBackends(projectId);
15
+ return backends.map(backend => ({
16
+ id: backend.id,
17
+ url: backend.url,
18
+ title: backend.title,
19
+ isInteractive: backend.is_interactive || false,
20
+ modelVersion: backend.model_version || 'unknown'
21
+ }));
22
+ }
23
+ catch (error) {
24
+ console.error(`Failed to fetch ML backends for project ${projectId}:`, error);
25
+ throw new Error(`Failed to fetch ML backends: ${error.message}`);
26
+ }
27
+ }
28
+ /**
29
+ * Add ML backend to project
30
+ */
31
+ async addMLBackendToProject(projectId, input, context) {
32
+ try {
33
+ const backend = await label_studio_api_client_js_1.labelStudioApi.addMLBackend({
34
+ project: projectId,
35
+ url: input.url,
36
+ title: input.title,
37
+ is_interactive: input.isInteractive || false
38
+ });
39
+ return {
40
+ id: backend.id,
41
+ url: backend.url,
42
+ title: backend.title,
43
+ isInteractive: backend.is_interactive || false,
44
+ modelVersion: backend.model_version || 'unknown'
45
+ };
46
+ }
47
+ catch (error) {
48
+ console.error(`Failed to add ML backend to project ${projectId}:`, error);
49
+ throw new Error(`Failed to add ML backend: ${error.message}`);
50
+ }
51
+ }
52
+ /**
53
+ * Delete ML backend
54
+ */
55
+ async deleteMLBackend(mlBackendId, context) {
56
+ try {
57
+ await label_studio_api_client_js_1.labelStudioApi.deleteMLBackend(mlBackendId);
58
+ return true;
59
+ }
60
+ catch (error) {
61
+ console.error(`Failed to delete ML backend ${mlBackendId}:`, error);
62
+ throw new Error(`Failed to delete ML backend: ${error.message}`);
63
+ }
64
+ }
65
+ /**
66
+ * Trigger predictions for tasks
67
+ */
68
+ async triggerLabelStudioPredictions(projectId, context, taskIds) {
69
+ try {
70
+ await label_studio_api_client_js_1.labelStudioApi.triggerPredictions(projectId, taskIds);
71
+ return true;
72
+ }
73
+ catch (error) {
74
+ console.error(`Failed to trigger predictions for project ${projectId}:`, error);
75
+ throw new Error(`Failed to trigger predictions: ${error.message}`);
76
+ }
77
+ }
78
+ /**
79
+ * Train ML model
80
+ */
81
+ async trainLabelStudioModel(mlBackendId, context) {
82
+ try {
83
+ await label_studio_api_client_js_1.labelStudioApi.trainModel(mlBackendId);
84
+ return true;
85
+ }
86
+ catch (error) {
87
+ console.error(`Failed to train model ${mlBackendId}:`, error);
88
+ throw new Error(`Failed to train model: ${error.message}`);
89
+ }
90
+ }
91
+ };
92
+ exports.MLBackendService = MLBackendService;
93
+ tslib_1.__decorate([
94
+ (0, type_graphql_1.Query)(returns => [label_studio_types_js_1.MLBackend], {
95
+ description: 'Get all ML backends connected to a Label Studio project'
96
+ }),
97
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "query")'),
98
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
99
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
100
+ tslib_1.__metadata("design:type", Function),
101
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
102
+ tslib_1.__metadata("design:returntype", Promise)
103
+ ], MLBackendService.prototype, "labelStudioMLBackends", null);
104
+ tslib_1.__decorate([
105
+ (0, type_graphql_1.Mutation)(returns => label_studio_types_js_1.MLBackend, {
106
+ description: 'Add ML backend to Label Studio project for predictions and training'
107
+ }),
108
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
109
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
110
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('input')),
111
+ tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
112
+ tslib_1.__metadata("design:type", Function),
113
+ tslib_1.__metadata("design:paramtypes", [Number, label_studio_types_js_1.AddMLBackendInput, Object]),
114
+ tslib_1.__metadata("design:returntype", Promise)
115
+ ], MLBackendService.prototype, "addMLBackendToProject", null);
116
+ tslib_1.__decorate([
117
+ (0, type_graphql_1.Mutation)(returns => Boolean, {
118
+ description: 'Remove ML backend from project'
119
+ }),
120
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
121
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('mlBackendId', type => type_graphql_1.Int)),
122
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
123
+ tslib_1.__metadata("design:type", Function),
124
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
125
+ tslib_1.__metadata("design:returntype", Promise)
126
+ ], MLBackendService.prototype, "deleteMLBackend", null);
127
+ tslib_1.__decorate([
128
+ (0, type_graphql_1.Mutation)(returns => Boolean, {
129
+ description: 'Trigger ML predictions for tasks in a project'
130
+ }),
131
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
132
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
133
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
134
+ tslib_1.__param(2, (0, type_graphql_1.Arg)('taskIds', type => [type_graphql_1.Int], { nullable: true })),
135
+ tslib_1.__metadata("design:type", Function),
136
+ tslib_1.__metadata("design:paramtypes", [Number, Object, Array]),
137
+ tslib_1.__metadata("design:returntype", Promise)
138
+ ], MLBackendService.prototype, "triggerLabelStudioPredictions", null);
139
+ tslib_1.__decorate([
140
+ (0, type_graphql_1.Mutation)(returns => Boolean, {
141
+ description: 'Trigger ML model training with current annotations'
142
+ }),
143
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
144
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('mlBackendId', type => type_graphql_1.Int)),
145
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
146
+ tslib_1.__metadata("design:type", Function),
147
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
148
+ tslib_1.__metadata("design:returntype", Promise)
149
+ ], MLBackendService.prototype, "trainLabelStudioModel", null);
150
+ exports.MLBackendService = MLBackendService = tslib_1.__decorate([
151
+ (0, type_graphql_1.Resolver)()
152
+ ], MLBackendService);
153
+ //# sourceMappingURL=ml-backend-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ml-backend-service.js","sourceRoot":"","sources":["../../../server/service/ml/ml-backend-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Mutation, Query, Arg, Ctx, Int, Directive } from 'type-graphql'\nimport { labelStudioApi } from '../../utils/label-studio-api-client.js'\nimport { MLBackend, AddMLBackendInput } from '../../types/label-studio-types.js'\n\n@Resolver()\nexport class MLBackendService {\n /**\n * Get ML backends for a project\n */\n @Query(returns => [MLBackend], {\n description: 'Get all ML backends connected to a Label Studio project'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"query\")')\n async labelStudioMLBackends(\n @Arg('projectId', type => Int) projectId: number,\n @Ctx() context: ResolverContext\n ): Promise<MLBackend[]> {\n try {\n const backends = await labelStudioApi.getMLBackends(projectId)\n\n return backends.map(backend => ({\n id: backend.id,\n url: backend.url,\n title: backend.title,\n isInteractive: backend.is_interactive || false,\n modelVersion: backend.model_version || 'unknown'\n }))\n } catch (error) {\n console.error(`Failed to fetch ML backends for project ${projectId}:`, error)\n throw new Error(`Failed to fetch ML backends: ${error.message}`)\n }\n }\n\n /**\n * Add ML backend to project\n */\n @Mutation(returns => MLBackend, {\n description: 'Add ML backend to Label Studio project for predictions and training'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"mutation\")')\n async addMLBackendToProject(\n @Arg('projectId', type => Int) projectId: number,\n @Arg('input') input: AddMLBackendInput,\n @Ctx() context: ResolverContext\n ): Promise<MLBackend> {\n try {\n const backend = await labelStudioApi.addMLBackend({\n project: projectId,\n url: input.url,\n title: input.title,\n is_interactive: input.isInteractive || false\n })\n\n return {\n id: backend.id,\n url: backend.url,\n title: backend.title,\n isInteractive: backend.is_interactive || false,\n modelVersion: backend.model_version || 'unknown'\n }\n } catch (error) {\n console.error(`Failed to add ML backend to project ${projectId}:`, error)\n throw new Error(`Failed to add ML backend: ${error.message}`)\n }\n }\n\n /**\n * Delete ML backend\n */\n @Mutation(returns => Boolean, {\n description: 'Remove ML backend from project'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"mutation\")')\n async deleteMLBackend(\n @Arg('mlBackendId', type => Int) mlBackendId: number,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n try {\n await labelStudioApi.deleteMLBackend(mlBackendId)\n return true\n } catch (error) {\n console.error(`Failed to delete ML backend ${mlBackendId}:`, error)\n throw new Error(`Failed to delete ML backend: ${error.message}`)\n }\n }\n\n /**\n * Trigger predictions for tasks\n */\n @Mutation(returns => Boolean, {\n description: 'Trigger ML predictions for tasks in a project'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"mutation\")')\n async triggerLabelStudioPredictions(\n @Arg('projectId', type => Int) projectId: number,\n @Ctx() context: ResolverContext,\n @Arg('taskIds', type => [Int], { nullable: true }) taskIds?: number[]\n ): Promise<boolean> {\n try {\n await labelStudioApi.triggerPredictions(projectId, taskIds)\n return true\n } catch (error) {\n console.error(`Failed to trigger predictions for project ${projectId}:`, error)\n throw new Error(`Failed to trigger predictions: ${error.message}`)\n }\n }\n\n /**\n * Train ML model\n */\n @Mutation(returns => Boolean, {\n description: 'Trigger ML model training with current annotations'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"mutation\")')\n async trainLabelStudioModel(\n @Arg('mlBackendId', type => Int) mlBackendId: number,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n try {\n await labelStudioApi.trainModel(mlBackendId)\n return true\n } catch (error) {\n console.error(`Failed to train model ${mlBackendId}:`, error)\n throw new Error(`Failed to train model: ${error.message}`)\n }\n }\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { LabelStudioPrediction, PredictionInput, PredictionImportResult, BulkPredictionInput } from '../../types/label-studio-types.js';
2
+ export declare class PredictionManagement {
3
+ /**
4
+ * Get predictions for a task
5
+ */
6
+ labelStudioTaskPredictions(taskId: number, context: ResolverContext): Promise<LabelStudioPrediction[]>;
7
+ /**
8
+ * Get predictions for a project
9
+ */
10
+ labelStudioProjectPredictions(projectId: number, context: ResolverContext): Promise<LabelStudioPrediction[]>;
11
+ /**
12
+ * Get single prediction by ID
13
+ */
14
+ labelStudioPrediction(predictionId: number, context: ResolverContext): Promise<LabelStudioPrediction | null>;
15
+ /**
16
+ * Create a prediction for a task
17
+ */
18
+ createLabelStudioPrediction(input: PredictionInput, context: ResolverContext): Promise<LabelStudioPrediction>;
19
+ /**
20
+ * Create predictions in bulk
21
+ */
22
+ createBulkPredictions(predictions: BulkPredictionInput[], context: ResolverContext): Promise<PredictionImportResult>;
23
+ /**
24
+ * Import predictions for a project
25
+ * This is the recommended way to bulk import AI model predictions
26
+ */
27
+ importPredictionsToProject(projectId: number, predictions: BulkPredictionInput[], context: ResolverContext): Promise<PredictionImportResult>;
28
+ /**
29
+ * Delete prediction
30
+ */
31
+ deleteLabelStudioPrediction(predictionId: number, context: ResolverContext): Promise<boolean>;
32
+ }
@@ -0,0 +1,299 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PredictionManagement = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ const label_studio_api_client_js_1 = require("../../utils/label-studio-api-client.js");
7
+ const label_studio_types_js_1 = require("../../types/label-studio-types.js");
8
+ let PredictionManagement = class PredictionManagement {
9
+ /**
10
+ * Get predictions for a task
11
+ */
12
+ async labelStudioTaskPredictions(taskId, context) {
13
+ try {
14
+ const predictions = await label_studio_api_client_js_1.labelStudioApi.getPredictions(taskId);
15
+ return predictions.map((prediction) => ({
16
+ id: prediction.id,
17
+ taskId: prediction.task || taskId,
18
+ result: JSON.stringify(prediction.result),
19
+ score: prediction.score || undefined,
20
+ modelVersion: prediction.model_version || undefined,
21
+ createdAt: prediction.created_at ? new Date(prediction.created_at) : undefined
22
+ }));
23
+ }
24
+ catch (error) {
25
+ console.error(`Failed to fetch predictions for task ${taskId}:`, error);
26
+ throw new Error(`Failed to fetch predictions: ${error.message}`);
27
+ }
28
+ }
29
+ /**
30
+ * Get predictions for a project
31
+ */
32
+ async labelStudioProjectPredictions(projectId, context) {
33
+ try {
34
+ const predictions = await label_studio_api_client_js_1.labelStudioApi.getProjectPredictions(projectId);
35
+ return predictions.map((prediction) => ({
36
+ id: prediction.id,
37
+ taskId: prediction.task,
38
+ result: JSON.stringify(prediction.result),
39
+ score: prediction.score || undefined,
40
+ modelVersion: prediction.model_version || undefined,
41
+ createdAt: prediction.created_at ? new Date(prediction.created_at) : undefined
42
+ }));
43
+ }
44
+ catch (error) {
45
+ console.error(`Failed to fetch predictions for project ${projectId}:`, error);
46
+ throw new Error(`Failed to fetch predictions: ${error.message}`);
47
+ }
48
+ }
49
+ /**
50
+ * Get single prediction by ID
51
+ */
52
+ async labelStudioPrediction(predictionId, context) {
53
+ try {
54
+ const prediction = await label_studio_api_client_js_1.labelStudioApi.getPrediction(predictionId);
55
+ if (!prediction) {
56
+ return null;
57
+ }
58
+ return {
59
+ id: prediction.id,
60
+ taskId: prediction.task,
61
+ result: JSON.stringify(prediction.result),
62
+ score: prediction.score || undefined,
63
+ modelVersion: prediction.model_version || undefined,
64
+ createdAt: prediction.created_at ? new Date(prediction.created_at) : undefined
65
+ };
66
+ }
67
+ catch (error) {
68
+ console.error(`Failed to fetch prediction ${predictionId}:`, error);
69
+ return null;
70
+ }
71
+ }
72
+ /**
73
+ * Create a prediction for a task
74
+ */
75
+ async createLabelStudioPrediction(input, context) {
76
+ try {
77
+ // Parse result JSON
78
+ const result = JSON.parse(input.result);
79
+ // Create prediction
80
+ const prediction = await label_studio_api_client_js_1.labelStudioApi.createPrediction({
81
+ task: input.taskId,
82
+ result,
83
+ score: input.score,
84
+ model_version: input.modelVersion
85
+ });
86
+ return {
87
+ id: prediction.id,
88
+ taskId: prediction.task,
89
+ result: JSON.stringify(prediction.result),
90
+ score: prediction.score || undefined,
91
+ modelVersion: prediction.model_version || undefined,
92
+ createdAt: prediction.created_at ? new Date(prediction.created_at) : undefined
93
+ };
94
+ }
95
+ catch (error) {
96
+ console.error(`Failed to create prediction for task ${input.taskId}:`, error);
97
+ throw new Error(`Failed to create prediction: ${error.message}`);
98
+ }
99
+ }
100
+ /**
101
+ * Create predictions in bulk
102
+ */
103
+ async createBulkPredictions(predictions, context) {
104
+ const errors = [];
105
+ let created = 0;
106
+ let failed = 0;
107
+ try {
108
+ // Parse and validate predictions
109
+ const parsedPredictions = predictions.map((pred, index) => {
110
+ try {
111
+ return {
112
+ task: pred.taskId,
113
+ result: JSON.parse(pred.result),
114
+ score: pred.score,
115
+ model_version: pred.modelVersion
116
+ };
117
+ }
118
+ catch (e) {
119
+ failed++;
120
+ errors.push(`Invalid JSON in prediction ${index}: ${pred.result}`);
121
+ return null;
122
+ }
123
+ });
124
+ const validPredictions = parsedPredictions.filter(p => p !== null);
125
+ if (validPredictions.length === 0) {
126
+ return {
127
+ created: 0,
128
+ failed: predictions.length,
129
+ errors
130
+ };
131
+ }
132
+ // Create predictions
133
+ const response = await label_studio_api_client_js_1.labelStudioApi.createPredictions(validPredictions);
134
+ created = response.created || validPredictions.length;
135
+ return {
136
+ created,
137
+ failed,
138
+ errors: errors.length > 0 ? errors : undefined
139
+ };
140
+ }
141
+ catch (error) {
142
+ console.error('Failed to create bulk predictions:', error);
143
+ throw new Error(`Failed to create predictions: ${error.message}`);
144
+ }
145
+ }
146
+ /**
147
+ * Import predictions for a project
148
+ * This is the recommended way to bulk import AI model predictions
149
+ */
150
+ async importPredictionsToProject(projectId, predictions, context) {
151
+ const errors = [];
152
+ let created = 0;
153
+ let failed = 0;
154
+ try {
155
+ // Parse and validate predictions
156
+ const parsedPredictions = predictions.map((pred, index) => {
157
+ try {
158
+ return {
159
+ task: pred.taskId,
160
+ result: JSON.parse(pred.result),
161
+ score: pred.score,
162
+ model_version: pred.modelVersion
163
+ };
164
+ }
165
+ catch (e) {
166
+ failed++;
167
+ errors.push(`Invalid JSON in prediction ${index}: ${pred.result}`);
168
+ return null;
169
+ }
170
+ });
171
+ const validPredictions = parsedPredictions.filter(p => p !== null);
172
+ if (validPredictions.length === 0) {
173
+ return {
174
+ created: 0,
175
+ failed: predictions.length,
176
+ errors
177
+ };
178
+ }
179
+ // Import predictions using project endpoint
180
+ const response = await label_studio_api_client_js_1.labelStudioApi.importPredictions(projectId, validPredictions);
181
+ // Parse response
182
+ if (response.created !== undefined) {
183
+ created = response.created;
184
+ }
185
+ else if (response.task_count !== undefined) {
186
+ created = response.task_count;
187
+ }
188
+ else if (Array.isArray(response)) {
189
+ created = response.length;
190
+ }
191
+ return {
192
+ created,
193
+ failed,
194
+ errors: errors.length > 0 ? errors : undefined
195
+ };
196
+ }
197
+ catch (error) {
198
+ console.error(`Failed to import predictions to project ${projectId}:`, error);
199
+ throw new Error(`Failed to import predictions: ${error.message}`);
200
+ }
201
+ }
202
+ /**
203
+ * Delete prediction
204
+ */
205
+ async deleteLabelStudioPrediction(predictionId, context) {
206
+ try {
207
+ await label_studio_api_client_js_1.labelStudioApi.deletePrediction(predictionId);
208
+ return true;
209
+ }
210
+ catch (error) {
211
+ console.error(`Failed to delete prediction ${predictionId}:`, error);
212
+ throw new Error(`Failed to delete prediction: ${error.message}`);
213
+ }
214
+ }
215
+ };
216
+ exports.PredictionManagement = PredictionManagement;
217
+ tslib_1.__decorate([
218
+ (0, type_graphql_1.Query)(returns => [label_studio_types_js_1.LabelStudioPrediction], {
219
+ description: 'Get all predictions for a Label Studio task'
220
+ }),
221
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "query")'),
222
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('taskId', type => type_graphql_1.Int)),
223
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
224
+ tslib_1.__metadata("design:type", Function),
225
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
226
+ tslib_1.__metadata("design:returntype", Promise)
227
+ ], PredictionManagement.prototype, "labelStudioTaskPredictions", null);
228
+ tslib_1.__decorate([
229
+ (0, type_graphql_1.Query)(returns => [label_studio_types_js_1.LabelStudioPrediction], {
230
+ description: 'Get all predictions for a Label Studio project'
231
+ }),
232
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "query")'),
233
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
234
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
235
+ tslib_1.__metadata("design:type", Function),
236
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
237
+ tslib_1.__metadata("design:returntype", Promise)
238
+ ], PredictionManagement.prototype, "labelStudioProjectPredictions", null);
239
+ tslib_1.__decorate([
240
+ (0, type_graphql_1.Query)(returns => label_studio_types_js_1.LabelStudioPrediction, {
241
+ description: 'Get a single prediction by ID',
242
+ nullable: true
243
+ }),
244
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "query")'),
245
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('predictionId', type => type_graphql_1.Int)),
246
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
247
+ tslib_1.__metadata("design:type", Function),
248
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
249
+ tslib_1.__metadata("design:returntype", Promise)
250
+ ], PredictionManagement.prototype, "labelStudioPrediction", null);
251
+ tslib_1.__decorate([
252
+ (0, type_graphql_1.Mutation)(returns => label_studio_types_js_1.LabelStudioPrediction, {
253
+ description: 'Create a prediction for a Label Studio task'
254
+ }),
255
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
256
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('input')),
257
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
258
+ tslib_1.__metadata("design:type", Function),
259
+ tslib_1.__metadata("design:paramtypes", [label_studio_types_js_1.PredictionInput, Object]),
260
+ tslib_1.__metadata("design:returntype", Promise)
261
+ ], PredictionManagement.prototype, "createLabelStudioPrediction", null);
262
+ tslib_1.__decorate([
263
+ (0, type_graphql_1.Mutation)(returns => label_studio_types_js_1.PredictionImportResult, {
264
+ description: 'Create multiple predictions at once'
265
+ }),
266
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
267
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('predictions', type => [label_studio_types_js_1.BulkPredictionInput])),
268
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
269
+ tslib_1.__metadata("design:type", Function),
270
+ tslib_1.__metadata("design:paramtypes", [Array, Object]),
271
+ tslib_1.__metadata("design:returntype", Promise)
272
+ ], PredictionManagement.prototype, "createBulkPredictions", null);
273
+ tslib_1.__decorate([
274
+ (0, type_graphql_1.Mutation)(returns => label_studio_types_js_1.PredictionImportResult, {
275
+ description: 'Import predictions for a Label Studio project in bulk'
276
+ }),
277
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
278
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
279
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('predictions', type => [label_studio_types_js_1.BulkPredictionInput])),
280
+ tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
281
+ tslib_1.__metadata("design:type", Function),
282
+ tslib_1.__metadata("design:paramtypes", [Number, Array, Object]),
283
+ tslib_1.__metadata("design:returntype", Promise)
284
+ ], PredictionManagement.prototype, "importPredictionsToProject", null);
285
+ tslib_1.__decorate([
286
+ (0, type_graphql_1.Mutation)(returns => Boolean, {
287
+ description: 'Delete a prediction from Label Studio'
288
+ }),
289
+ (0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
290
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('predictionId', type => type_graphql_1.Int)),
291
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
292
+ tslib_1.__metadata("design:type", Function),
293
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
294
+ tslib_1.__metadata("design:returntype", Promise)
295
+ ], PredictionManagement.prototype, "deleteLabelStudioPrediction", null);
296
+ exports.PredictionManagement = PredictionManagement = tslib_1.__decorate([
297
+ (0, type_graphql_1.Resolver)()
298
+ ], PredictionManagement);
299
+ //# sourceMappingURL=prediction-management.js.map