karrio-cli 2025.5rc3__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.
Files changed (68) hide show
  1. karrio_cli/__init__.py +0 -0
  2. karrio_cli/__main__.py +105 -0
  3. karrio_cli/ai/README.md +335 -0
  4. karrio_cli/ai/__init__.py +0 -0
  5. karrio_cli/ai/commands.py +102 -0
  6. karrio_cli/ai/karrio_ai/__init__.py +1 -0
  7. karrio_cli/ai/karrio_ai/agent.py +972 -0
  8. karrio_cli/ai/karrio_ai/architecture/INTEGRATION_AGENT_PROMPT.md +497 -0
  9. karrio_cli/ai/karrio_ai/architecture/MAPPING_AGENT_PROMPT.md +355 -0
  10. karrio_cli/ai/karrio_ai/architecture/REAL_WORLD_TESTING.md +305 -0
  11. karrio_cli/ai/karrio_ai/architecture/SCHEMA_AGENT_PROMPT.md +183 -0
  12. karrio_cli/ai/karrio_ai/architecture/TESTING_AGENT_PROMPT.md +448 -0
  13. karrio_cli/ai/karrio_ai/architecture/TESTING_GUIDE.md +271 -0
  14. karrio_cli/ai/karrio_ai/enhanced_tools.py +943 -0
  15. karrio_cli/ai/karrio_ai/rag_system.py +503 -0
  16. karrio_cli/ai/karrio_ai/tests/test_agent.py +350 -0
  17. karrio_cli/ai/karrio_ai/tests/test_real_integration.py +360 -0
  18. karrio_cli/ai/karrio_ai/tests/test_real_world_scenarios.py +513 -0
  19. karrio_cli/commands/__init__.py +0 -0
  20. karrio_cli/commands/codegen.py +336 -0
  21. karrio_cli/commands/login.py +139 -0
  22. karrio_cli/commands/plugins.py +168 -0
  23. karrio_cli/commands/sdk.py +870 -0
  24. karrio_cli/common/queries.py +101 -0
  25. karrio_cli/common/utils.py +368 -0
  26. karrio_cli/resources/__init__.py +0 -0
  27. karrio_cli/resources/carriers.py +91 -0
  28. karrio_cli/resources/connections.py +207 -0
  29. karrio_cli/resources/events.py +151 -0
  30. karrio_cli/resources/logs.py +151 -0
  31. karrio_cli/resources/orders.py +144 -0
  32. karrio_cli/resources/shipments.py +210 -0
  33. karrio_cli/resources/trackers.py +287 -0
  34. karrio_cli/templates/__init__.py +9 -0
  35. karrio_cli/templates/__pycache__/__init__.cpython-311.pyc +0 -0
  36. karrio_cli/templates/__pycache__/__init__.cpython-312.pyc +0 -0
  37. karrio_cli/templates/__pycache__/address.cpython-311.pyc +0 -0
  38. karrio_cli/templates/__pycache__/address.cpython-312.pyc +0 -0
  39. karrio_cli/templates/__pycache__/docs.cpython-311.pyc +0 -0
  40. karrio_cli/templates/__pycache__/docs.cpython-312.pyc +0 -0
  41. karrio_cli/templates/__pycache__/documents.cpython-311.pyc +0 -0
  42. karrio_cli/templates/__pycache__/documents.cpython-312.pyc +0 -0
  43. karrio_cli/templates/__pycache__/manifest.cpython-311.pyc +0 -0
  44. karrio_cli/templates/__pycache__/manifest.cpython-312.pyc +0 -0
  45. karrio_cli/templates/__pycache__/pickup.cpython-311.pyc +0 -0
  46. karrio_cli/templates/__pycache__/pickup.cpython-312.pyc +0 -0
  47. karrio_cli/templates/__pycache__/rates.cpython-311.pyc +0 -0
  48. karrio_cli/templates/__pycache__/rates.cpython-312.pyc +0 -0
  49. karrio_cli/templates/__pycache__/sdk.cpython-311.pyc +0 -0
  50. karrio_cli/templates/__pycache__/sdk.cpython-312.pyc +0 -0
  51. karrio_cli/templates/__pycache__/shipments.cpython-311.pyc +0 -0
  52. karrio_cli/templates/__pycache__/shipments.cpython-312.pyc +0 -0
  53. karrio_cli/templates/__pycache__/tracking.cpython-311.pyc +0 -0
  54. karrio_cli/templates/__pycache__/tracking.cpython-312.pyc +0 -0
  55. karrio_cli/templates/address.py +308 -0
  56. karrio_cli/templates/docs.py +150 -0
  57. karrio_cli/templates/documents.py +428 -0
  58. karrio_cli/templates/manifest.py +396 -0
  59. karrio_cli/templates/pickup.py +839 -0
  60. karrio_cli/templates/rates.py +638 -0
  61. karrio_cli/templates/sdk.py +947 -0
  62. karrio_cli/templates/shipments.py +892 -0
  63. karrio_cli/templates/tracking.py +437 -0
  64. karrio_cli-2025.5rc3.dist-info/METADATA +165 -0
  65. karrio_cli-2025.5rc3.dist-info/RECORD +68 -0
  66. karrio_cli-2025.5rc3.dist-info/WHEEL +5 -0
  67. karrio_cli-2025.5rc3.dist-info/entry_points.txt +2 -0
  68. karrio_cli-2025.5rc3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,428 @@
