cap-sdk-python 1.0.6__tar.gz → 2.0.0__tar.gz
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.
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/PKG-INFO +2 -2
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/README.md +1 -1
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/client.py +11 -1
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/buspacket_pb2.py +2 -2
- cap_sdk_python-2.0.0/cap/pb/cortex/agent/v1/job_pb2.py +55 -0
- cap_sdk_python-2.0.0/cap/pb/cortex/agent/v1/safety_pb2.py +48 -0
- cap_sdk_python-2.0.0/cap/worker.py +77 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap_sdk_python.egg-info/PKG-INFO +2 -2
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap_sdk_python.egg-info/SOURCES.txt +2 -1
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap_sdk_python.egg-info/top_level.txt +1 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/pyproject.toml +1 -1
- cap_sdk_python-2.0.0/tests/test_sdk.py +103 -0
- cap_sdk_python-1.0.6/cap/pb/cortex/agent/v1/job_pb2.py +0 -47
- cap_sdk_python-1.0.6/cap/pb/cortex/agent/v1/safety_pb2.py +0 -44
- cap_sdk_python-1.0.6/cap/worker.py +0 -45
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/__init__.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/bus.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/__init__.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/__init__.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/__init__.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/__init__.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/alert_pb2.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/alert_pb2_grpc.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/buspacket_pb2_grpc.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/heartbeat_pb2.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/heartbeat_pb2_grpc.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/job_pb2_grpc.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap/pb/cortex/agent/v1/safety_pb2_grpc.py +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap_sdk_python.egg-info/dependency_links.txt +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/cap_sdk_python.egg-info/requires.txt +0 -0
- {cap_sdk_python-1.0.6 → cap_sdk_python-2.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cap-sdk-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: CAP (Cortex Agent Protocol) Python SDK
|
|
5
5
|
Project-URL: Homepage, https://github.com/coretexos/cap
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -22,7 +22,7 @@ Asyncio-first SDK with NATS helpers for CAP workers and clients.
|
|
|
22
22
|
--grpc_python_out=./cap/pb \
|
|
23
23
|
../../proto/cortex/agent/v1/*.proto
|
|
24
24
|
```
|
|
25
|
-
(Or run `./tools/make_protos.sh` from repo root and copy
|
|
25
|
+
(Or run `./tools/make_protos.sh` from repo root with `CAP_RUN_PY=1` and copy `/python` into `sdk/python/cap/pb` if you want vendored stubs.)
|
|
26
26
|
|
|
27
27
|
2. Install:
|
|
28
28
|
```bash
|
|
@@ -11,7 +11,7 @@ Asyncio-first SDK with NATS helpers for CAP workers and clients.
|
|
|
11
11
|
--grpc_python_out=./cap/pb \
|
|
12
12
|
../../proto/cortex/agent/v1/*.proto
|
|
13
13
|
```
|
|
14
|
-
(Or run `./tools/make_protos.sh` from repo root and copy
|
|
14
|
+
(Or run `./tools/make_protos.sh` from repo root with `CAP_RUN_PY=1` and copy `/python` into `sdk/python/cap/pb` if you want vendored stubs.)
|
|
15
15
|
|
|
16
16
|
2. Install:
|
|
17
17
|
```bash
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import nats
|
|
1
2
|
from google.protobuf import timestamp_pb2
|
|
2
3
|
from cap.pb.cortex.agent.v1 import buspacket_pb2
|
|
4
|
+
from cryptography.hazmat.primitives.asymmetric import ec
|
|
5
|
+
from cryptography.hazmat.primitives import hashes
|
|
6
|
+
import hashlib
|
|
3
7
|
|
|
4
8
|
|
|
5
9
|
DEFAULT_PROTOCOL_VERSION = 1
|
|
6
10
|
SUBJECT_SUBMIT = "sys.job.submit"
|
|
7
11
|
|
|
8
12
|
|
|
9
|
-
async def submit_job(nc, job_request, trace_id: str, sender_id: str):
|
|
13
|
+
async def submit_job(nc, job_request, trace_id: str, sender_id: str, private_key: ec.EllipticCurvePrivateKey):
|
|
10
14
|
ts = timestamp_pb2.Timestamp()
|
|
11
15
|
ts.GetCurrentTime()
|
|
12
16
|
packet = buspacket_pb2.BusPacket()
|
|
@@ -15,4 +19,10 @@ async def submit_job(nc, job_request, trace_id: str, sender_id: str):
|
|
|
15
19
|
packet.created_at.CopyFrom(ts)
|
|
16
20
|
packet.protocol_version = DEFAULT_PROTOCOL_VERSION
|
|
17
21
|
packet.job_request.CopyFrom(job_request)
|
|
22
|
+
|
|
23
|
+
unsigned_data = packet.SerializeToString()
|
|
24
|
+
digest = hashlib.sha256(unsigned_data).digest()
|
|
25
|
+
signature = private_key.sign(digest, ec.ECDSA(hashes.SHA256()))
|
|
26
|
+
packet.signature = signature
|
|
27
|
+
|
|
18
28
|
await nc.publish(SUBJECT_SUBMIT, packet.SerializeToString())
|
|
@@ -28,7 +28,7 @@ from cortex.agent.v1 import heartbeat_pb2 as cortex_dot_agent_dot_v1_dot_heartbe
|
|
|
28
28
|
from cortex.agent.v1 import alert_pb2 as cortex_dot_agent_dot_v1_dot_alert__pb2
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1f\x63ortex/agent/v1/buspacket.proto\x12\x0f\x63ortex.agent.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x19\x63ortex/agent/v1/job.proto\x1a\x1f\x63ortex/agent/v1/heartbeat.proto\x1a\x1b\x63ortex/agent/v1/alert.proto\"\
|
|
31
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1f\x63ortex/agent/v1/buspacket.proto\x12\x0f\x63ortex.agent.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x19\x63ortex/agent/v1/job.proto\x1a\x1f\x63ortex/agent/v1/heartbeat.proto\x1a\x1b\x63ortex/agent/v1/alert.proto\"\xde\x02\n\tBusPacket\x12\x10\n\x08trace_id\x18\x01 \x01(\t\x12\x11\n\tsender_id\x18\x02 \x01(\t\x12.\n\ncreated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10protocol_version\x18\x04 \x01(\x05\x12\x32\n\x0bjob_request\x18\n \x01(\x0b\x32\x1b.cortex.agent.v1.JobRequestH\x00\x12\x30\n\njob_result\x18\x0b \x01(\x0b\x32\x1a.cortex.agent.v1.JobResultH\x00\x12/\n\theartbeat\x18\x0c \x01(\x0b\x32\x1a.cortex.agent.v1.HeartbeatH\x00\x12-\n\x05\x61lert\x18\r \x01(\x0b\x32\x1c.cortex.agent.v1.SystemAlertH\x00\x12\x11\n\tsignature\x18\x0e \x01(\x0c\x42\t\n\x07payloadB\x7f\n\x16\x61i.cortex.cap.agent.v1P\x01Z+github.com/coretexos/cap/go/cortex/agent/v1\xaa\x02\x0f\x43ortex.Agent.V1\xca\x02\x0f\x43ortex\\Agent\\V1\xea\x02\x11\x43ortex::Agent::V1b\x06proto3')
|
|
32
32
|
|
|
33
33
|
_globals = globals()
|
|
34
34
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -37,5 +37,5 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
|
37
37
|
_globals['DESCRIPTOR']._loaded_options = None
|
|
38
38
|
_globals['DESCRIPTOR']._serialized_options = b'\n\026ai.cortex.cap.agent.v1P\001Z+github.com/coretexos/cap/go/cortex/agent/v1\252\002\017Cortex.Agent.V1\312\002\017Cortex\\Agent\\V1\352\002\021Cortex::Agent::V1'
|
|
39
39
|
_globals['_BUSPACKET']._serialized_start=175
|
|
40
|
-
_globals['_BUSPACKET']._serialized_end=
|
|
40
|
+
_globals['_BUSPACKET']._serialized_end=525
|
|
41
41
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: cortex/agent/v1/job.proto
|
|
5
|
+
# Protobuf Python Version: 6.31.1
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
6,
|
|
15
|
+
31,
|
|
16
|
+
1,
|
|
17
|
+
'',
|
|
18
|
+
'cortex/agent/v1/job.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x63ortex/agent/v1/job.proto\x12\x0f\x63ortex.agent.v1\"l\n\x0c\x43ontextHints\x12\x18\n\x10max_input_tokens\x18\x01 \x01(\x05\x12\x1b\n\x13\x61llow_summarization\x18\x02 \x01(\x08\x12\x17\n\x0f\x61llow_retrieval\x18\x03 \x01(\x08\x12\x0c\n\x04tags\x18\x04 \x03(\t\"l\n\x06\x42udget\x12\x18\n\x10max_input_tokens\x18\x01 \x01(\x03\x12\x19\n\x11max_output_tokens\x18\x02 \x01(\x03\x12\x18\n\x10max_total_tokens\x18\x03 \x01(\x03\x12\x13\n\x0b\x64\x65\x61\x64line_ms\x18\x04 \x01(\x03\"\xa6\x04\n\nJobRequest\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12.\n\x08priority\x18\x03 \x01(\x0e\x32\x1c.cortex.agent.v1.JobPriority\x12\x13\n\x0b\x63ontext_ptr\x18\x04 \x01(\t\x12\x12\n\nadapter_id\x18\x05 \x01(\t\x12\x31\n\x03\x65nv\x18\x06 \x03(\x0b\x32$.cortex.agent.v1.JobRequest.EnvEntry\x12\x15\n\rparent_job_id\x18\x07 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x08 \x01(\t\x12\x12\n\nstep_index\x18\t \x01(\x05\x12\x11\n\tmemory_id\x18\n \x01(\t\x12\x34\n\rcontext_hints\x18\x0b \x01(\x0b\x32\x1d.cortex.agent.v1.ContextHints\x12\'\n\x06\x62udget\x18\x0c \x01(\x0b\x32\x17.cortex.agent.v1.Budget\x12\x11\n\ttenant_id\x18\r \x01(\t\x12\x14\n\x0cprincipal_id\x18\x0e \x01(\t\x12\x37\n\x06labels\x18\x0f \x03(\x0b\x32\'.cortex.agent.v1.JobRequest.LabelsEntry\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xaf\x01\n\tJobResult\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12*\n\x06status\x18\x02 \x01(\x0e\x32\x1a.cortex.agent.v1.JobStatus\x12\x12\n\nresult_ptr\x18\x03 \x01(\t\x12\x11\n\tworker_id\x18\x04 \x01(\t\x12\x14\n\x0c\x65xecution_ms\x18\x05 \x01(\x03\x12\x12\n\nerror_code\x18\x06 \x01(\t\x12\x15\n\rerror_message\x18\x07 \x01(\t*|\n\x0bJobPriority\x12\x1c\n\x18JOB_PRIORITY_UNSPECIFIED\x10\x00\x12\x1c\n\x18JOB_PRIORITY_INTERACTIVE\x10\x01\x12\x16\n\x12JOB_PRIORITY_BATCH\x10\x02\x12\x19\n\x15JOB_PRIORITY_CRITICAL\x10\x03*\x86\x02\n\tJobStatus\x12\x1a\n\x16JOB_STATUS_UNSPECIFIED\x10\x00\x12\x16\n\x12JOB_STATUS_PENDING\x10\x01\x12\x18\n\x14JOB_STATUS_SCHEDULED\x10\x02\x12\x19\n\x15JOB_STATUS_DISPATCHED\x10\x03\x12\x16\n\x12JOB_STATUS_RUNNING\x10\x04\x12\x18\n\x14JOB_STATUS_SUCCEEDED\x10\x05\x12\x15\n\x11JOB_STATUS_FAILED\x10\x06\x12\x18\n\x14JOB_STATUS_CANCELLED\x10\x07\x12\x15\n\x11JOB_STATUS_DENIED\x10\x08\x12\x16\n\x12JOB_STATUS_TIMEOUT\x10\tB\x7f\n\x16\x61i.cortex.cap.agent.v1P\x01Z+github.com/coretexos/cap/go/cortex/agent/v1\xaa\x02\x0f\x43ortex.Agent.V1\xca\x02\x0f\x43ortex\\Agent\\V1\xea\x02\x11\x43ortex::Agent::V1b\x06proto3')
|
|
28
|
+
|
|
29
|
+
_globals = globals()
|
|
30
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'cortex.agent.v1.job_pb2', _globals)
|
|
32
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
34
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n\026ai.cortex.cap.agent.v1P\001Z+github.com/coretexos/cap/go/cortex/agent/v1\252\002\017Cortex.Agent.V1\312\002\017Cortex\\Agent\\V1\352\002\021Cortex::Agent::V1'
|
|
35
|
+
_globals['_JOBREQUEST_ENVENTRY']._loaded_options = None
|
|
36
|
+
_globals['_JOBREQUEST_ENVENTRY']._serialized_options = b'8\001'
|
|
37
|
+
_globals['_JOBREQUEST_LABELSENTRY']._loaded_options = None
|
|
38
|
+
_globals['_JOBREQUEST_LABELSENTRY']._serialized_options = b'8\001'
|
|
39
|
+
_globals['_JOBPRIORITY']._serialized_start=997
|
|
40
|
+
_globals['_JOBPRIORITY']._serialized_end=1121
|
|
41
|
+
_globals['_JOBSTATUS']._serialized_start=1124
|
|
42
|
+
_globals['_JOBSTATUS']._serialized_end=1386
|
|
43
|
+
_globals['_CONTEXTHINTS']._serialized_start=46
|
|
44
|
+
_globals['_CONTEXTHINTS']._serialized_end=154
|
|
45
|
+
_globals['_BUDGET']._serialized_start=156
|
|
46
|
+
_globals['_BUDGET']._serialized_end=264
|
|
47
|
+
_globals['_JOBREQUEST']._serialized_start=267
|
|
48
|
+
_globals['_JOBREQUEST']._serialized_end=817
|
|
49
|
+
_globals['_JOBREQUEST_ENVENTRY']._serialized_start=728
|
|
50
|
+
_globals['_JOBREQUEST_ENVENTRY']._serialized_end=770
|
|
51
|
+
_globals['_JOBREQUEST_LABELSENTRY']._serialized_start=772
|
|
52
|
+
_globals['_JOBREQUEST_LABELSENTRY']._serialized_end=817
|
|
53
|
+
_globals['_JOBRESULT']._serialized_start=820
|
|
54
|
+
_globals['_JOBRESULT']._serialized_end=995
|
|
55
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: cortex/agent/v1/safety.proto
|
|
5
|
+
# Protobuf Python Version: 6.31.1
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
6,
|
|
15
|
+
31,
|
|
16
|
+
1,
|
|
17
|
+
'',
|
|
18
|
+
'cortex/agent/v1/safety.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
from cortex.agent.v1 import job_pb2 as cortex_dot_agent_dot_v1_dot_job__pb2
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x63ortex/agent/v1/safety.proto\x12\x0f\x63ortex.agent.v1\x1a\x19\x63ortex/agent/v1/job.proto\"\xcd\x02\n\x12PolicyCheckRequest\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x0e\n\x06tenant\x18\x03 \x01(\t\x12.\n\x08priority\x18\x04 \x01(\x0e\x32\x1c.cortex.agent.v1.JobPriority\x12\x16\n\x0e\x65stimated_cost\x18\x05 \x01(\x01\x12\'\n\x06\x62udget\x18\x06 \x01(\x0b\x32\x17.cortex.agent.v1.Budget\x12\x14\n\x0cprincipal_id\x18\x07 \x01(\t\x12?\n\x06labels\x18\x08 \x03(\x0b\x32/.cortex.agent.v1.PolicyCheckRequest.LabelsEntry\x12\x11\n\tmemory_id\x18\t \x01(\t\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"t\n\x13PolicyCheckResponse\x12/\n\x08\x64\x65\x63ision\x18\x01 \x01(\x0e\x32\x1d.cortex.agent.v1.DecisionType\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x1c\n\x14redacted_context_ptr\x18\x03 \x01(\t*\x9b\x01\n\x0c\x44\x65\x63isionType\x12\x1d\n\x19\x44\x45\x43ISION_TYPE_UNSPECIFIED\x10\x00\x12\x17\n\x13\x44\x45\x43ISION_TYPE_ALLOW\x10\x01\x12\x16\n\x12\x44\x45\x43ISION_TYPE_DENY\x10\x02\x12\x1f\n\x1b\x44\x45\x43ISION_TYPE_REQUIRE_HUMAN\x10\x03\x12\x1a\n\x16\x44\x45\x43ISION_TYPE_THROTTLE\x10\x04\x32\x62\n\x0cSafetyKernel\x12R\n\x05\x43heck\x12#.cortex.agent.v1.PolicyCheckRequest\x1a$.cortex.agent.v1.PolicyCheckResponseB\x7f\n\x16\x61i.cortex.cap.agent.v1P\x01Z+github.com/coretexos/cap/go/cortex/agent/v1\xaa\x02\x0f\x43ortex.Agent.V1\xca\x02\x0f\x43ortex\\Agent\\V1\xea\x02\x11\x43ortex::Agent::V1b\x06proto3')
|
|
29
|
+
|
|
30
|
+
_globals = globals()
|
|
31
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
32
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'cortex.agent.v1.safety_pb2', _globals)
|
|
33
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
34
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
35
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n\026ai.cortex.cap.agent.v1P\001Z+github.com/coretexos/cap/go/cortex/agent/v1\252\002\017Cortex.Agent.V1\312\002\017Cortex\\Agent\\V1\352\002\021Cortex::Agent::V1'
|
|
36
|
+
_globals['_POLICYCHECKREQUEST_LABELSENTRY']._loaded_options = None
|
|
37
|
+
_globals['_POLICYCHECKREQUEST_LABELSENTRY']._serialized_options = b'8\001'
|
|
38
|
+
_globals['_DECISIONTYPE']._serialized_start=531
|
|
39
|
+
_globals['_DECISIONTYPE']._serialized_end=686
|
|
40
|
+
_globals['_POLICYCHECKREQUEST']._serialized_start=77
|
|
41
|
+
_globals['_POLICYCHECKREQUEST']._serialized_end=410
|
|
42
|
+
_globals['_POLICYCHECKREQUEST_LABELSENTRY']._serialized_start=365
|
|
43
|
+
_globals['_POLICYCHECKREQUEST_LABELSENTRY']._serialized_end=410
|
|
44
|
+
_globals['_POLICYCHECKRESPONSE']._serialized_start=412
|
|
45
|
+
_globals['_POLICYCHECKRESPONSE']._serialized_end=528
|
|
46
|
+
_globals['_SAFETYKERNEL']._serialized_start=688
|
|
47
|
+
_globals['_SAFETYKERNEL']._serialized_end=786
|
|
48
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import Callable, Awaitable, Dict
|
|
3
|
+
|
|
4
|
+
import nats
|
|
5
|
+
from google.protobuf import timestamp_pb2
|
|
6
|
+
from cap.pb.cortex.agent.v1 import buspacket_pb2, job_pb2
|
|
7
|
+
from cryptography.hazmat.primitives.asymmetric import ec
|
|
8
|
+
from cryptography.hazmat.primitives import hashes
|
|
9
|
+
import hashlib
|
|
10
|
+
|
|
11
|
+
DEFAULT_PROTOCOL_VERSION = 1
|
|
12
|
+
SUBJECT_RESULT = "sys.job.result"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def run_worker(nats_url: str, subject: str, handler: Callable[[job_pb2.JobRequest], Awaitable[job_pb2.JobResult]],
|
|
16
|
+
public_keys: Dict[str, ec.EllipticCurvePublicKey] = None,
|
|
17
|
+
private_key: ec.EllipticCurvePrivateKey = None,
|
|
18
|
+
sender_id: str = "cap-worker",
|
|
19
|
+
connect_fn: Callable = nats.connect):
|
|
20
|
+
|
|
21
|
+
# Allow injection for tests; defaults to nats.connect.
|
|
22
|
+
nc = await connect_fn(servers=nats_url, name=sender_id)
|
|
23
|
+
|
|
24
|
+
async def on_msg(msg):
|
|
25
|
+
packet = buspacket_pb2.BusPacket()
|
|
26
|
+
packet.ParseFromString(msg.data)
|
|
27
|
+
|
|
28
|
+
if public_keys:
|
|
29
|
+
public_key = public_keys.get(packet.sender_id)
|
|
30
|
+
if not public_key:
|
|
31
|
+
print(f"worker: no public key found for sender: {packet.sender_id}")
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
signature = packet.signature
|
|
35
|
+
packet.ClearField("signature")
|
|
36
|
+
unsigned_data = packet.SerializeToString()
|
|
37
|
+
digest = hashlib.sha256(unsigned_data).digest()
|
|
38
|
+
try:
|
|
39
|
+
public_key.verify(signature, digest, ec.ECDSA(hashes.SHA256()))
|
|
40
|
+
except Exception:
|
|
41
|
+
print(f"worker: invalid signature from sender: {packet.sender_id}")
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
req = packet.job_request
|
|
45
|
+
if not req.job_id:
|
|
46
|
+
return
|
|
47
|
+
try:
|
|
48
|
+
res = await handler(req)
|
|
49
|
+
except Exception as exc: # noqa: BLE001
|
|
50
|
+
res = job_pb2.JobResult(
|
|
51
|
+
job_id=req.job_id,
|
|
52
|
+
status=job_pb2.JOB_STATUS_FAILED,
|
|
53
|
+
error_message=str(exc),
|
|
54
|
+
)
|
|
55
|
+
ts = timestamp_pb2.Timestamp()
|
|
56
|
+
ts.GetCurrentTime()
|
|
57
|
+
out = buspacket_pb2.BusPacket()
|
|
58
|
+
out.trace_id = packet.trace_id
|
|
59
|
+
out.sender_id = sender_id
|
|
60
|
+
out.protocol_version = DEFAULT_PROTOCOL_VERSION
|
|
61
|
+
out.created_at.CopyFrom(ts)
|
|
62
|
+
out.job_result.CopyFrom(res)
|
|
63
|
+
|
|
64
|
+
if private_key:
|
|
65
|
+
unsigned_data = out.SerializeToString()
|
|
66
|
+
digest = hashlib.sha256(unsigned_data).digest()
|
|
67
|
+
signature = private_key.sign(digest, ec.ECDSA(hashes.SHA256()))
|
|
68
|
+
out.signature = signature
|
|
69
|
+
|
|
70
|
+
await nc.publish(SUBJECT_RESULT, out.SerializeToString())
|
|
71
|
+
|
|
72
|
+
await nc.subscribe(subject, queue=subject, cb=on_msg)
|
|
73
|
+
try:
|
|
74
|
+
while True:
|
|
75
|
+
await asyncio.sleep(1)
|
|
76
|
+
finally:
|
|
77
|
+
await nc.drain()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cap-sdk-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: CAP (Cortex Agent Protocol) Python SDK
|
|
5
5
|
Project-URL: Homepage, https://github.com/coretexos/cap
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -22,7 +22,7 @@ Asyncio-first SDK with NATS helpers for CAP workers and clients.
|
|
|
22
22
|
--grpc_python_out=./cap/pb \
|
|
23
23
|
../../proto/cortex/agent/v1/*.proto
|
|
24
24
|
```
|
|
25
|
-
(Or run `./tools/make_protos.sh` from repo root and copy
|
|
25
|
+
(Or run `./tools/make_protos.sh` from repo root with `CAP_RUN_PY=1` and copy `/python` into `sdk/python/cap/pb` if you want vendored stubs.)
|
|
26
26
|
|
|
27
27
|
2. Install:
|
|
28
28
|
```bash
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import sys
|
|
3
|
+
import os
|
|
4
|
+
import unittest
|
|
5
|
+
from typing import Callable, Awaitable, Dict
|
|
6
|
+
|
|
7
|
+
# Avoid loading duplicate generated stubs from both /python and sdk/python/cap/pb.
|
|
8
|
+
sys.path = [p for p in sys.path if not p.rstrip("/").endswith("python")]
|
|
9
|
+
# Ensure generated modules under sdk/python/cap/pb are discoverable for `cortex.agent.v1.*`.
|
|
10
|
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "cap", "pb")))
|
|
11
|
+
|
|
12
|
+
from cryptography.hazmat.primitives.asymmetric import ec
|
|
13
|
+
from cryptography.hazmat.primitives import hashes
|
|
14
|
+
|
|
15
|
+
from cap.pb.cortex.agent.v1 import job_pb2
|
|
16
|
+
from cap import client
|
|
17
|
+
from cap import worker
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MockNATS:
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.subscriptions = {}
|
|
23
|
+
self.published = asyncio.Queue()
|
|
24
|
+
|
|
25
|
+
async def publish(self, subject, data):
|
|
26
|
+
await self.published.put((subject, data))
|
|
27
|
+
|
|
28
|
+
async def subscribe(self, subject, queue, cb):
|
|
29
|
+
self.subscriptions[subject] = cb
|
|
30
|
+
|
|
31
|
+
async def connect(self, servers, name):
|
|
32
|
+
return self
|
|
33
|
+
|
|
34
|
+
async def drain(self):
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TestSDK(unittest.TestCase):
|
|
39
|
+
def test_e2e(self):
|
|
40
|
+
async def run_test():
|
|
41
|
+
client_key = ec.generate_private_key(ec.SECP256R1())
|
|
42
|
+
worker_key = ec.generate_private_key(ec.SECP256R1())
|
|
43
|
+
|
|
44
|
+
mock_nats = MockNATS()
|
|
45
|
+
|
|
46
|
+
async def handler(req: job_pb2.JobRequest) -> job_pb2.JobResult:
|
|
47
|
+
return job_pb2.JobResult(status=job_pb2.JOB_STATUS_SUCCEEDED)
|
|
48
|
+
|
|
49
|
+
worker_task = asyncio.create_task(
|
|
50
|
+
worker.run_worker(
|
|
51
|
+
nats_url="",
|
|
52
|
+
subject="test.worker",
|
|
53
|
+
handler=handler,
|
|
54
|
+
public_keys={"test-client": client_key.public_key()},
|
|
55
|
+
private_key=worker_key,
|
|
56
|
+
sender_id="test-worker",
|
|
57
|
+
connect_fn=mock_nats.connect
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Wait until the worker subscription is registered on the mock bus.
|
|
62
|
+
for _ in range(20):
|
|
63
|
+
if "test.worker" in mock_nats.subscriptions:
|
|
64
|
+
break
|
|
65
|
+
await asyncio.sleep(0)
|
|
66
|
+
self.assertIn("test.worker", mock_nats.subscriptions)
|
|
67
|
+
|
|
68
|
+
job_request = job_pb2.JobRequest(job_id="test-job-1", topic="test.worker")
|
|
69
|
+
await client.submit_job(
|
|
70
|
+
mock_nats,
|
|
71
|
+
job_request,
|
|
72
|
+
"test-trace",
|
|
73
|
+
"test-client",
|
|
74
|
+
client_key
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Get the published job and send it to the worker
|
|
78
|
+
subj, data = await mock_nats.published.get()
|
|
79
|
+
self.assertEqual(subj, client.SUBJECT_SUBMIT)
|
|
80
|
+
await mock_nats.subscriptions["test.worker"](type("obj", (object,), {"data": data})())
|
|
81
|
+
|
|
82
|
+
# Get the result from the worker
|
|
83
|
+
subj, data = await mock_nats.published.get()
|
|
84
|
+
self.assertEqual(subj, worker.SUBJECT_RESULT)
|
|
85
|
+
|
|
86
|
+
# Verify the signature of the result
|
|
87
|
+
from cap.pb.cortex.agent.v1 import buspacket_pb2
|
|
88
|
+
import hashlib
|
|
89
|
+
result_packet = buspacket_pb2.BusPacket()
|
|
90
|
+
result_packet.ParseFromString(data)
|
|
91
|
+
signature = result_packet.signature
|
|
92
|
+
result_packet.ClearField("signature")
|
|
93
|
+
unsigned_data = result_packet.SerializeToString()
|
|
94
|
+
digest = hashlib.sha256(unsigned_data).digest()
|
|
95
|
+
worker_key.public_key().verify(signature, digest, ec.ECDSA(hashes.SHA256()))
|
|
96
|
+
|
|
97
|
+
worker_task.cancel()
|
|
98
|
+
|
|
99
|
+
asyncio.run(run_test())
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if __name__ == "__main__":
|
|
103
|
+
unittest.main()
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
-
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
-
# source: cortex/agent/v1/job.proto
|
|
5
|
-
# Protobuf Python Version: 6.31.1
|
|
6
|
-
"""Generated protocol buffer code."""
|
|
7
|
-
from google.protobuf import descriptor as _descriptor
|
|
8
|
-
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
-
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
-
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
-
from google.protobuf.internal import builder as _builder
|
|
12
|
-
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
-
_runtime_version.Domain.PUBLIC,
|
|
14
|
-
6,
|
|
15
|
-
31,
|
|
16
|
-
1,
|
|
17
|
-
'',
|
|
18
|
-
'cortex/agent/v1/job.proto'
|
|
19
|
-
)
|
|
20
|
-
# @@protoc_insertion_point(imports)
|
|
21
|
-
|
|
22
|
-
_sym_db = _symbol_database.Default()
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x63ortex/agent/v1/job.proto\x12\x0f\x63ortex.agent.v1\"\xa3\x02\n\nJobRequest\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12.\n\x08priority\x18\x03 \x01(\x0e\x32\x1c.cortex.agent.v1.JobPriority\x12\x13\n\x0b\x63ontext_ptr\x18\x04 \x01(\t\x12\x12\n\nadapter_id\x18\x05 \x01(\t\x12\x31\n\x03\x65nv\x18\x06 \x03(\x0b\x32$.cortex.agent.v1.JobRequest.EnvEntry\x12\x15\n\rparent_job_id\x18\x07 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x08 \x01(\t\x12\x12\n\nstep_index\x18\t \x01(\x05\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xaf\x01\n\tJobResult\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12*\n\x06status\x18\x02 \x01(\x0e\x32\x1a.cortex.agent.v1.JobStatus\x12\x12\n\nresult_ptr\x18\x03 \x01(\t\x12\x11\n\tworker_id\x18\x04 \x01(\t\x12\x14\n\x0c\x65xecution_ms\x18\x05 \x01(\x03\x12\x12\n\nerror_code\x18\x06 \x01(\t\x12\x15\n\rerror_message\x18\x07 \x01(\t*|\n\x0bJobPriority\x12\x1c\n\x18JOB_PRIORITY_UNSPECIFIED\x10\x00\x12\x1c\n\x18JOB_PRIORITY_INTERACTIVE\x10\x01\x12\x16\n\x12JOB_PRIORITY_BATCH\x10\x02\x12\x19\n\x15JOB_PRIORITY_CRITICAL\x10\x03*\x86\x02\n\tJobStatus\x12\x1a\n\x16JOB_STATUS_UNSPECIFIED\x10\x00\x12\x16\n\x12JOB_STATUS_PENDING\x10\x01\x12\x18\n\x14JOB_STATUS_SCHEDULED\x10\x02\x12\x19\n\x15JOB_STATUS_DISPATCHED\x10\x03\x12\x16\n\x12JOB_STATUS_RUNNING\x10\x04\x12\x18\n\x14JOB_STATUS_SUCCEEDED\x10\x05\x12\x15\n\x11JOB_STATUS_FAILED\x10\x06\x12\x18\n\x14JOB_STATUS_CANCELLED\x10\x07\x12\x15\n\x11JOB_STATUS_DENIED\x10\x08\x12\x16\n\x12JOB_STATUS_TIMEOUT\x10\tB\x7f\n\x16\x61i.cortex.cap.agent.v1P\x01Z+github.com/coretexos/cap/go/cortex/agent/v1\xaa\x02\x0f\x43ortex.Agent.V1\xca\x02\x0f\x43ortex\\Agent\\V1\xea\x02\x11\x43ortex::Agent::V1b\x06proto3')
|
|
28
|
-
|
|
29
|
-
_globals = globals()
|
|
30
|
-
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
-
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'cortex.agent.v1.job_pb2', _globals)
|
|
32
|
-
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
-
_globals['DESCRIPTOR']._loaded_options = None
|
|
34
|
-
_globals['DESCRIPTOR']._serialized_options = b'\n\026ai.cortex.cap.agent.v1P\001Z+github.com/coretexos/cap/go/cortex/agent/v1\252\002\017Cortex.Agent.V1\312\002\017Cortex\\Agent\\V1\352\002\021Cortex::Agent::V1'
|
|
35
|
-
_globals['_JOBREQUEST_ENVENTRY']._loaded_options = None
|
|
36
|
-
_globals['_JOBREQUEST_ENVENTRY']._serialized_options = b'8\001'
|
|
37
|
-
_globals['_JOBPRIORITY']._serialized_start=518
|
|
38
|
-
_globals['_JOBPRIORITY']._serialized_end=642
|
|
39
|
-
_globals['_JOBSTATUS']._serialized_start=645
|
|
40
|
-
_globals['_JOBSTATUS']._serialized_end=907
|
|
41
|
-
_globals['_JOBREQUEST']._serialized_start=47
|
|
42
|
-
_globals['_JOBREQUEST']._serialized_end=338
|
|
43
|
-
_globals['_JOBREQUEST_ENVENTRY']._serialized_start=296
|
|
44
|
-
_globals['_JOBREQUEST_ENVENTRY']._serialized_end=338
|
|
45
|
-
_globals['_JOBRESULT']._serialized_start=341
|
|
46
|
-
_globals['_JOBRESULT']._serialized_end=516
|
|
47
|
-
# @@protoc_insertion_point(module_scope)
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
-
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
-
# source: cortex/agent/v1/safety.proto
|
|
5
|
-
# Protobuf Python Version: 6.31.1
|
|
6
|
-
"""Generated protocol buffer code."""
|
|
7
|
-
from google.protobuf import descriptor as _descriptor
|
|
8
|
-
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
-
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
-
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
-
from google.protobuf.internal import builder as _builder
|
|
12
|
-
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
-
_runtime_version.Domain.PUBLIC,
|
|
14
|
-
6,
|
|
15
|
-
31,
|
|
16
|
-
1,
|
|
17
|
-
'',
|
|
18
|
-
'cortex/agent/v1/safety.proto'
|
|
19
|
-
)
|
|
20
|
-
# @@protoc_insertion_point(imports)
|
|
21
|
-
|
|
22
|
-
_sym_db = _symbol_database.Default()
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
from cortex.agent.v1 import job_pb2 as cortex_dot_agent_dot_v1_dot_job__pb2
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x63ortex/agent/v1/safety.proto\x12\x0f\x63ortex.agent.v1\x1a\x19\x63ortex/agent/v1/job.proto\"\x8b\x01\n\x12PolicyCheckRequest\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x0e\n\x06tenant\x18\x03 \x01(\t\x12.\n\x08priority\x18\x04 \x01(\x0e\x32\x1c.cortex.agent.v1.JobPriority\x12\x16\n\x0e\x65stimated_cost\x18\x05 \x01(\x01\"t\n\x13PolicyCheckResponse\x12/\n\x08\x64\x65\x63ision\x18\x01 \x01(\x0e\x32\x1d.cortex.agent.v1.DecisionType\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x1c\n\x14redacted_context_ptr\x18\x03 \x01(\t*\x9b\x01\n\x0c\x44\x65\x63isionType\x12\x1d\n\x19\x44\x45\x43ISION_TYPE_UNSPECIFIED\x10\x00\x12\x17\n\x13\x44\x45\x43ISION_TYPE_ALLOW\x10\x01\x12\x16\n\x12\x44\x45\x43ISION_TYPE_DENY\x10\x02\x12\x1f\n\x1b\x44\x45\x43ISION_TYPE_REQUIRE_HUMAN\x10\x03\x12\x1a\n\x16\x44\x45\x43ISION_TYPE_THROTTLE\x10\x04\x32\x62\n\x0cSafetyKernel\x12R\n\x05\x43heck\x12#.cortex.agent.v1.PolicyCheckRequest\x1a$.cortex.agent.v1.PolicyCheckResponseB\x7f\n\x16\x61i.cortex.cap.agent.v1P\x01Z+github.com/coretexos/cap/go/cortex/agent/v1\xaa\x02\x0f\x43ortex.Agent.V1\xca\x02\x0f\x43ortex\\Agent\\V1\xea\x02\x11\x43ortex::Agent::V1b\x06proto3')
|
|
29
|
-
|
|
30
|
-
_globals = globals()
|
|
31
|
-
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
32
|
-
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'cortex.agent.v1.safety_pb2', _globals)
|
|
33
|
-
if not _descriptor._USE_C_DESCRIPTORS:
|
|
34
|
-
_globals['DESCRIPTOR']._loaded_options = None
|
|
35
|
-
_globals['DESCRIPTOR']._serialized_options = b'\n\026ai.cortex.cap.agent.v1P\001Z+github.com/coretexos/cap/go/cortex/agent/v1\252\002\017Cortex.Agent.V1\312\002\017Cortex\\Agent\\V1\352\002\021Cortex::Agent::V1'
|
|
36
|
-
_globals['_DECISIONTYPE']._serialized_start=337
|
|
37
|
-
_globals['_DECISIONTYPE']._serialized_end=492
|
|
38
|
-
_globals['_POLICYCHECKREQUEST']._serialized_start=77
|
|
39
|
-
_globals['_POLICYCHECKREQUEST']._serialized_end=216
|
|
40
|
-
_globals['_POLICYCHECKRESPONSE']._serialized_start=218
|
|
41
|
-
_globals['_POLICYCHECKRESPONSE']._serialized_end=334
|
|
42
|
-
_globals['_SAFETYKERNEL']._serialized_start=494
|
|
43
|
-
_globals['_SAFETYKERNEL']._serialized_end=592
|
|
44
|
-
# @@protoc_insertion_point(module_scope)
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
from typing import Callable, Awaitable
|
|
3
|
-
|
|
4
|
-
from google.protobuf import timestamp_pb2
|
|
5
|
-
from cap.pb.cortex.agent.v1 import buspacket_pb2, job_pb2
|
|
6
|
-
|
|
7
|
-
DEFAULT_PROTOCOL_VERSION = 1
|
|
8
|
-
SUBJECT_RESULT = "sys.job.result"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
async def run_worker(nats_url: str, subject: str, handler: Callable[[job_pb2.JobRequest], Awaitable[job_pb2.JobResult]]):
|
|
12
|
-
import nats
|
|
13
|
-
|
|
14
|
-
nc = await nats.connect(servers=nats_url, name="cap-worker")
|
|
15
|
-
|
|
16
|
-
async def on_msg(msg):
|
|
17
|
-
packet = buspacket_pb2.BusPacket()
|
|
18
|
-
packet.ParseFromString(msg.data)
|
|
19
|
-
req = packet.job_request
|
|
20
|
-
if not req.job_id:
|
|
21
|
-
return
|
|
22
|
-
try:
|
|
23
|
-
res = await handler(req)
|
|
24
|
-
except Exception as exc: # noqa: BLE001
|
|
25
|
-
res = job_pb2.JobResult(
|
|
26
|
-
job_id=req.job_id,
|
|
27
|
-
status=job_pb2.JOB_STATUS_FAILED,
|
|
28
|
-
error_message=str(exc),
|
|
29
|
-
)
|
|
30
|
-
ts = timestamp_pb2.Timestamp()
|
|
31
|
-
ts.GetCurrentTime()
|
|
32
|
-
out = buspacket_pb2.BusPacket()
|
|
33
|
-
out.trace_id = packet.trace_id
|
|
34
|
-
out.sender_id = "cap-worker"
|
|
35
|
-
out.protocol_version = DEFAULT_PROTOCOL_VERSION
|
|
36
|
-
out.created_at.CopyFrom(ts)
|
|
37
|
-
out.job_result.CopyFrom(res)
|
|
38
|
-
await nc.publish(SUBJECT_RESULT, out.SerializeToString())
|
|
39
|
-
|
|
40
|
-
await nc.subscribe(subject, queue=subject, cb=on_msg)
|
|
41
|
-
try:
|
|
42
|
-
while True:
|
|
43
|
-
await asyncio.sleep(1)
|
|
44
|
-
finally:
|
|
45
|
-
await nc.drain()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|