synapse-sdk 2025.9.5__py3-none-any.whl → 2025.10.6__py3-none-any.whl

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.

Potentially problematic release.


This version of synapse-sdk might be problematic. Click here for more details.

Files changed (78) hide show
  1. synapse_sdk/clients/base.py +129 -9
  2. synapse_sdk/devtools/docs/docs/api/clients/base.md +230 -8
  3. synapse_sdk/devtools/docs/docs/api/plugins/models.md +58 -3
  4. synapse_sdk/devtools/docs/docs/plugins/categories/neural-net-plugins/train-action-overview.md +663 -0
  5. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
  6. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
  7. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
  8. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
  9. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-action.md +934 -0
  10. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-overview.md +585 -0
  11. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-template.md +715 -0
  12. synapse_sdk/devtools/docs/docs/plugins/export-plugins.md +39 -0
  13. synapse_sdk/devtools/docs/docs/plugins/plugins.md +12 -5
  14. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/base.md +230 -8
  15. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/plugins/models.md +114 -0
  16. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/neural-net-plugins/train-action-overview.md +621 -0
  17. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
  18. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
  19. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
  20. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
  21. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-action.md +934 -0
  22. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-overview.md +585 -0
  23. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-template.md +715 -0
  24. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/export-plugins.md +39 -0
  25. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current.json +16 -4
  26. synapse_sdk/devtools/docs/sidebars.ts +45 -1
  27. synapse_sdk/plugins/README.md +487 -80
  28. synapse_sdk/plugins/categories/base.py +1 -0
  29. synapse_sdk/plugins/categories/export/actions/export/action.py +8 -3
  30. synapse_sdk/plugins/categories/export/actions/export/utils.py +108 -8
  31. synapse_sdk/plugins/categories/export/templates/config.yaml +18 -0
  32. synapse_sdk/plugins/categories/export/templates/plugin/export.py +97 -0
  33. synapse_sdk/plugins/categories/neural_net/actions/train.py +592 -22
  34. synapse_sdk/plugins/categories/neural_net/actions/tune.py +150 -3
  35. synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +4 -0
  36. synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation/__init__.py +3 -0
  37. synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation/action.py +10 -0
  38. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/__init__.py +28 -0
  39. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/action.py +145 -0
  40. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/enums.py +269 -0
  41. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/exceptions.py +14 -0
  42. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/factory.py +76 -0
  43. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/models.py +97 -0
  44. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/orchestrator.py +250 -0
  45. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/run.py +64 -0
  46. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/__init__.py +17 -0
  47. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/annotation.py +284 -0
  48. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/base.py +170 -0
  49. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/extraction.py +83 -0
  50. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/metrics.py +87 -0
  51. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/preprocessor.py +127 -0
  52. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/validation.py +143 -0
  53. synapse_sdk/plugins/categories/upload/actions/upload/__init__.py +2 -1
  54. synapse_sdk/plugins/categories/upload/actions/upload/action.py +8 -1
  55. synapse_sdk/plugins/categories/upload/actions/upload/context.py +0 -1
  56. synapse_sdk/plugins/categories/upload/actions/upload/models.py +134 -94
  57. synapse_sdk/plugins/categories/upload/actions/upload/steps/cleanup.py +2 -2
  58. synapse_sdk/plugins/categories/upload/actions/upload/steps/generate.py +6 -2
  59. synapse_sdk/plugins/categories/upload/actions/upload/steps/initialize.py +24 -9
  60. synapse_sdk/plugins/categories/upload/actions/upload/steps/metadata.py +130 -18
  61. synapse_sdk/plugins/categories/upload/actions/upload/steps/organize.py +147 -37
  62. synapse_sdk/plugins/categories/upload/actions/upload/steps/upload.py +10 -5
  63. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/flat.py +31 -6
  64. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/recursive.py +65 -37
  65. synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/default.py +17 -2
  66. synapse_sdk/plugins/categories/upload/templates/README.md +394 -0
  67. synapse_sdk/plugins/models.py +62 -0
  68. synapse_sdk/utils/file/download.py +261 -0
  69. {synapse_sdk-2025.9.5.dist-info → synapse_sdk-2025.10.6.dist-info}/METADATA +15 -2
  70. {synapse_sdk-2025.9.5.dist-info → synapse_sdk-2025.10.6.dist-info}/RECORD +74 -43
  71. synapse_sdk/devtools/docs/docs/plugins/developing-upload-template.md +0 -1463
  72. synapse_sdk/devtools/docs/docs/plugins/upload-plugins.md +0 -1964
  73. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/developing-upload-template.md +0 -1463
  74. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/upload-plugins.md +0 -2077
  75. {synapse_sdk-2025.9.5.dist-info → synapse_sdk-2025.10.6.dist-info}/WHEEL +0 -0
  76. {synapse_sdk-2025.9.5.dist-info → synapse_sdk-2025.10.6.dist-info}/entry_points.txt +0 -0
  77. {synapse_sdk-2025.9.5.dist-info → synapse_sdk-2025.10.6.dist-info}/licenses/LICENSE +0 -0
  78. {synapse_sdk-2025.9.5.dist-info → synapse_sdk-2025.10.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,585 @@
1
+ ---
2
+ id: upload-plugin-overview
3
+ title: Upload Plugin Overview
4
+ sidebar_position: 1
5
+ ---
6
+
7
+ # Upload Plugin Overview
8
+
9
+ Upload plugins provide comprehensive file upload and data ingestion operations for processing files into the Synapse platform with metadata support, security validation, and organized data unit generation.
10
+
11
+ ## Quick Overview
12
+
13
+ **Category:** Upload
14
+ **Available Actions:** `upload`
15
+ **Execution Method:** Job-based execution
16
+
17
+ ## Key Features
18
+
19
+ - **Multi-Path Mode Support**: Upload files from different locations with individual path settings for each asset
20
+ - **Excel Metadata Integration**: Automatic metadata annotation from Excel files
21
+ - **Flexible File Organization**: Single-path or multi-path modes for different use cases
22
+ - **Batch Processing**: Optimized batch processing for large-scale uploads
23
+ - **Progress Tracking**: Real-time progress updates across workflow stages
24
+ - **Security Validation**: Comprehensive file and Excel security checks
25
+
26
+ ## Use Cases
27
+
28
+ - Bulk file uploads with metadata annotation
29
+ - Excel-based metadata mapping and validation
30
+ - Recursive directory processing
31
+ - Type-based file organization
32
+ - Batch data unit creation
33
+ - Multi-source dataset uploads (sensors, cameras, annotations from different locations)
34
+ - Secure file processing with size and content validation
35
+
36
+ ## Supported Upload Sources
37
+
38
+ - Local file system paths (files and directories)
39
+ - Recursive directory scanning
40
+ - Excel metadata files for enhanced file annotation
41
+ - Mixed file types with automatic organization
42
+ - Distributed data sources with per-asset path configuration
43
+
44
+ ## Configuration Modes
45
+
46
+ ### Mode 1: Single Path Mode (Default - `use_single_path: true`)
47
+
48
+ All assets share one base directory. The system expects subdirectories for each file specification.
49
+
50
+ ```json
51
+ {
52
+ "name": "Standard Upload",
53
+ "use_single_path": true,
54
+ "path": "/data/experiment",
55
+ "is_recursive": true,
56
+ "storage": 1,
57
+ "data_collection": 5
58
+ }
59
+ ```
60
+
61
+ **Expected Directory Structure:**
62
+
63
+ ```
64
+ /data/experiment/
65
+ ├── pcd_1/ # Point clouds
66
+ │ └── *.pcd
67
+ ├── image_1/ # Images
68
+ │ └── *.jpg
69
+ └── json_meta_1/ # Metadata
70
+ └── *.json
71
+ ```
72
+
73
+ ### Mode 2: Multi-Path Mode (`use_single_path: false`)
74
+
75
+ Each asset has its own path and recursive setting. Perfect for distributed data sources.
76
+
77
+ ```json
78
+ {
79
+ "name": "Multi-Source Upload",
80
+ "use_single_path": false,
81
+ "assets": {
82
+ "pcd_1": {
83
+ "path": "/sensors/lidar/scan_001",
84
+ "is_recursive": false
85
+ },
86
+ "image_1": {
87
+ "path": "/sensors/camera/front",
88
+ "is_recursive": true
89
+ },
90
+ "json_meta_1": {
91
+ "path": "/metadata/annotations",
92
+ "is_recursive": false
93
+ }
94
+ },
95
+ "storage": 1,
96
+ "data_collection": 5
97
+ }
98
+ ```
99
+
100
+ **Optional File Specs:**
101
+
102
+ In multi-path mode, file specifications can be marked as optional in the data collection's file specification template:
103
+
104
+ - **Required specs** (`is_required: true`): Must have an asset path in the `assets` parameter
105
+ - **Optional specs** (`is_required: false`): Can be omitted from `assets` - the system will skip them
106
+
107
+ Example with optional spec omitted:
108
+
109
+ ```json
110
+ {
111
+ "name": "Multi-Source Upload",
112
+ "use_single_path": false,
113
+ "assets": {
114
+ "pcd_1": {"path": "/sensors/lidar", "is_recursive": false},
115
+ "image_1": {"path": "/cameras/front", "is_recursive": true}
116
+ // "json_meta_1" is optional and omitted
117
+ },
118
+ "storage": 1,
119
+ "data_collection": 5
120
+ }
121
+ ```
122
+
123
+ The system logs: `"Skipping optional spec json_meta_1: no asset path configured"`
124
+
125
+ ## Basic Usage
126
+
127
+ ### CLI Usage
128
+
129
+ ```bash
130
+ # Single path mode (traditional)
131
+ synapse plugin run upload '{
132
+ "name": "Dataset Upload",
133
+ "use_single_path": true,
134
+ "path": "/data/training",
135
+ "is_recursive": true,
136
+ "storage": 1,
137
+ "data_collection": 5
138
+ }'
139
+
140
+ # Multi-path mode (advanced)
141
+ synapse plugin run upload '{
142
+ "name": "Multi-Sensor Upload",
143
+ "use_single_path": false,
144
+ "assets": {
145
+ "lidar": {"path": "/sensors/lidar", "is_recursive": true},
146
+ "camera": {"path": "/sensors/camera", "is_recursive": false}
147
+ },
148
+ "storage": 1,
149
+ "data_collection": 5
150
+ }'
151
+ ```
152
+
153
+ ### Python API Usage
154
+
155
+ ```python
156
+ from synapse_sdk.plugins.categories.upload.actions.upload.action import UploadAction
157
+
158
+ # Configure upload parameters
159
+ params = {
160
+ "name": "Dataset Upload",
161
+ "use_single_path": true,
162
+ "path": "/data/training_images",
163
+ "is_recursive": True,
164
+ "storage": 1,
165
+ "data_collection": 5,
166
+ "max_file_size_mb": 100
167
+ }
168
+
169
+ action = UploadAction(params=params, plugin_config=plugin_config)
170
+ result = action.start()
171
+
172
+ print(f"Uploaded {result['uploaded_files_count']} files")
173
+ print(f"Generated {result['generated_data_units_count']} data units")
174
+ ```
175
+
176
+ ## Configuration Parameters
177
+
178
+ ### Required Parameters
179
+
180
+ | Parameter | Type | Description | Example |
181
+ | ----------------- | ----- | ------------------ | ------------- |
182
+ | `name` | `str` | Upload name | `"My Upload"` |
183
+ | `storage` | `int` | Storage ID | `1` |
184
+ | `data_collection` | `int` | Data collection ID | `5` |
185
+
186
+ ### Mode-Specific Required Parameters
187
+
188
+ **Single Path Mode** (`use_single_path: true`):
189
+
190
+ - `path` (str): Base directory path
191
+
192
+ **Multi-Path Mode** (`use_single_path: false`):
193
+
194
+ - `assets` (dict): Asset-specific configurations with `path` and `is_recursive` per asset
195
+
196
+ ### Optional Parameters
197
+
198
+ | Parameter | Type | Default | Description |
199
+ | ------------------------------- | ------------- | ------- | --------------------------------- |
200
+ | `description` | `str \| None` | `None` | Upload description |
201
+ | `project` | `int \| None` | `None` | Project ID |
202
+ | `use_single_path` | `bool` | `true` | Mode toggle |
203
+ | `is_recursive` | `bool` | `true` | Recursive scan (single path mode) |
204
+ | `excel_metadata_path` | `str \| None` | `None` | Excel metadata file path (will be deprecated in future, use `excel_metadata` instead) |
205
+ | `excel_metadata` | `dict \| None`| `None` | Excel metadata (base64 encoded, recommended) |
206
+ | `max_file_size_mb` | `int` | `50` | Maximum file size in MB |
207
+ | `creating_data_unit_batch_size` | `int` | `100` | Batch size for data units |
208
+ | `use_async_upload` | `bool` | `True` | Use asynchronous processing |
209
+
210
+ ## Excel Metadata Support
211
+
212
+ The upload plugin provides advanced Excel metadata processing with flexible header support, comprehensive filename matching, and two distinct input methods for different use cases.
213
+
214
+ ### Input Methods
215
+
216
+ There are two separate parameters for providing Excel metadata:
217
+
218
+ #### 1. File Path Method (`excel_metadata_path`)
219
+
220
+ :::info Future Deprecation Notice
221
+ This parameter will be deprecated in a future version.
222
+ We recommend using the `excel_metadata` parameter with base64 encoding for new implementations.
223
+ :::
224
+
225
+ **Use case:** Traditional file-based uploads where the Excel file exists on the server's file system.
226
+
227
+ Simple string path to an Excel file:
228
+
229
+ ```json
230
+ {
231
+ "excel_metadata_path": "/data/metadata.xlsx"
232
+ }
233
+ ```
234
+
235
+ **Advantages:**
236
+ - Backward compatible with existing implementations
237
+ - Simple and straightforward
238
+ - Direct file system access
239
+
240
+ **Note:** Consider migrating to base64 encoded method for future compatibility (see Method 2 below)
241
+
242
+ #### 2. Base64 Encoded Method (`excel_metadata`) - **RECOMMENDED**
243
+
244
+ **Use case:** Web frontends, APIs, and cloud integrations where files are transmitted as encoded data.
245
+
246
+ Send Excel file as base64-encoded data with original filename:
247
+
248
+ ```json
249
+ {
250
+ "excel_metadata": {
251
+ "data": "UEsDBBQABgAIAAAAIQDd4Z...", // base64 encoded Excel file
252
+ "filename": "metadata.xlsx"
253
+ }
254
+ }
255
+ ```
256
+
257
+ **Advantages:**
258
+ - No intermediate file storage required
259
+ - Perfect for web upload forms
260
+ - API-friendly JSON payload
261
+ - Automatic temporary file cleanup
262
+ - **This is the recommended method going forward**
263
+
264
+ **Python Example:**
265
+ ```python
266
+ import base64
267
+
268
+ # Read Excel file and encode to base64
269
+ with open("metadata.xlsx", "rb") as f:
270
+ excel_bytes = f.read()
271
+ encoded_excel = base64.b64encode(excel_bytes).decode("utf-8")
272
+
273
+ # Use in upload parameters
274
+ upload_params = {
275
+ "name": "Web Upload",
276
+ "path": "/data/files",
277
+ "storage": 1,
278
+ "data_collection": 5,
279
+ "excel_metadata": {
280
+ "data": encoded_excel,
281
+ "filename": "metadata.xlsx"
282
+ }
283
+ }
284
+ ```
285
+
286
+ :::warning Important
287
+ You **cannot** use both `excel_metadata_path` and `excel_metadata` at the same time. Choose the method that best fits your use case:
288
+ - Use `excel_metadata_path` for server-side files (will be deprecated in future versions)
289
+ - Use `excel_metadata` for all use cases (recommended for new implementations)
290
+ :::
291
+
292
+ ### Future-Proof Migration Example
293
+
294
+ For new implementations, we recommend using `excel_metadata`. Here's how to migrate:
295
+
296
+ ```python
297
+ import base64
298
+
299
+ # Current approach (will be deprecated in future):
300
+ upload_params = {
301
+ "name": "My Upload",
302
+ "path": "/data/files",
303
+ "storage": 1,
304
+ "data_collection": 5,
305
+ "excel_metadata_path": "/data/metadata.xlsx" # Will be deprecated
306
+ }
307
+
308
+ # Recommended approach for new implementations:
309
+ with open("/data/metadata.xlsx", "rb") as f:
310
+ excel_bytes = f.read()
311
+ encoded_excel = base64.b64encode(excel_bytes).decode("utf-8")
312
+
313
+ upload_params = {
314
+ "name": "My Upload",
315
+ "path": "/data/files",
316
+ "storage": 1,
317
+ "data_collection": 5,
318
+ "excel_metadata": {
319
+ "data": encoded_excel,
320
+ "filename": "metadata.xlsx"
321
+ }
322
+ }
323
+ ```
324
+
325
+ ### Excel Format
326
+
327
+ Both header formats are supported (case-insensitive):
328
+
329
+ **Option 1: "filename" header**
330
+ | filename | category | description | custom_field |
331
+ |----------|----------|-------------|--------------|
332
+ | image1.jpg | nature | Mountain landscape | high_res |
333
+ | image2.png | urban | City skyline | processed |
334
+
335
+ **Option 2: "filename" header**
336
+ | file_name | category | description | custom_field |
337
+ |-----------|----------|-------------|--------------|
338
+ | image1.jpg | nature | Mountain landscape | high_res |
339
+ | image2.png | urban | City skyline | processed |
340
+
341
+ ### Filename Matching
342
+
343
+ The system uses a 5-tier priority matching algorithm:
344
+
345
+ 1. **Exact stem match** (highest priority): `image1` matches `image1.jpg`
346
+ 2. **Exact filename match**: `image1.jpg` matches `image1.jpg`
347
+ 3. **Metadata key stem match**: `path/image1.ext` stem matches `image1`
348
+ 4. **Partial path matching**: `/uploads/image1.jpg` contains `image1`
349
+ 5. **Full path matching**: Complete path matching for complex structures
350
+
351
+ ### Security Validation
352
+
353
+ Excel files undergo security validation:
354
+
355
+ ```python
356
+ # Default security limits
357
+ max_file_size_mb: 10 # File size limit
358
+ max_rows: 100000 # Row count limit
359
+ max_columns: 50 # Column count limit
360
+ ```
361
+
362
+ ### Configuration
363
+
364
+ Configure Excel security in `config.yaml`:
365
+
366
+ ```yaml
367
+ actions:
368
+ upload:
369
+ excel_config:
370
+ max_file_size_mb: 10
371
+ max_rows: 100000
372
+ max_columns: 50
373
+ ```
374
+
375
+ ## Progress Tracking
376
+
377
+ The upload action tracks progress across three main phases:
378
+
379
+ | Category | Proportion | Description |
380
+ | --------------------- | ---------- | ----------------------------------- |
381
+ | `analyze_collection` | 2% | Parameter validation and setup |
382
+ | `upload_data_files` | 38% | File upload processing |
383
+ | `generate_data_units` | 60% | Data unit creation and finalization |
384
+
385
+ ## Common Use Cases
386
+
387
+ ### 1. Simple Dataset Upload
388
+
389
+ ```json
390
+ {
391
+ "name": "Training Dataset",
392
+ "use_single_path": true,
393
+ "path": "/datasets/training",
394
+ "is_recursive": true,
395
+ "storage": 1,
396
+ "data_collection": 2
397
+ }
398
+ ```
399
+
400
+ ### 2. Multi-Source Sensor Data
401
+
402
+ ```json
403
+ {
404
+ "name": "Multi-Camera Dataset",
405
+ "use_single_path": false,
406
+ "assets": {
407
+ "front_camera": { "path": "/cameras/front", "is_recursive": true },
408
+ "rear_camera": { "path": "/cameras/rear", "is_recursive": true },
409
+ "lidar": { "path": "/sensors/lidar", "is_recursive": false }
410
+ },
411
+ "storage": 1,
412
+ "data_collection": 2
413
+ }
414
+ ```
415
+
416
+ ### 3. Dataset with Metadata (File Path)
417
+
418
+ ```json
419
+ {
420
+ "name": "Annotated Dataset",
421
+ "use_single_path": true,
422
+ "path": "/data/annotated",
423
+ "is_recursive": true,
424
+ "excel_metadata_path": "/data/metadata.xlsx",
425
+ "storage": 1,
426
+ "data_collection": 5
427
+ }
428
+ ```
429
+
430
+ ### 4. Dataset with Base64 Metadata (API/Web Use Case)
431
+
432
+ ```json
433
+ {
434
+ "name": "Web Upload with Metadata",
435
+ "use_single_path": true,
436
+ "path": "/data/uploads",
437
+ "is_recursive": true,
438
+ "excel_metadata": {
439
+ "data": "UEsDBBQABgAIAAAAIQDd4Zg...",
440
+ "filename": "metadata.xlsx"
441
+ },
442
+ "storage": 1,
443
+ "data_collection": 5
444
+ }
445
+ ```
446
+
447
+ **Python Example - Convert Excel to Base64:**
448
+
449
+ ```python
450
+ import base64
451
+
452
+ # Read Excel file and convert to base64
453
+ with open('metadata.xlsx', 'rb') as f:
454
+ excel_data = f.read()
455
+ encoded = base64.b64encode(excel_data).decode('utf-8')
456
+
457
+ # Use in upload params
458
+ params = {
459
+ "name": "Web Upload",
460
+ "path": "/data/uploads",
461
+ "excel_metadata": {
462
+ "data": encoded,
463
+ "filename": "metadata.xlsx"
464
+ },
465
+ "storage": 1,
466
+ "data_collection": 5
467
+ }
468
+ ```
469
+
470
+ ## Benefits
471
+
472
+ ### For Users
473
+
474
+ - **Flexibility**: Upload files from multiple different locations in a single operation
475
+ - **Granular Control**: Set recursive search per asset, not globally
476
+ - **Organization**: Map complex file structures to data collection specifications
477
+ - **Use Case Support**: Multi-sensor data collection, distributed datasets, heterogeneous sources
478
+
479
+ ### For Developers
480
+
481
+ - **Backward Compatible**: Existing code continues to work without changes
482
+ - **Type Safe**: Full Pydantic validation with clear error messages
483
+ - **Maintainable**: Clean separation between single-path and multi-path logic
484
+ - **Extensible**: Easy to add more per-asset configuration options in the future
485
+
486
+ ## Next Steps
487
+
488
+ - **For Plugin Developers**: See [BaseUploader Template Guide](./upload-plugin-template.md) for creating custom upload plugins with file processing logic
489
+ - **For SDK/Action Developers**: See [Upload Action Development](./upload-plugin-action.md) for architecture details, strategy patterns, and action internals
490
+
491
+ ## Migration Guide
492
+
493
+ ### From Legacy to Current Version
494
+
495
+ The upload action maintains 100% backward compatibility. The default behavior (`use_single_path=true`) works identically to the previous version.
496
+
497
+ #### No Migration Required
498
+
499
+ Existing configurations continue to work without changes:
500
+
501
+ ```python
502
+ # This legacy usage still works
503
+ params = {
504
+ "name": "My Upload",
505
+ "path": "/data/files",
506
+ "storage": 1,
507
+ "data_collection": 5
508
+ }
509
+ ```
510
+
511
+ #### Adopting Multi-Path Mode
512
+
513
+ To use the new multi-path functionality:
514
+
515
+ 1. Set `use_single_path: false`
516
+ 2. Remove the `path` field (it will be ignored)
517
+ 3. Add `assets` dictionary with per-asset configurations
518
+
519
+ ```python
520
+ # New multi-path mode
521
+ params = {
522
+ "name": "Multi-Source Upload",
523
+ "use_single_path": false,
524
+ "assets": {
525
+ "pcd_1": {"path": "/sensors/lidar", "is_recursive": false},
526
+ "image_1": {"path": "/cameras/front", "is_recursive": true}
527
+ },
528
+ "storage": 1,
529
+ "data_collection": 5
530
+ }
531
+ ```
532
+
533
+ ## Troubleshooting
534
+
535
+ ### Common Issues
536
+
537
+ #### "No Files Found" Error
538
+
539
+ ```bash
540
+ # Check path exists and is readable
541
+ ls -la /path/to/data
542
+ test -r /path/to/data && echo "Readable" || echo "Not readable"
543
+
544
+ # Verify files exist
545
+ find /path/to/data -name "*.jpg" | head -10
546
+ ```
547
+
548
+ #### Excel Processing Errors
549
+
550
+ ```bash
551
+ # Check file format and size
552
+ file /path/to/metadata.xlsx
553
+ ls -lh /path/to/metadata.xlsx
554
+ ```
555
+
556
+ #### Mode Validation Errors
557
+
558
+ - **Single path mode**: Ensure `path` is provided
559
+ - **Multi-path mode**: Ensure `assets` is provided with at least one asset configuration
560
+
561
+ ## Best Practices
562
+
563
+ ### Directory Organization
564
+
565
+ - Use clear, descriptive directory names
566
+ - Keep reasonable directory sizes (< 10,000 files per directory)
567
+ - Use absolute paths for reliability
568
+
569
+ ### Performance Optimization
570
+
571
+ - Enable recursive only when needed
572
+ - Keep Excel files under 5MB for best performance
573
+ - Organize files in balanced directory structures
574
+
575
+ ### Security Considerations
576
+
577
+ - Validate all paths before processing
578
+ - Use read-only permissions for source data
579
+ - Set appropriate Excel size limits
580
+
581
+ ## Support and Resources
582
+
583
+ - **Action Development Guide**: [Upload Plugin Action Development](./upload-plugin-action.md)
584
+ - **Template Development Guide**: [Upload Plugin Template Development](./upload-plugin-template.md)
585
+ - **API Reference**: See action development documentation for detailed API reference