1
+ from jinja2 import Template
2
+
3
+ PROVIDER_DOCUMENT_UPLOAD_TEMPLATE = Template(
4
+ '''"""Karrio {{name}} document upload API implementation."""
5
+
6
+ # IMPLEMENTATION INSTRUCTIONS:
7
+ # 1. Uncomment the imports when the schema types are generated
8
+ # 2. Import the specific request and response types you need
9
+ # 3. Create a request instance with the appropriate request type
10
+ # 4. Extract document details from the response
11
+
12
+ import typing
13
+ import base64
14
+ import karrio.lib as lib
15
+ import karrio.core.models as models
16
+ import karrio.providers.{{id}}.error as error
17
+ import karrio.providers.{{id}}.utils as provider_utils
18
+ import karrio.providers.{{id}}.units as provider_units
19
+
20
+
21
+ def parse_document_upload_response(
22
+ _response: lib.Deserializable[{% if is_xml_api %}lib.Element{% else %}dict{% endif %}],
23
+ settings: provider_utils.Settings,
24
+ ) -> typing.Tuple[models.DocumentUploadDetails, typing.List[models.Message]]:
25
+ """
26
+ Parse document upload response from carrier API
27
+
28
+ _response: The carrier response to deserialize
29
+ settings: The carrier connection settings
30
+
31
+ Returns a tuple with (DocumentUploadDetails, List[Message])
32
+ """
33
+ response = _response.deserialize()
34
+ messages = error.parse_error_response(response, settings)
35
+ details = _extract_details(response, settings)
36
+
37
+ return details, messages
38
+
39
+
40
+ def _extract_details(
41
+ data: {% if is_xml_api %}lib.Element{% else %}dict{% endif %},
42
+ settings: provider_utils.Settings,
43
+ ) -> models.DocumentUploadDetails:
44
+ """
45
+ Extract document upload details from carrier response data
46
+
47
+ data: The carrier-specific document upload response data
48
+ settings: The carrier connection settings
49
+
50
+ Returns a DocumentUploadDetails object with the uploaded document information
51
+ """
52
+ {% if is_xml_api %}
53
+ # Example implementation for XML response:
54
+ # Extract document IDs and file names from the response
55
+ # documents = []
56
+ # doc_elements = lib.find_element("document", data)
57
+ # for doc_element in doc_elements:
58
+ # doc_id = lib.find_element("id", doc_element, first=True).text
59
+ # file_name = lib.find_element("file-name", doc_element, first=True).text
60
+ # documents.append({"document_id": doc_id, "file_name": file_name})
61
+
62
+ # For development, return sample data
63
+ documents = [{"document_id": "doc_123456", "file_name": "invoice.pdf"}]
64
+ {% else %}
65
+ # Example implementation for JSON response:
66
+ # documents = []
67
+ # doc_data = data.get("documents", [])
68
+ # for doc in doc_data:
69
+ # documents.append({
70
+ # "document_id": doc.get("id"),
71
+ # "file_name": doc.get("fileName")
72
+ # })
73
+
74
+ # For development, return sample data
75
+ documents = [{"document_id": "doc_123456", "file_name": "invoice.pdf"}]
76
+ {% endif %}
77
+
78
+ return models.DocumentUploadDetails(
79
+ carrier_id=settings.carrier_id,
80
+ carrier_name=settings.carrier_name,
81
+ documents=[
82
+ models.DocumentDetails(
83
+ document_id=doc["document_id"],
84
+ file_name=doc["file_name"],
85
+ )
86
+ for doc in documents
87
+ ],
88
+ meta=dict(
89
+ # Additional carrier-specific metadata
90
+ upload_timestamp="2023-07-01T12:00:00Z"
91
+ ),
92
+ )
93
+
94
+
95
+ def document_upload_request(
96
+ payload: models.DocumentUploadRequest,
97
+ settings: provider_utils.Settings,
98
+ ) -> lib.Serializable:
99
+ """
100
+ Create a document upload request for the carrier API
101
+
102
+ payload: The standardized DocumentUploadRequest from karrio
103
+ settings: The carrier connection settings
104
+
105
+ Returns a Serializable object that can be sent to the carrier API
106
+ """
107
+ # Extract document files from the payload
108
+ documents = payload.document_files
109
+
110
+ {% if is_xml_api %}
111
+ # Example implementation for XML document upload request:
112
+ # import karrio.schemas.{{id}}.document_upload_request as {{id}}_req
113
+ #
114
+ # doc_list = []
115
+ # for doc in documents:
116
+ # doc_list.append({{id}}_req.Document(
117
+ # file_name=doc.get("doc_name", ""),
118
+ # file_format=doc.get("doc_format", "PDF"),
119
+ # document_type=doc.get("doc_type", "invoice"),
120
+ # file_content=doc.get("doc_file", "")
121
+ # ))
122
+ #
123
+ # request = {{id}}_req.DocumentUploadRequest(
124
+ # account_number=settings.account_number,
125
+ # documents=doc_list
126
+ # )
127
+ #
128
+ # return lib.Serializable(
129
+ # request,
130
+ # lambda _: lib.to_xml(
131
+ # _,
132
+ # name_="DocumentUploadRequest",
133
+ # namespacedef_='xmlns="http://{{id}}.com/schema/document/upload"'
134
+ # )
135
+ # )
136
+
137
+ # For development, return a simple XML request
138
+ document_content = next((doc.get("doc_file", "") for doc in documents), "")
139
+ document_name = next((doc.get("doc_name", "document.pdf") for doc in documents), "")
140
+ document_type = next((doc.get("doc_type", "invoice") for doc in documents), "")
141
+ document_format = next((doc.get("doc_format", "PDF") for doc in documents), "")
142
+
143
+ request = f"""<?xml version="1.0"?>
144
+ <document-upload-request>
145
+ <account-number>{settings.account_number}</account-number>
146
+ <document>
147
+ <file-name>{document_name}</file-name>
148
+ <file-format>{document_format}</file-format>
149
+ <document-type>{document_type}</document-type>
150
+ <file-content>{document_content}</file-content>
151
+ </document>
152
+ </document-upload-request>"""
153
+
154
+ return lib.Serializable(request, lambda r: r)
155
+ {% else %}
156
+ # Example implementation for JSON document upload request:
157
+ # import karrio.schemas.{{id}}.document_upload_request as {{id}}_req
158
+ #
159
+ # doc_list = []
160
+ # for doc in documents:
161
+ # doc_list.append({
162
+ # "fileName": doc.get("doc_name", ""),
163
+ # "fileFormat": doc.get("doc_format", "PDF"),
164
+ # "documentType": doc.get("doc_type", "invoice"),
165
+ # "fileContent": doc.get("doc_file", "")
166
+ # })
167
+ #
168
+ # request = {{id}}_req.DocumentUploadRequestType(
169
+ # accountNumber=settings.account_number,
170
+ # documents=doc_list
171
+ # )
172
+ #
173
+ # return lib.Serializable(request, lib.to_dict)
174
+
175
+ # For development, return a simple JSON request
176
+ doc_list = []
177
+ for doc in documents:
178
+ doc_list.append({
179
+ "fileName": doc.get("doc_name", ""),
180
+ "fileFormat": doc.get("doc_format", "PDF"),
181
+ "documentType": doc.get("doc_type", "invoice"),
182
+ "fileContent": doc.get("doc_file", "")
183
+ })
184
+
185
+ request = {
186
+ "accountNumber": settings.account_number,
187
+ "documents": doc_list
188
+ }
189
+
190
+ return lib.Serializable(request, lib.to_dict)
191
+ {% endif %}
192
+ '''
193
+ )
194
+
195
+ # Provider document upload template
196
+ PROVIDER_DOCUMENT_UPLOAD_TEMPLATE = Template(
197
+ '''"""Karrio {{name}} document upload API implementation."""
198
+ import attr
199
+ from typing import List, Dict, Any, Optional
200
+ from base64 import b64encode
201
+ from karrio.core.models import (
202
+ Message,
203
+ CheckoutResponse,
204
+ DocumentModels,
205
+ )
206
+ from karrio.core.errors import UploadDocumentError
207
+ from karrio.providers.{{id}}.utils import Settings
208
+ from karrio.providers.{{id}}.error import parse_error_response
209
+
210
+
211
+ def upload_document(
212
+ documents: List[DocumentModels.Document],
213
+ settings: Settings,
214
+ ) -> CheckoutResponse:
215
+ """Upload documents to carrier's API
216
+ Parameters:
217
+ documents: List of document to upload
218
+ settings: carrier connection settings
219
+
220
+ Returns:
221
+ upload document checkout response
222
+ """
223
+ response = CheckoutResponse(messages=[], documents=[])
224
+
225
+ try:
226
+ # Implement carrier-specific document upload logic here
227
+ # For example:
228
+ # client = create_client(settings)
229
+ # for document in documents:
230
+ # result = client.upload_document(document)
231
+ # if result.successful:
232
+ # response.documents.append(
233
+ # DocumentModels.Document(
234
+ # id=result.id,
235
+ # type=document.type,
236
+ # name=document.name,
237
+ # )
238
+ # )
239
+ # else:
240
+ # response.messages.append(Message(code="error", message=result.error))
241
+
242
+ # Placeholder implementation
243
+ for document in documents:
244
+ reference_id = f"DOC-{document.name[:8]}-{document.type[:3]}"
245
+ response.documents.append(
246
+ DocumentModels.Document(
247
+ id=reference_id,
248
+ type=document.type,
249
+ name=document.name,
250
+ )
251
+ )
252
+ response.messages.append(
253
+ Message(
254
+ code="success",
255
+ message=f"Document {document.name} uploaded successfully",
256
+ details=f"Document ID: {reference_id}",
257
+ )
258
+ )
259
+
260
+ except Exception as e:
261
+ error_response = parse_error_response(response, e)
262
+ response.messages.append(
263
+ Message(
264
+ code="upload_document_error",
265
+ message=str(error_response),
266
+ carrier_name="{{id}}",
267
+ carrier_id="{{id}}",
268
+ )
269
+ )
270
+
271
+ return response
272
+ '''
273
+ )
274
+
275
+ # Test document upload template
276
+ TEST_DOCUMENT_UPLOAD_TEMPLATE = Template(
277
+ '''import unittest
278
+ from unittest.mock import patch, ANY
279
+ import karrio.core
280
+ from karrio.core.models import DocumentModels, CheckoutResponse
281
+ from .fixture import gateway
282
+ import logging
283
+
284
+ logger = logging.getLogger(__name__)
285
+
286
+ class TestDocumentUpload(unittest.TestCase):
287
+ def setUp(self):
288
+ self.maxDiff = None
289
+ self.settings = gateway.settings
290
+
291
+ # Test document
292
+ self.document = DocumentModels.Document(
293
+ type="COMMERCIAL_INVOICE",
294
+ name="invoice.pdf",
295
+ content="SGVsbG8gV29ybGQh",
296
+ format="PDF",
297
+ )
298
+
299
+ def test_document_upload(self):
300
+ with patch('karrio.providers.{{id}}.document.upload_document') as mock:
301
+ mock.return_value = CheckoutResponse(
302
+ messages=[],
303
+ documents=[DocumentModels.Document(
304
+ id="DOC123456",
305
+ type="COMMERCIAL_INVOICE",
306
+ name="invoice.pdf",
307
+ )]
308
+ )
309
+
310
+ # Check the function is called with expected parameters
311
+ response = karrio.core.checkout.upload_document(
312
+ documents=[self.document],
313
+ settings=self.settings
314
+ )
315
+
316
+ mock.assert_called_once_with([self.document], self.settings)
317
+ self.assertEqual(len(response.documents), 1)
318
+ '''
319
+ )
320
+
321
+
322
+ XML_SCHEMA_DOCUMENT_UPLOAD_REQUEST_TEMPLATE = Template("""<?xml version="1.0"?>
323
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://{{id}}.com/ws/document-upload-request" xmlns="http://{{id}}.com/ws/document-upload-request" elementFormDefault="qualified">
324
+ <xsd:element name="document-upload-request">
325
+ <xsd:complexType>
326
+ <xsd:all>
327
+ <xsd:element name="account-number" type="xsd:string" minOccurs="0" />
328
+ <xsd:element name="documents">
329
+ <xsd:complexType>
330
+ <xsd:sequence>
331
+ <xsd:element name="document" maxOccurs="unbounded">
332
+ <xsd:complexType>
333
+ <xsd:all>
334
+ <xsd:element name="document-type" type="xsd:string" />
335
+ <xsd:element name="document-name" type="xsd:string" />
336
+ <xsd:element name="document-format" type="xsd:string" />
337
+ <xsd:element name="document-content" type="xsd:base64Binary" />
338
+ <xsd:element name="reference" type="xsd:string" minOccurs="0" />
339
+ </xsd:all>
340
+ </xsd:complexType>
341
+ </xsd:element>
342
+ </xsd:sequence>
343
+ </xsd:complexType>
344
+ </xsd:element>
345
+ </xsd:all>
346
+ </xsd:complexType>
347
+ </xsd:element>
348
+ </xsd:schema>
349
+ """
350
+ )
351
+
352
+ XML_SCHEMA_DOCUMENT_UPLOAD_RESPONSE_TEMPLATE = Template("""<?xml version="1.0"?>
353
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://{{id}}.com/ws/document-upload-response" xmlns="http://{{id}}.com/ws/document-upload-response" elementFormDefault="qualified">
354
+ <xsd:element name="document-upload-response">
355
+ <xsd:complexType>
356
+ <xsd:all>
357
+ <xsd:element name="status" type="xsd:string" />
358
+ <xsd:element name="documents" minOccurs="0">
359
+ <xsd:complexType>
360
+ <xsd:sequence>
361
+ <xsd:element name="document" maxOccurs="unbounded">
362
+ <xsd:complexType>
363
+ <xsd:all>
364
+ <xsd:element name="document-id" type="xsd:string" />
365
+ <xsd:element name="document-name" type="xsd:string" minOccurs="0" />
366
+ <xsd:element name="status" type="xsd:string" minOccurs="0" />
367
+ <xsd:element name="reference" type="xsd:string" minOccurs="0" />
368
+ </xsd:all>
369
+ </xsd:complexType>
370
+ </xsd:element>
371
+ </xsd:sequence>
372
+ </xsd:complexType>
373
+ </xsd:element>
374
+ </xsd:all>
375
+ </xsd:complexType>
376
+ </xsd:element>
377
+ </xsd:schema>
378
+ """
379
+ )
380
+
381
+ # JSON schema templates for document upload operations
382
+ JSON_SCHEMA_DOCUMENT_UPLOAD_REQUEST_TEMPLATE = Template(
383
+ """{
384
+ "documentUploadRequest": {
385
+ "accountNumber": "123456",
386
+ "documents": [
387
+ {
388
+ "documentType": "INVOICE",
389
+ "documentName": "invoice.pdf",
390
+ "documentFormat": "PDF",
391
+ "documentContent": "base64_encoded_document_data",
392
+ "reference": "REF123456"
393
+ },
394
+ {
395
+ "documentType": "COMMERCIAL_INVOICE",
396
+ "documentName": "commercial_invoice.pdf",
397
+ "documentFormat": "PDF",
398
+ "documentContent": "base64_encoded_document_data",
399
+ "reference": "REF789012"
400
+ }
401
+ ]
402
+ }
403
+ }
404
+ """
405
+ )
406
+
407
+ JSON_SCHEMA_DOCUMENT_UPLOAD_RESPONSE_TEMPLATE = Template(
408
+ """{
409
+ "documentUploadResponse": {
410
+ "status": "completed",
411
+ "documents": [
412
+ {
413
+ "documentId": "DOC123456",
414
+ "documentName": "invoice.pdf",
415
+ "status": "uploaded",
416
+ "reference": "REF123456"
417
+ },
418
+ {
419
+ "documentId": "DOC789012",
420
+ "documentName": "commercial_invoice.pdf",
421
+ "status": "uploaded",
422
+ "reference": "REF789012"
423
+ }
424
+ ]
425
+ }
426
+ }
427
+ """
428
+ )