@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,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BatchPredictionResult = exports.PredictionGenerationResult = exports.BatchGeneratePredictionRequest = exports.GeneratePredictionRequest = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ // ============================================================================
7
+ // Label Studio Prediction Generation Types
8
+ // ============================================================================
9
+ /**
10
+ * Label Studio prediction generation request
11
+ */
12
+ let GeneratePredictionRequest = class GeneratePredictionRequest {
13
+ };
14
+ exports.GeneratePredictionRequest = GeneratePredictionRequest;
15
+ tslib_1.__decorate([
16
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Label Studio task ID' }),
17
+ tslib_1.__metadata("design:type", Number)
18
+ ], GeneratePredictionRequest.prototype, "taskId", void 0);
19
+ tslib_1.__decorate([
20
+ (0, type_graphql_1.Field)({ description: 'Image URL from task data' }),
21
+ tslib_1.__metadata("design:type", String)
22
+ ], GeneratePredictionRequest.prototype, "imageUrl", void 0);
23
+ tslib_1.__decorate([
24
+ (0, type_graphql_1.Field)({ nullable: true, description: 'AI model ID to use' }),
25
+ tslib_1.__metadata("design:type", String)
26
+ ], GeneratePredictionRequest.prototype, "modelId", void 0);
27
+ tslib_1.__decorate([
28
+ (0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'Confidence threshold (0-1)' }),
29
+ tslib_1.__metadata("design:type", Number)
30
+ ], GeneratePredictionRequest.prototype, "confidenceThreshold", void 0);
31
+ exports.GeneratePredictionRequest = GeneratePredictionRequest = tslib_1.__decorate([
32
+ (0, type_graphql_1.InputType)({ description: 'Request to generate Label Studio predictions' })
33
+ ], GeneratePredictionRequest);
34
+ /**
35
+ * Batch prediction generation request
36
+ */
37
+ let BatchGeneratePredictionRequest = class BatchGeneratePredictionRequest {
38
+ };
39
+ exports.BatchGeneratePredictionRequest = BatchGeneratePredictionRequest;
40
+ tslib_1.__decorate([
41
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Label Studio project ID' }),
42
+ tslib_1.__metadata("design:type", Number)
43
+ ], BatchGeneratePredictionRequest.prototype, "projectId", void 0);
44
+ tslib_1.__decorate([
45
+ (0, type_graphql_1.Field)(type => [type_graphql_1.Int], { description: 'Array of task IDs' }),
46
+ tslib_1.__metadata("design:type", Array)
47
+ ], BatchGeneratePredictionRequest.prototype, "taskIds", void 0);
48
+ tslib_1.__decorate([
49
+ (0, type_graphql_1.Field)({ nullable: true, description: 'AI model ID to use' }),
50
+ tslib_1.__metadata("design:type", String)
51
+ ], BatchGeneratePredictionRequest.prototype, "modelId", void 0);
52
+ tslib_1.__decorate([
53
+ (0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'Confidence threshold (0-1)' }),
54
+ tslib_1.__metadata("design:type", Number)
55
+ ], BatchGeneratePredictionRequest.prototype, "confidenceThreshold", void 0);
56
+ exports.BatchGeneratePredictionRequest = BatchGeneratePredictionRequest = tslib_1.__decorate([
57
+ (0, type_graphql_1.InputType)({ description: 'Request to generate predictions for multiple tasks' })
58
+ ], BatchGeneratePredictionRequest);
59
+ /**
60
+ * Prediction generation result
61
+ */
62
+ let PredictionGenerationResult = class PredictionGenerationResult {
63
+ };
64
+ exports.PredictionGenerationResult = PredictionGenerationResult;
65
+ tslib_1.__decorate([
66
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Task ID' }),
67
+ tslib_1.__metadata("design:type", Number)
68
+ ], PredictionGenerationResult.prototype, "taskId", void 0);
69
+ tslib_1.__decorate([
70
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { nullable: true, description: 'Created prediction ID' }),
71
+ tslib_1.__metadata("design:type", Number)
72
+ ], PredictionGenerationResult.prototype, "predictionId", void 0);
73
+ tslib_1.__decorate([
74
+ (0, type_graphql_1.Field)({ description: 'Success status' }),
75
+ tslib_1.__metadata("design:type", Boolean)
76
+ ], PredictionGenerationResult.prototype, "success", void 0);
77
+ tslib_1.__decorate([
78
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Error message if failed' }),
79
+ tslib_1.__metadata("design:type", String)
80
+ ], PredictionGenerationResult.prototype, "error", void 0);
81
+ tslib_1.__decorate([
82
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Number of detected objects' }),
83
+ tslib_1.__metadata("design:type", Number)
84
+ ], PredictionGenerationResult.prototype, "objectCount", void 0);
85
+ tslib_1.__decorate([
86
+ (0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'Average confidence score' }),
87
+ tslib_1.__metadata("design:type", Number)
88
+ ], PredictionGenerationResult.prototype, "avgConfidence", void 0);
89
+ exports.PredictionGenerationResult = PredictionGenerationResult = tslib_1.__decorate([
90
+ (0, type_graphql_1.ObjectType)({ description: 'Prediction generation result' })
91
+ ], PredictionGenerationResult);
92
+ /**
93
+ * Batch prediction generation result
94
+ */
95
+ let BatchPredictionResult = class BatchPredictionResult {
96
+ };
97
+ exports.BatchPredictionResult = BatchPredictionResult;
98
+ tslib_1.__decorate([
99
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Total tasks processed' }),
100
+ tslib_1.__metadata("design:type", Number)
101
+ ], BatchPredictionResult.prototype, "total", void 0);
102
+ tslib_1.__decorate([
103
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Number of successful predictions' }),
104
+ tslib_1.__metadata("design:type", Number)
105
+ ], BatchPredictionResult.prototype, "succeeded", void 0);
106
+ tslib_1.__decorate([
107
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Number of failed predictions' }),
108
+ tslib_1.__metadata("design:type", Number)
109
+ ], BatchPredictionResult.prototype, "failed", void 0);
110
+ tslib_1.__decorate([
111
+ (0, type_graphql_1.Field)(type => [PredictionGenerationResult], { description: 'Individual results' }),
112
+ tslib_1.__metadata("design:type", Array)
113
+ ], BatchPredictionResult.prototype, "results", void 0);
114
+ tslib_1.__decorate([
115
+ (0, type_graphql_1.Field)({ description: 'Model version used' }),
116
+ tslib_1.__metadata("design:type", String)
117
+ ], BatchPredictionResult.prototype, "modelVersion", void 0);
118
+ exports.BatchPredictionResult = BatchPredictionResult = tslib_1.__decorate([
119
+ (0, type_graphql_1.ObjectType)({ description: 'Batch prediction generation result' })
120
+ ], BatchPredictionResult);
121
+ //# sourceMappingURL=prediction-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prediction-types.js","sourceRoot":"","sources":["../../server/types/prediction-types.ts"],"names":[],"mappings":";;;;AAAA,+CAAuE;AAEvE,+EAA+E;AAC/E,2CAA2C;AAC3C,+EAA+E;AAE/E;;GAEG;AAEI,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;CAYrC,CAAA;AAZY,8DAAyB;AAEpC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC;;yDAC9C;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC;;2DACnC;AAGhB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC;;0DAC7C;AAGhB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;sEACxD;oCAXjB,yBAAyB;IADrC,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;GAC9D,yBAAyB,CAYrC;AAED;;GAEG;AAEI,IAAM,8BAA8B,GAApC,MAAM,8BAA8B;CAY1C,CAAA;AAZY,wEAA8B;AAEzC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;;iEAC9C;AAGjB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,kBAAG,CAAC,EAAE,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC;;+DAC1C;AAGjB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC;;+DAC7C;AAGhB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;2EACxD;yCAXjB,8BAA8B;IAD1C,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;GACpE,8BAA8B,CAY1C;AAED;;GAEG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;CAkBtC,CAAA;AAlBY,gEAA0B;AAErC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;;0DACjC;AAGd;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;;gEACxD;AAGrB;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC;;2DACzB;AAGhB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;;yDACpD;AAGd;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;+DAC/C;AAGnB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC;;iEAC5D;qCAjBX,0BAA0B;IADtC,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;GAC/C,0BAA0B,CAkBtC;AAED;;GAEG;AAEI,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;CAejC,CAAA;AAfY,sDAAqB;AAEhC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;;oDAChD;AAGb;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;;wDACvD;AAGjB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;;qDACtD;AAGd;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,0BAA0B,CAAC,EAAE,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC;;sDAC9C;AAGrC;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC;;2DACzB;gCAdT,qBAAqB;IADjC,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;GACrD,qBAAqB,CAejC","sourcesContent":["import { Field, ObjectType, InputType, Int, Float } from 'type-graphql'\n\n// ============================================================================\n// Label Studio Prediction Generation Types\n// ============================================================================\n\n/**\n * Label Studio prediction generation request\n */\n@InputType({ description: 'Request to generate Label Studio predictions' })\nexport class GeneratePredictionRequest {\n @Field(type => Int, { description: 'Label Studio task ID' })\n taskId: number\n\n @Field({ description: 'Image URL from task data' })\n imageUrl: string\n\n @Field({ nullable: true, description: 'AI model ID to use' })\n modelId?: string\n\n @Field(type => Float, { nullable: true, description: 'Confidence threshold (0-1)' })\n confidenceThreshold?: number\n}\n\n/**\n * Batch prediction generation request\n */\n@InputType({ description: 'Request to generate predictions for multiple tasks' })\nexport class BatchGeneratePredictionRequest {\n @Field(type => Int, { description: 'Label Studio project ID' })\n projectId: number\n\n @Field(type => [Int], { description: 'Array of task IDs' })\n taskIds: number[]\n\n @Field({ nullable: true, description: 'AI model ID to use' })\n modelId?: string\n\n @Field(type => Float, { nullable: true, description: 'Confidence threshold (0-1)' })\n confidenceThreshold?: number\n}\n\n/**\n * Prediction generation result\n */\n@ObjectType({ description: 'Prediction generation result' })\nexport class PredictionGenerationResult {\n @Field(type => Int, { description: 'Task ID' })\n taskId: number\n\n @Field(type => Int, { nullable: true, description: 'Created prediction ID' })\n predictionId?: number\n\n @Field({ description: 'Success status' })\n success: boolean\n\n @Field({ nullable: true, description: 'Error message if failed' })\n error?: string\n\n @Field(type => Int, { description: 'Number of detected objects' })\n objectCount: number\n\n @Field(type => Float, { nullable: true, description: 'Average confidence score' })\n avgConfidence?: number\n}\n\n/**\n * Batch prediction generation result\n */\n@ObjectType({ description: 'Batch prediction generation result' })\nexport class BatchPredictionResult {\n @Field(type => Int, { description: 'Total tasks processed' })\n total: number\n\n @Field(type => Int, { description: 'Number of successful predictions' })\n succeeded: number\n\n @Field(type => Int, { description: 'Number of failed predictions' })\n failed: number\n\n @Field(type => [PredictionGenerationResult], { description: 'Individual results' })\n results: PredictionGenerationResult[]\n\n @Field({ description: 'Model version used' })\n modelVersion: string\n}\n"]}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Annotation Exporter
3
+ *
4
+ * Flexible annotation export system with pluggable format converters.
5
+ * Supports custom export formats for different use cases.
6
+ */
7
+ export interface LabelStudioAnnotation {
8
+ id: number;
9
+ task: number;
10
+ project: number;
11
+ completed_by: {
12
+ id: number;
13
+ email: string;
14
+ first_name: string;
15
+ last_name: string;
16
+ };
17
+ result: Array<{
18
+ from_name: string;
19
+ to_name: string;
20
+ type: string;
21
+ value: any;
22
+ }>;
23
+ created_at: string;
24
+ updated_at: string;
25
+ lead_time?: number;
26
+ }
27
+ export interface ExportContext {
28
+ projectId: number;
29
+ projectTitle?: string;
30
+ exportedAt: string;
31
+ metadata?: any;
32
+ }
33
+ /**
34
+ * Export format converter function type
35
+ * Converts Label Studio annotations to custom format
36
+ */
37
+ export type FormatConverter<T = any> = (annotations: LabelStudioAnnotation[], context: ExportContext) => T | Promise<T>;
38
+ /**
39
+ * Register a custom export format converter
40
+ *
41
+ * @param formatName - Unique format identifier (e.g., "csv", "coco", "yolo")
42
+ * @param converter - Converter function
43
+ *
44
+ * @example
45
+ * registerExportFormat('csv', (annotations, context) => {
46
+ * const rows = annotations.map(a => ({
47
+ * id: a.id,
48
+ * task: a.task,
49
+ * result: JSON.stringify(a.result)
50
+ * }))
51
+ * return Papa.unparse(rows)
52
+ * })
53
+ */
54
+ export declare function registerExportFormat<T = any>(formatName: string, converter: FormatConverter<T>): void;
55
+ /**
56
+ * Unregister an export format
57
+ */
58
+ export declare function unregisterExportFormat(formatName: string): void;
59
+ /**
60
+ * Get all registered format names
61
+ */
62
+ export declare function getRegisteredFormats(): string[];
63
+ /**
64
+ * Export annotations to specified format
65
+ *
66
+ * @param annotations - Label Studio annotations
67
+ * @param format - Export format name
68
+ * @param context - Export context
69
+ * @returns Converted data in requested format
70
+ */
71
+ export declare function exportAnnotations<T = any>(annotations: LabelStudioAnnotation[], format: string, context: ExportContext): Promise<T>;
72
+ /**
73
+ * Pre-built export formats
74
+ */
75
+ export declare class ExportFormats {
76
+ /**
77
+ * Export as JSON (default Label Studio format)
78
+ */
79
+ static json(): FormatConverter<string>;
80
+ /**
81
+ * Export as JSON Lines (one annotation per line)
82
+ */
83
+ static jsonl(): FormatConverter<string>;
84
+ /**
85
+ * Export image classification results as CSV
86
+ */
87
+ static imageClassificationCSV(): FormatConverter<string>;
88
+ /**
89
+ * Export Rank N classification results
90
+ */
91
+ static rankNClassificationCSV(ranks?: number): FormatConverter<string>;
92
+ /**
93
+ * Export object detection results as COCO format
94
+ */
95
+ static coco(): FormatConverter<any>;
96
+ /**
97
+ * Export object detection results as YOLO format
98
+ */
99
+ static yolo(): FormatConverter<Map<number, string>>;
100
+ /**
101
+ * Export NER (Named Entity Recognition) results
102
+ */
103
+ static nerJSON(): FormatConverter<any[]>;
104
+ }
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ /**
3
+ * Annotation Exporter
4
+ *
5
+ * Flexible annotation export system with pluggable format converters.
6
+ * Supports custom export formats for different use cases.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ExportFormats = void 0;
10
+ exports.registerExportFormat = registerExportFormat;
11
+ exports.unregisterExportFormat = unregisterExportFormat;
12
+ exports.getRegisteredFormats = getRegisteredFormats;
13
+ exports.exportAnnotations = exportAnnotations;
14
+ /**
15
+ * Registry for custom export formats
16
+ */
17
+ const formatConverters = new Map();
18
+ /**
19
+ * Register a custom export format converter
20
+ *
21
+ * @param formatName - Unique format identifier (e.g., "csv", "coco", "yolo")
22
+ * @param converter - Converter function
23
+ *
24
+ * @example
25
+ * registerExportFormat('csv', (annotations, context) => {
26
+ * const rows = annotations.map(a => ({
27
+ * id: a.id,
28
+ * task: a.task,
29
+ * result: JSON.stringify(a.result)
30
+ * }))
31
+ * return Papa.unparse(rows)
32
+ * })
33
+ */
34
+ function registerExportFormat(formatName, converter) {
35
+ formatConverters.set(formatName.toLowerCase(), converter);
36
+ }
37
+ /**
38
+ * Unregister an export format
39
+ */
40
+ function unregisterExportFormat(formatName) {
41
+ formatConverters.delete(formatName.toLowerCase());
42
+ }
43
+ /**
44
+ * Get all registered format names
45
+ */
46
+ function getRegisteredFormats() {
47
+ return Array.from(formatConverters.keys());
48
+ }
49
+ /**
50
+ * Export annotations to specified format
51
+ *
52
+ * @param annotations - Label Studio annotations
53
+ * @param format - Export format name
54
+ * @param context - Export context
55
+ * @returns Converted data in requested format
56
+ */
57
+ async function exportAnnotations(annotations, format, context) {
58
+ const converter = formatConverters.get(format.toLowerCase());
59
+ if (!converter) {
60
+ throw new Error(`Unknown export format: ${format}. Available formats: ${getRegisteredFormats().join(', ')}`);
61
+ }
62
+ return await converter(annotations, context);
63
+ }
64
+ /**
65
+ * Pre-built export formats
66
+ */
67
+ class ExportFormats {
68
+ /**
69
+ * Export as JSON (default Label Studio format)
70
+ */
71
+ static json() {
72
+ return (annotations, context) => {
73
+ return JSON.stringify({
74
+ meta: context,
75
+ annotations
76
+ }, null, 2);
77
+ };
78
+ }
79
+ /**
80
+ * Export as JSON Lines (one annotation per line)
81
+ */
82
+ static jsonl() {
83
+ return annotations => {
84
+ return annotations.map(a => JSON.stringify(a)).join('\n');
85
+ };
86
+ }
87
+ /**
88
+ * Export image classification results as CSV
89
+ */
90
+ static imageClassificationCSV() {
91
+ return annotations => {
92
+ const rows = ['task_id,annotation_id,label,annotator,lead_time,created_at'];
93
+ for (const annotation of annotations) {
94
+ const label = annotation.result.find(r => r.type === 'choices');
95
+ if (label && label.value.choices) {
96
+ const choice = label.value.choices[0];
97
+ rows.push([
98
+ annotation.task,
99
+ annotation.id,
100
+ choice,
101
+ annotation.completed_by?.email || 'unknown',
102
+ annotation.lead_time || 0,
103
+ annotation.created_at
104
+ ].join(','));
105
+ }
106
+ }
107
+ return rows.join('\n');
108
+ };
109
+ }
110
+ /**
111
+ * Export Rank N classification results
112
+ */
113
+ static rankNClassificationCSV(ranks = 3) {
114
+ return annotations => {
115
+ const rankHeaders = Array.from({ length: ranks }, (_, i) => `rank${i + 1}`).join(',');
116
+ const rows = [`task_id,annotation_id,${rankHeaders},annotator,lead_time,created_at`];
117
+ for (const annotation of annotations) {
118
+ const rankValues = [];
119
+ for (let i = 1; i <= ranks; i++) {
120
+ const rankResult = annotation.result.find(r => r.from_name === `rank${i}`);
121
+ rankValues.push(rankResult?.value?.choices?.[0] || '');
122
+ }
123
+ rows.push([
124
+ annotation.task,
125
+ annotation.id,
126
+ ...rankValues,
127
+ annotation.completed_by?.email || 'unknown',
128
+ annotation.lead_time || 0,
129
+ annotation.created_at
130
+ ].join(','));
131
+ }
132
+ return rows.join('\n');
133
+ };
134
+ }
135
+ /**
136
+ * Export object detection results as COCO format
137
+ */
138
+ static coco() {
139
+ return (annotations, context) => {
140
+ const images = [];
141
+ const cocoAnnotations = [];
142
+ const categories = new Map();
143
+ let imageId = 1;
144
+ let annotationId = 1;
145
+ let categoryId = 1;
146
+ for (const annotation of annotations) {
147
+ // Add image
148
+ images.push({
149
+ id: imageId,
150
+ file_name: `task_${annotation.task}.jpg`,
151
+ width: 0, // TODO: extract from annotation if available
152
+ height: 0
153
+ });
154
+ // Process bounding boxes
155
+ for (const result of annotation.result) {
156
+ if (result.type === 'rectanglelabels') {
157
+ const label = result.value.rectanglelabels[0];
158
+ // Register category
159
+ if (!categories.has(label)) {
160
+ categories.set(label, categoryId++);
161
+ }
162
+ // Add annotation
163
+ cocoAnnotations.push({
164
+ id: annotationId++,
165
+ image_id: imageId,
166
+ category_id: categories.get(label),
167
+ bbox: [result.value.x, result.value.y, result.value.width, result.value.height],
168
+ area: result.value.width * result.value.height,
169
+ iscrowd: 0
170
+ });
171
+ }
172
+ }
173
+ imageId++;
174
+ }
175
+ return {
176
+ info: {
177
+ description: context.projectTitle || 'Label Studio Export',
178
+ date_created: context.exportedAt
179
+ },
180
+ images,
181
+ annotations: cocoAnnotations,
182
+ categories: Array.from(categories.entries()).map(([name, id]) => ({
183
+ id,
184
+ name,
185
+ supercategory: 'none'
186
+ }))
187
+ };
188
+ };
189
+ }
190
+ /**
191
+ * Export object detection results as YOLO format
192
+ */
193
+ static yolo() {
194
+ return annotations => {
195
+ const taskAnnotations = new Map();
196
+ const categoryIndex = new Map();
197
+ let nextCategoryId = 0;
198
+ for (const annotation of annotations) {
199
+ const lines = [];
200
+ for (const result of annotation.result) {
201
+ if (result.type === 'rectanglelabels') {
202
+ const label = result.value.rectanglelabels[0];
203
+ // Register category
204
+ if (!categoryIndex.has(label)) {
205
+ categoryIndex.set(label, nextCategoryId++);
206
+ }
207
+ const classId = categoryIndex.get(label);
208
+ // Convert to YOLO format (normalized center x, center y, width, height)
209
+ const x = result.value.x / 100;
210
+ const y = result.value.y / 100;
211
+ const w = result.value.width / 100;
212
+ const h = result.value.height / 100;
213
+ const centerX = x + w / 2;
214
+ const centerY = y + h / 2;
215
+ lines.push(`${classId} ${centerX} ${centerY} ${w} ${h}`);
216
+ }
217
+ }
218
+ if (lines.length > 0) {
219
+ taskAnnotations.set(annotation.task, lines.join('\n'));
220
+ }
221
+ }
222
+ return taskAnnotations;
223
+ };
224
+ }
225
+ /**
226
+ * Export NER (Named Entity Recognition) results
227
+ */
228
+ static nerJSON() {
229
+ return annotations => {
230
+ return annotations.map(annotation => {
231
+ const entities = [];
232
+ for (const result of annotation.result) {
233
+ if (result.type === 'labels') {
234
+ entities.push({
235
+ start: result.value.start,
236
+ end: result.value.end,
237
+ text: result.value.text,
238
+ label: result.value.labels[0]
239
+ });
240
+ }
241
+ }
242
+ return {
243
+ task_id: annotation.task,
244
+ annotation_id: annotation.id,
245
+ entities,
246
+ annotator: annotation.completed_by?.email
247
+ };
248
+ });
249
+ };
250
+ }
251
+ }
252
+ exports.ExportFormats = ExportFormats;
253
+ // Register default formats
254
+ registerExportFormat('json', ExportFormats.json());
255
+ registerExportFormat('jsonl', ExportFormats.jsonl());
256
+ registerExportFormat('csv', ExportFormats.imageClassificationCSV());
257
+ registerExportFormat('rank-csv', ExportFormats.rankNClassificationCSV());
258
+ registerExportFormat('coco', ExportFormats.coco());
259
+ registerExportFormat('yolo', ExportFormats.yolo());
260
+ registerExportFormat('ner-json', ExportFormats.nerJSON());
261
+ //# sourceMappingURL=annotation-exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotation-exporter.js","sourceRoot":"","sources":["../../server/utils/annotation-exporter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Annotation Exporter\n *\n * Flexible annotation export system with pluggable format converters.\n * Supports custom export formats for different use cases.\n */\n\nexport interface LabelStudioAnnotation {\n id: number\n task: number\n project: number\n completed_by: {\n id: number\n email: string\n first_name: string\n last_name: string\n }\n result: Array<{\n from_name: string\n to_name: string\n type: string\n value: any\n }>\n created_at: string\n updated_at: string\n lead_time?: number\n}\n\nexport interface ExportContext {\n projectId: number\n projectTitle?: string\n exportedAt: string\n metadata?: any\n}\n\n/**\n * Export format converter function type\n * Converts Label Studio annotations to custom format\n */\nexport type FormatConverter<T = any> = (\n annotations: LabelStudioAnnotation[],\n context: ExportContext\n) => T | Promise<T>\n\n/**\n * Registry for custom export formats\n */\nconst formatConverters: Map<string, FormatConverter> = new Map()\n\n/**\n * Register a custom export format converter\n *\n * @param formatName - Unique format identifier (e.g., \"csv\", \"coco\", \"yolo\")\n * @param converter - Converter function\n *\n * @example\n * registerExportFormat('csv', (annotations, context) => {\n * const rows = annotations.map(a => ({\n * id: a.id,\n * task: a.task,\n * result: JSON.stringify(a.result)\n * }))\n * return Papa.unparse(rows)\n * })\n */\nexport function registerExportFormat<T = any>(formatName: string, converter: FormatConverter<T>): void {\n formatConverters.set(formatName.toLowerCase(), converter)\n}\n\n/**\n * Unregister an export format\n */\nexport function unregisterExportFormat(formatName: string): void {\n formatConverters.delete(formatName.toLowerCase())\n}\n\n/**\n * Get all registered format names\n */\nexport function getRegisteredFormats(): string[] {\n return Array.from(formatConverters.keys())\n}\n\n/**\n * Export annotations to specified format\n *\n * @param annotations - Label Studio annotations\n * @param format - Export format name\n * @param context - Export context\n * @returns Converted data in requested format\n */\nexport async function exportAnnotations<T = any>(\n annotations: LabelStudioAnnotation[],\n format: string,\n context: ExportContext\n): Promise<T> {\n const converter = formatConverters.get(format.toLowerCase())\n\n if (!converter) {\n throw new Error(`Unknown export format: ${format}. Available formats: ${getRegisteredFormats().join(', ')}`)\n }\n\n return await converter(annotations, context)\n}\n\n/**\n * Pre-built export formats\n */\nexport class ExportFormats {\n /**\n * Export as JSON (default Label Studio format)\n */\n static json(): FormatConverter<string> {\n return (annotations, context) => {\n return JSON.stringify(\n {\n meta: context,\n annotations\n },\n null,\n 2\n )\n }\n }\n\n /**\n * Export as JSON Lines (one annotation per line)\n */\n static jsonl(): FormatConverter<string> {\n return annotations => {\n return annotations.map(a => JSON.stringify(a)).join('\\n')\n }\n }\n\n /**\n * Export image classification results as CSV\n */\n static imageClassificationCSV(): FormatConverter<string> {\n return annotations => {\n const rows: string[] = ['task_id,annotation_id,label,annotator,lead_time,created_at']\n\n for (const annotation of annotations) {\n const label = annotation.result.find(r => r.type === 'choices')\n if (label && label.value.choices) {\n const choice = label.value.choices[0]\n rows.push(\n [\n annotation.task,\n annotation.id,\n choice,\n annotation.completed_by?.email || 'unknown',\n annotation.lead_time || 0,\n annotation.created_at\n ].join(',')\n )\n }\n }\n\n return rows.join('\\n')\n }\n }\n\n /**\n * Export Rank N classification results\n */\n static rankNClassificationCSV(ranks: number = 3): FormatConverter<string> {\n return annotations => {\n const rankHeaders = Array.from({ length: ranks }, (_, i) => `rank${i + 1}`).join(',')\n const rows: string[] = [`task_id,annotation_id,${rankHeaders},annotator,lead_time,created_at`]\n\n for (const annotation of annotations) {\n const rankValues: string[] = []\n\n for (let i = 1; i <= ranks; i++) {\n const rankResult = annotation.result.find(r => r.from_name === `rank${i}`)\n rankValues.push(rankResult?.value?.choices?.[0] || '')\n }\n\n rows.push(\n [\n annotation.task,\n annotation.id,\n ...rankValues,\n annotation.completed_by?.email || 'unknown',\n annotation.lead_time || 0,\n annotation.created_at\n ].join(',')\n )\n }\n\n return rows.join('\\n')\n }\n }\n\n /**\n * Export object detection results as COCO format\n */\n static coco(): FormatConverter<any> {\n return (annotations, context) => {\n const images: any[] = []\n const cocoAnnotations: any[] = []\n const categories: Map<string, number> = new Map()\n\n let imageId = 1\n let annotationId = 1\n let categoryId = 1\n\n for (const annotation of annotations) {\n // Add image\n images.push({\n id: imageId,\n file_name: `task_${annotation.task}.jpg`,\n width: 0, // TODO: extract from annotation if available\n height: 0\n })\n\n // Process bounding boxes\n for (const result of annotation.result) {\n if (result.type === 'rectanglelabels') {\n const label = result.value.rectanglelabels[0]\n\n // Register category\n if (!categories.has(label)) {\n categories.set(label, categoryId++)\n }\n\n // Add annotation\n cocoAnnotations.push({\n id: annotationId++,\n image_id: imageId,\n category_id: categories.get(label),\n bbox: [result.value.x, result.value.y, result.value.width, result.value.height],\n area: result.value.width * result.value.height,\n iscrowd: 0\n })\n }\n }\n\n imageId++\n }\n\n return {\n info: {\n description: context.projectTitle || 'Label Studio Export',\n date_created: context.exportedAt\n },\n images,\n annotations: cocoAnnotations,\n categories: Array.from(categories.entries()).map(([name, id]) => ({\n id,\n name,\n supercategory: 'none'\n }))\n }\n }\n }\n\n /**\n * Export object detection results as YOLO format\n */\n static yolo(): FormatConverter<Map<number, string>> {\n return annotations => {\n const taskAnnotations: Map<number, string> = new Map()\n const categoryIndex: Map<string, number> = new Map()\n let nextCategoryId = 0\n\n for (const annotation of annotations) {\n const lines: string[] = []\n\n for (const result of annotation.result) {\n if (result.type === 'rectanglelabels') {\n const label = result.value.rectanglelabels[0]\n\n // Register category\n if (!categoryIndex.has(label)) {\n categoryIndex.set(label, nextCategoryId++)\n }\n\n const classId = categoryIndex.get(label)!\n\n // Convert to YOLO format (normalized center x, center y, width, height)\n const x = result.value.x / 100\n const y = result.value.y / 100\n const w = result.value.width / 100\n const h = result.value.height / 100\n\n const centerX = x + w / 2\n const centerY = y + h / 2\n\n lines.push(`${classId} ${centerX} ${centerY} ${w} ${h}`)\n }\n }\n\n if (lines.length > 0) {\n taskAnnotations.set(annotation.task, lines.join('\\n'))\n }\n }\n\n return taskAnnotations\n }\n }\n\n /**\n * Export NER (Named Entity Recognition) results\n */\n static nerJSON(): FormatConverter<any[]> {\n return annotations => {\n return annotations.map(annotation => {\n const entities: any[] = []\n\n for (const result of annotation.result) {\n if (result.type === 'labels') {\n entities.push({\n start: result.value.start,\n end: result.value.end,\n text: result.value.text,\n label: result.value.labels[0]\n })\n }\n }\n\n return {\n task_id: annotation.task,\n annotation_id: annotation.id,\n entities,\n annotator: annotation.completed_by?.email\n }\n })\n }\n }\n}\n\n// Register default formats\nregisterExportFormat('json', ExportFormats.json())\nregisterExportFormat('jsonl', ExportFormats.jsonl())\nregisterExportFormat('csv', ExportFormats.imageClassificationCSV())\nregisterExportFormat('rank-csv', ExportFormats.rankNClassificationCSV())\nregisterExportFormat('coco', ExportFormats.coco())\nregisterExportFormat('yolo', ExportFormats.yolo())\nregisterExportFormat('ner-json', ExportFormats.nerJSON())\n"]}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Label Config Builder
3
+ *
4
+ * Flexible, declarative Label Studio configuration generator.
5
+ * Supports any data type and control combination without hardcoding templates.
6
+ */
7
+ export interface LabelConfigSpec {
8
+ dataType: 'image' | 'text' | 'audio' | 'video' | 'timeseries' | 'html' | 'hypertext';
9
+ dataName?: string;
10
+ controls: ControlSpec[];
11
+ }
12
+ export interface ControlSpec {
13
+ type: 'choices' | 'labels' | 'textarea' | 'rating' | 'rectangles' | 'polygon' | 'keypoint' | 'brush';
14
+ name: string;
15
+ toName: string;
16
+ config: any;
17
+ }
18
+ export interface ChoicesConfig {
19
+ choices: string[];
20
+ choice?: 'single' | 'multiple';
21
+ required?: boolean;
22
+ }
23
+ export interface LabelsConfig {
24
+ labels: Array<{
25
+ value: string;
26
+ background?: string;
27
+ hotkey?: string;
28
+ }>;
29
+ }
30
+ export interface RatingConfig {
31
+ maxRating?: number;
32
+ icon?: string;
33
+ size?: 'small' | 'medium' | 'large';
34
+ }
35
+ export declare class LabelConfigBuilder {
36
+ /**
37
+ * Build Label Studio XML configuration from specification
38
+ */
39
+ static build(spec: LabelConfigSpec): string;
40
+ /**
41
+ * Build data source tag (Image, Text, Audio, etc.)
42
+ */
43
+ private static buildDataTag;
44
+ /**
45
+ * Build control tag based on type
46
+ */
47
+ private static buildControlTag;
48
+ /**
49
+ * Build Choices control (single or multiple selection)
50
+ */
51
+ private static buildChoices;
52
+ /**
53
+ * Build Labels control (for NER, classification, etc.)
54
+ */
55
+ private static buildLabels;
56
+ /**
57
+ * Build TextArea control
58
+ */
59
+ private static buildTextArea;
60
+ /**
61
+ * Build Rating control
62
+ */
63
+ private static buildRating;
64
+ /**
65
+ * Build Rectangle control (bounding boxes)
66
+ */
67
+ private static buildRectangles;
68
+ /**
69
+ * Build Polygon control
70
+ */
71
+ private static buildPolygon;
72
+ /**
73
+ * Build Keypoint control
74
+ */
75
+ private static buildKeypoint;
76
+ /**
77
+ * Build Brush control (semantic segmentation)
78
+ */
79
+ private static buildBrush;
80
+ /**
81
+ * Escape XML special characters
82
+ */
83
+ private static escapeXml;
84
+ }
85
+ /**
86
+ * Pre-built template generators for common use cases
87
+ */
88
+ export declare class LabelConfigTemplates {
89
+ /**
90
+ * Generate Rank N image classification config
91
+ * Example: WBM Rank 3 classification
92
+ */
93
+ static imageRankN(ranks: number, classes: string[]): LabelConfigSpec;
94
+ /**
95
+ * Simple image classification
96
+ */
97
+ static imageClassification(classes: string[], multiLabel?: boolean): LabelConfigSpec;
98
+ /**
99
+ * Text classification (sentiment, intent, etc.)
100
+ */
101
+ static textClassification(classes: string[]): LabelConfigSpec;
102
+ /**
103
+ * Named Entity Recognition
104
+ */
105
+ static namedEntityRecognition(labels: Array<{
106
+ value: string;
107
+ background: string;
108
+ }>): LabelConfigSpec;
109
+ /**
110
+ * Object detection (bounding boxes)
111
+ */
112
+ static objectDetection(labels: string[]): LabelConfigSpec;
113
+ /**
114
+ * Semantic segmentation
115
+ */
116
+ static semanticSegmentation(labels: string[]): LabelConfigSpec;
117
+ }