@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,108 @@
1
+ /**
2
+ * Task Transformer
3
+ *
4
+ * Flexible data transformation from any source format to Label Studio tasks.
5
+ * Supports nested data, predictions, and custom field mapping.
6
+ */
7
+ export interface TaskTransformRule {
8
+ /**
9
+ * Field mapping: Label Studio field name -> source data path
10
+ * Example: { "image": "image_url", "date": "metadata.timestamp" }
11
+ */
12
+ dataFields: {
13
+ [lsField: string]: string;
14
+ };
15
+ /**
16
+ * Prediction configuration (optional)
17
+ */
18
+ predictions?: PredictionConfig;
19
+ /**
20
+ * Metadata to attach to task (optional)
21
+ */
22
+ meta?: {
23
+ [key: string]: string;
24
+ };
25
+ }
26
+ export interface PredictionConfig {
27
+ /**
28
+ * Enable predictions
29
+ */
30
+ enabled: boolean;
31
+ /**
32
+ * Path to prediction result in source data
33
+ */
34
+ resultPath: string;
35
+ /**
36
+ * Path to confidence score (optional)
37
+ */
38
+ scorePath?: string;
39
+ /**
40
+ * Model version identifier (optional)
41
+ */
42
+ modelVersion?: string;
43
+ /**
44
+ * Transform function for prediction result
45
+ */
46
+ resultTransform?: (result: any) => any;
47
+ }
48
+ export interface LabelStudioTask {
49
+ data: string;
50
+ predictions?: Array<{
51
+ result: any;
52
+ score?: number;
53
+ model_version?: string;
54
+ }>;
55
+ meta?: any;
56
+ }
57
+ export declare class TaskTransformer {
58
+ /**
59
+ * Transform source data to Label Studio tasks
60
+ *
61
+ * @param sourceData - Array of source data objects
62
+ * @param rule - Transformation rules
63
+ * @returns Array of Label Studio tasks
64
+ */
65
+ static transform(sourceData: any[], rule: TaskTransformRule): LabelStudioTask[];
66
+ /**
67
+ * Transform a single data object
68
+ */
69
+ static transformOne(sourceData: any, rule: TaskTransformRule): LabelStudioTask | null;
70
+ /**
71
+ * Build prediction object from source data
72
+ */
73
+ private static buildPrediction;
74
+ /**
75
+ * Get nested value from object using dot notation path
76
+ * Example: "metadata.user.name" -> obj.metadata.user.name
77
+ */
78
+ private static getNestedValue;
79
+ /**
80
+ * Transform with multiple rules (useful for heterogeneous data)
81
+ */
82
+ static transformMultiRule(sourceData: any[], rules: TaskTransformRule[]): LabelStudioTask[];
83
+ }
84
+ /**
85
+ * Pre-built transformation templates for common scenarios
86
+ */
87
+ export declare class TaskTransformTemplates {
88
+ /**
89
+ * WBM Image Classification with AI predictions
90
+ */
91
+ static wbmImageClassification(includeAiPrediction?: boolean): TaskTransformRule;
92
+ /**
93
+ * Simple image classification
94
+ */
95
+ static imageClassification(imageField?: string): TaskTransformRule;
96
+ /**
97
+ * Text classification with metadata
98
+ */
99
+ static textClassification(textField?: string, metaFields?: string[]): TaskTransformRule;
100
+ /**
101
+ * Time series data
102
+ */
103
+ static timeSeries(valuesField: string, timestampField?: string): TaskTransformRule;
104
+ /**
105
+ * Object detection with bounding box predictions
106
+ */
107
+ static objectDetection(imageField?: string, predictionsField?: string): TaskTransformRule;
108
+ }
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ /**
3
+ * Task Transformer
4
+ *
5
+ * Flexible data transformation from any source format to Label Studio tasks.
6
+ * Supports nested data, predictions, and custom field mapping.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.TaskTransformTemplates = exports.TaskTransformer = void 0;
10
+ class TaskTransformer {
11
+ /**
12
+ * Transform source data to Label Studio tasks
13
+ *
14
+ * @param sourceData - Array of source data objects
15
+ * @param rule - Transformation rules
16
+ * @returns Array of Label Studio tasks
17
+ */
18
+ static transform(sourceData, rule) {
19
+ return sourceData.map(data => this.transformOne(data, rule)).filter(task => task !== null);
20
+ }
21
+ /**
22
+ * Transform a single data object
23
+ */
24
+ static transformOne(sourceData, rule) {
25
+ try {
26
+ // Build task data
27
+ const taskData = {};
28
+ for (const [lsField, sourcePath] of Object.entries(rule.dataFields)) {
29
+ const value = this.getNestedValue(sourceData, sourcePath);
30
+ if (value !== undefined) {
31
+ taskData[lsField] = value;
32
+ }
33
+ }
34
+ // Skip if no data extracted
35
+ if (Object.keys(taskData).length === 0) {
36
+ return null;
37
+ }
38
+ const task = {
39
+ data: JSON.stringify(taskData)
40
+ };
41
+ // Add predictions if configured
42
+ if (rule.predictions?.enabled) {
43
+ const prediction = this.buildPrediction(sourceData, rule.predictions);
44
+ if (prediction) {
45
+ task.predictions = [prediction];
46
+ }
47
+ }
48
+ // Add metadata if configured
49
+ if (rule.meta) {
50
+ const meta = {};
51
+ for (const [metaKey, sourcePath] of Object.entries(rule.meta)) {
52
+ const value = this.getNestedValue(sourceData, sourcePath);
53
+ if (value !== undefined) {
54
+ meta[metaKey] = value;
55
+ }
56
+ }
57
+ if (Object.keys(meta).length > 0) {
58
+ task.meta = meta;
59
+ }
60
+ }
61
+ return task;
62
+ }
63
+ catch (error) {
64
+ console.error('Failed to transform task:', error);
65
+ return null;
66
+ }
67
+ }
68
+ /**
69
+ * Build prediction object from source data
70
+ */
71
+ static buildPrediction(sourceData, config) {
72
+ const result = this.getNestedValue(sourceData, config.resultPath);
73
+ if (!result) {
74
+ return null;
75
+ }
76
+ const prediction = {
77
+ result: config.resultTransform ? config.resultTransform(result) : result
78
+ };
79
+ if (config.scorePath) {
80
+ const score = this.getNestedValue(sourceData, config.scorePath);
81
+ if (score !== undefined) {
82
+ prediction.score = score;
83
+ }
84
+ }
85
+ if (config.modelVersion) {
86
+ prediction.model_version = config.modelVersion;
87
+ }
88
+ return prediction;
89
+ }
90
+ /**
91
+ * Get nested value from object using dot notation path
92
+ * Example: "metadata.user.name" -> obj.metadata.user.name
93
+ */
94
+ static getNestedValue(obj, path) {
95
+ if (!path || !obj)
96
+ return undefined;
97
+ const keys = path.split('.');
98
+ let current = obj;
99
+ for (const key of keys) {
100
+ if (current === null || current === undefined) {
101
+ return undefined;
102
+ }
103
+ // Support array indexing: "items[0].name"
104
+ const arrayMatch = key.match(/^(\w+)\[(\d+)\]$/);
105
+ if (arrayMatch) {
106
+ const [, arrayKey, index] = arrayMatch;
107
+ current = current[arrayKey]?.[parseInt(index, 10)];
108
+ }
109
+ else {
110
+ current = current[key];
111
+ }
112
+ }
113
+ return current;
114
+ }
115
+ /**
116
+ * Transform with multiple rules (useful for heterogeneous data)
117
+ */
118
+ static transformMultiRule(sourceData, rules) {
119
+ const tasks = [];
120
+ for (const rule of rules) {
121
+ tasks.push(...this.transform(sourceData, rule));
122
+ }
123
+ return tasks;
124
+ }
125
+ }
126
+ exports.TaskTransformer = TaskTransformer;
127
+ /**
128
+ * Pre-built transformation templates for common scenarios
129
+ */
130
+ class TaskTransformTemplates {
131
+ /**
132
+ * WBM Image Classification with AI predictions
133
+ */
134
+ static wbmImageClassification(includeAiPrediction = true) {
135
+ const rule = {
136
+ dataFields: {
137
+ image: 'image_url',
138
+ date: 'timestamp',
139
+ device_id: 'device_id'
140
+ },
141
+ meta: {
142
+ wafer_id: 'wafer_id',
143
+ lot_id: 'lot_id'
144
+ }
145
+ };
146
+ if (includeAiPrediction) {
147
+ rule.predictions = {
148
+ enabled: true,
149
+ resultPath: 'ai_prediction',
150
+ scorePath: 'confidence',
151
+ modelVersion: 'wbm-classifier-v1',
152
+ resultTransform: result => {
153
+ // Transform AI result to Label Studio format
154
+ return [
155
+ {
156
+ from_name: 'rank1',
157
+ to_name: 'data',
158
+ type: 'choices',
159
+ value: {
160
+ choices: [result.rank1]
161
+ }
162
+ },
163
+ {
164
+ from_name: 'rank2',
165
+ to_name: 'data',
166
+ type: 'choices',
167
+ value: {
168
+ choices: [result.rank2]
169
+ }
170
+ },
171
+ {
172
+ from_name: 'rank3',
173
+ to_name: 'data',
174
+ type: 'choices',
175
+ value: {
176
+ choices: [result.rank3]
177
+ }
178
+ }
179
+ ];
180
+ }
181
+ };
182
+ }
183
+ return rule;
184
+ }
185
+ /**
186
+ * Simple image classification
187
+ */
188
+ static imageClassification(imageField = 'image_url') {
189
+ return {
190
+ dataFields: {
191
+ image: imageField
192
+ }
193
+ };
194
+ }
195
+ /**
196
+ * Text classification with metadata
197
+ */
198
+ static textClassification(textField = 'text', metaFields = []) {
199
+ const rule = {
200
+ dataFields: {
201
+ text: textField
202
+ }
203
+ };
204
+ if (metaFields.length > 0) {
205
+ rule.meta = {};
206
+ for (const field of metaFields) {
207
+ rule.meta[field] = field;
208
+ }
209
+ }
210
+ return rule;
211
+ }
212
+ /**
213
+ * Time series data
214
+ */
215
+ static timeSeries(valuesField, timestampField) {
216
+ const dataFields = {
217
+ timeseries: valuesField
218
+ };
219
+ if (timestampField) {
220
+ dataFields.timestamp = timestampField;
221
+ }
222
+ return {
223
+ dataFields
224
+ };
225
+ }
226
+ /**
227
+ * Object detection with bounding box predictions
228
+ */
229
+ static objectDetection(imageField = 'image_url', predictionsField) {
230
+ const rule = {
231
+ dataFields: {
232
+ image: imageField
233
+ }
234
+ };
235
+ if (predictionsField) {
236
+ rule.predictions = {
237
+ enabled: true,
238
+ resultPath: predictionsField,
239
+ resultTransform: bboxes => {
240
+ // Transform bounding boxes to Label Studio format
241
+ return bboxes.map((bbox) => ({
242
+ from_name: 'bbox',
243
+ to_name: 'data',
244
+ type: 'rectanglelabels',
245
+ value: {
246
+ x: bbox.x,
247
+ y: bbox.y,
248
+ width: bbox.width,
249
+ height: bbox.height,
250
+ rectanglelabels: [bbox.label]
251
+ }
252
+ }));
253
+ }
254
+ };
255
+ }
256
+ return rule;
257
+ }
258
+ }
259
+ exports.TaskTransformTemplates = TaskTransformTemplates;
260
+ //# sourceMappingURL=task-transformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-transformer.js","sourceRoot":"","sources":["../../server/utils/task-transformer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Task Transformer\n *\n * Flexible data transformation from any source format to Label Studio tasks.\n * Supports nested data, predictions, and custom field mapping.\n */\n\nexport interface TaskTransformRule {\n /**\n * Field mapping: Label Studio field name -> source data path\n * Example: { \"image\": \"image_url\", \"date\": \"metadata.timestamp\" }\n */\n dataFields: { [lsField: string]: string }\n\n /**\n * Prediction configuration (optional)\n */\n predictions?: PredictionConfig\n\n /**\n * Metadata to attach to task (optional)\n */\n meta?: { [key: string]: string }\n}\n\nexport interface PredictionConfig {\n /**\n * Enable predictions\n */\n enabled: boolean\n\n /**\n * Path to prediction result in source data\n */\n resultPath: string\n\n /**\n * Path to confidence score (optional)\n */\n scorePath?: string\n\n /**\n * Model version identifier (optional)\n */\n modelVersion?: string\n\n /**\n * Transform function for prediction result\n */\n resultTransform?: (result: any) => any\n}\n\nexport interface LabelStudioTask {\n data: string // JSON string\n predictions?: Array<{\n result: any\n score?: number\n model_version?: string\n }>\n meta?: any\n}\n\nexport class TaskTransformer {\n /**\n * Transform source data to Label Studio tasks\n *\n * @param sourceData - Array of source data objects\n * @param rule - Transformation rules\n * @returns Array of Label Studio tasks\n */\n static transform(sourceData: any[], rule: TaskTransformRule): LabelStudioTask[] {\n return sourceData.map(data => this.transformOne(data, rule)).filter(task => task !== null) as LabelStudioTask[]\n }\n\n /**\n * Transform a single data object\n */\n static transformOne(sourceData: any, rule: TaskTransformRule): LabelStudioTask | null {\n try {\n // Build task data\n const taskData: any = {}\n for (const [lsField, sourcePath] of Object.entries(rule.dataFields)) {\n const value = this.getNestedValue(sourceData, sourcePath)\n if (value !== undefined) {\n taskData[lsField] = value\n }\n }\n\n // Skip if no data extracted\n if (Object.keys(taskData).length === 0) {\n return null\n }\n\n const task: LabelStudioTask = {\n data: JSON.stringify(taskData)\n }\n\n // Add predictions if configured\n if (rule.predictions?.enabled) {\n const prediction = this.buildPrediction(sourceData, rule.predictions)\n if (prediction) {\n task.predictions = [prediction]\n }\n }\n\n // Add metadata if configured\n if (rule.meta) {\n const meta: any = {}\n for (const [metaKey, sourcePath] of Object.entries(rule.meta)) {\n const value = this.getNestedValue(sourceData, sourcePath)\n if (value !== undefined) {\n meta[metaKey] = value\n }\n }\n if (Object.keys(meta).length > 0) {\n task.meta = meta\n }\n }\n\n return task\n } catch (error) {\n console.error('Failed to transform task:', error)\n return null\n }\n }\n\n /**\n * Build prediction object from source data\n */\n private static buildPrediction(\n sourceData: any,\n config: PredictionConfig\n ): { result: any; score?: number; model_version?: string } | null {\n const result = this.getNestedValue(sourceData, config.resultPath)\n if (!result) {\n return null\n }\n\n const prediction: any = {\n result: config.resultTransform ? config.resultTransform(result) : result\n }\n\n if (config.scorePath) {\n const score = this.getNestedValue(sourceData, config.scorePath)\n if (score !== undefined) {\n prediction.score = score\n }\n }\n\n if (config.modelVersion) {\n prediction.model_version = config.modelVersion\n }\n\n return prediction\n }\n\n /**\n * Get nested value from object using dot notation path\n * Example: \"metadata.user.name\" -> obj.metadata.user.name\n */\n private static getNestedValue(obj: any, path: string): any {\n if (!path || !obj) return undefined\n\n const keys = path.split('.')\n let current = obj\n\n for (const key of keys) {\n if (current === null || current === undefined) {\n return undefined\n }\n\n // Support array indexing: \"items[0].name\"\n const arrayMatch = key.match(/^(\\w+)\\[(\\d+)\\]$/)\n if (arrayMatch) {\n const [, arrayKey, index] = arrayMatch\n current = current[arrayKey]?.[parseInt(index, 10)]\n } else {\n current = current[key]\n }\n }\n\n return current\n }\n\n /**\n * Transform with multiple rules (useful for heterogeneous data)\n */\n static transformMultiRule(sourceData: any[], rules: TaskTransformRule[]): LabelStudioTask[] {\n const tasks: LabelStudioTask[] = []\n\n for (const rule of rules) {\n tasks.push(...this.transform(sourceData, rule))\n }\n\n return tasks\n }\n}\n\n/**\n * Pre-built transformation templates for common scenarios\n */\nexport class TaskTransformTemplates {\n /**\n * WBM Image Classification with AI predictions\n */\n static wbmImageClassification(includeAiPrediction: boolean = true): TaskTransformRule {\n const rule: TaskTransformRule = {\n dataFields: {\n image: 'image_url',\n date: 'timestamp',\n device_id: 'device_id'\n },\n meta: {\n wafer_id: 'wafer_id',\n lot_id: 'lot_id'\n }\n }\n\n if (includeAiPrediction) {\n rule.predictions = {\n enabled: true,\n resultPath: 'ai_prediction',\n scorePath: 'confidence',\n modelVersion: 'wbm-classifier-v1',\n resultTransform: result => {\n // Transform AI result to Label Studio format\n return [\n {\n from_name: 'rank1',\n to_name: 'data',\n type: 'choices',\n value: {\n choices: [result.rank1]\n }\n },\n {\n from_name: 'rank2',\n to_name: 'data',\n type: 'choices',\n value: {\n choices: [result.rank2]\n }\n },\n {\n from_name: 'rank3',\n to_name: 'data',\n type: 'choices',\n value: {\n choices: [result.rank3]\n }\n }\n ]\n }\n }\n }\n\n return rule\n }\n\n /**\n * Simple image classification\n */\n static imageClassification(imageField: string = 'image_url'): TaskTransformRule {\n return {\n dataFields: {\n image: imageField\n }\n }\n }\n\n /**\n * Text classification with metadata\n */\n static textClassification(textField: string = 'text', metaFields: string[] = []): TaskTransformRule {\n const rule: TaskTransformRule = {\n dataFields: {\n text: textField\n }\n }\n\n if (metaFields.length > 0) {\n rule.meta = {}\n for (const field of metaFields) {\n rule.meta[field] = field\n }\n }\n\n return rule\n }\n\n /**\n * Time series data\n */\n static timeSeries(valuesField: string, timestampField?: string): TaskTransformRule {\n const dataFields: any = {\n timeseries: valuesField\n }\n\n if (timestampField) {\n dataFields.timestamp = timestampField\n }\n\n return {\n dataFields\n }\n }\n\n /**\n * Object detection with bounding box predictions\n */\n static objectDetection(imageField: string = 'image_url', predictionsField?: string): TaskTransformRule {\n const rule: TaskTransformRule = {\n dataFields: {\n image: imageField\n }\n }\n\n if (predictionsField) {\n rule.predictions = {\n enabled: true,\n resultPath: predictionsField,\n resultTransform: bboxes => {\n // Transform bounding boxes to Label Studio format\n return bboxes.map((bbox: any) => ({\n from_name: 'bbox',\n to_name: 'data',\n type: 'rectanglelabels',\n value: {\n x: bbox.x,\n y: bbox.y,\n width: bbox.width,\n height: bbox.height,\n rectanglelabels: [bbox.label]\n }\n }))\n }\n }\n }\n\n return rule\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@things-factory/integration-label-studio",
3
+ "version": "9.1.19",
4
+ "main": "dist-server/index.js",
5
+ "browser": "dist-client/index.js",
6
+ "things-factory": true,
7
+ "author": "Things-Factory Team",
8
+ "description": "Integration module for embedding Label Studio in Things-Factory with SSO support",
9
+ "license": "MIT",
10
+ "publishConfig": {
11
+ "access": "public",
12
+ "@things-factory:registry": "https://registry.npmjs.org"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/hatiolab/things-factory.git",
17
+ "directory": "packages/integration-label-studio"
18
+ },
19
+ "scripts": {
20
+ "build": "npm run build:server && npm run build:client",
21
+ "copy:files": "copyfiles -e \"./client/**/*.{ts,js,json}\" -u 1 \"./client/**/*\" dist-client",
22
+ "build:client": "npm run copy:files && npx tsc --p ./client/tsconfig.json",
23
+ "build:server": "npx tsc --p ./server/tsconfig.json",
24
+ "clean:client": "npx rimraf dist-client",
25
+ "clean:server": "npx rimraf dist-server",
26
+ "clean": "npm run clean:server && npm run clean:client"
27
+ },
28
+ "dependencies": {
29
+ "@operato/graphql": "^9.0.0",
30
+ "@operato/layout": "^9.0.0",
31
+ "@things-factory/ai-inference": "^9.1.19",
32
+ "@things-factory/auth-base": "^9.1.19",
33
+ "@things-factory/dataset": "^9.1.19",
34
+ "@things-factory/env": "^9.1.0",
35
+ "@things-factory/menu-base": "^9.1.19",
36
+ "@things-factory/shell": "^9.1.19"
37
+ },
38
+ "keywords": [
39
+ "things-factory",
40
+ "label-studio",
41
+ "integration",
42
+ "iframe",
43
+ "sso",
44
+ "data-labeling"
45
+ ],
46
+ "gitHead": "078438034dbe19915108e89ff24024f7044a85a9"
47
+ }