naas-abi-core 1.2.1__py3-none-any.whl → 1.4.0__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.
assets/logo.png ADDED
Binary file
@@ -46,169 +46,6 @@ print(response.json())
46
46
  ```
47
47
  """,
48
48
  },
49
- {
50
- "name": "Connections",
51
- "description": """
52
- Connections are currently configured using Integration secrets (API keys, credentials) set up in the GitHub project settings. \n
53
- Learn more about the data access and secrets key [here](https://github.com/jupyter-naas/abi/blob/main/README.md#setup-github-repository-secrets).
54
-
55
- ### Agicap
56
- Required:
57
- - `AGICAP_USERNAME`: Username of your Agicap account
58
- - `AGICAP_PASSWORD`: Password of your Agicap account
59
- - `AGICAP_CLIENT_ID`: Client ID of your Agicap account. [Get your client ID](https://app.agicap.com/fr/app/organization-advanced-settings/public-api)
60
- - `AGICAP_CLIENT_SECRET`: Client Secret of your Agicap account. [Get your client secret](https://app.agicap.com/fr/app/organization-advanced-settings/public-api)
61
- - `AGICAP_BEARER_TOKEN`: Bearer Token of your Agicap account.
62
- - `AGICAP_API_TOKEN`: API token of your Agicap account. [Get your API token](https://app.agicap.com/fr/app/parametres/openapi)
63
-
64
- ### Algolia
65
- Required:
66
- - `ALGOLIA_API_KEY`: API key of your Algolia account. [Get your API key](https://www.algolia.com/api-keys)
67
- - `ALGOLIA_APPLICATION_ID`: Application ID of your Algolia account. [Get your application ID](https://www.algolia.com/api-keys)
68
-
69
- ### Airtable
70
- Required:
71
- - `AIRTABLE_API_KEY`: API key of your Airtable account. [Get your API key](https://airtable.com/create/tokens)
72
- - `AIRTABLE_BASE_ID`: Base ID of your Airtable account. [Get your base ID](https://airtable.com/create/tokens)
73
-
74
- ### AWS
75
- Required:
76
- - `AWS_ACCESS_KEY_ID`: Access key ID of your AWS account. [Get your access key ID](https://us-east-1.console.aws.amazon.com/iam/home)
77
- - `AWS_SECRET_ACCESS_KEY`: Secret access key of your AWS account. [Get your secret access key](https://us-east-1.console.aws.amazon.com/iam/home)
78
- - `AWS_REGION`: Region of your AWS account. [Get your region](https://us-east-1.console.aws.amazon.com/iam/home)
79
-
80
- ### Brevo
81
- Required:
82
- - `BREVO_API_KEY`: API key of your Brevo account. [Get your API key](https://help.brevo.com/hc/en-us/articles/209467485)
83
-
84
- ### Clockify
85
- Required:
86
- - `CLOCKIFY_API_KEY`: API key of your Clockify account. [Get your API key](https://clockify.me/user/settings)
87
-
88
- ### Discord
89
- Required:
90
- - `DISCORD_API_KEY`: API key of your Discord account. [Get your API key](https://discord.com/developers/applications)
91
-
92
- ### Github
93
- Required:
94
- - `GITHUB_ACCESS_TOKEN`: Access token of your Github account. [Get your access token](https://github.com/settings/tokens)
95
-
96
- ### Gladia
97
- Required:
98
- - `GLADIA_API_KEY`: API key of your Gladia account. [Get your API key](https://www.gladia.ai/)
99
-
100
- ### Gmail
101
- Required:
102
- - `GMAIL_EMAIL`: Email of your Gmail account.
103
- - `GMAIL_APP_PASSWORD`: App password of your Gmail account. [Get your app password](https://support.google.com/mail/answer/185833)
104
-
105
- ### Harvest
106
- Required:
107
- - `HARVEST_API_KEY`: API key of your Harvest account. [Get your API key](https://app.harvestapp.com/account/api)
108
- - `HARVEST_ACCOUNT_ID`: Account ID of your Harvest account.
109
-
110
- ### HubSpot
111
- Required:
112
- - `HUBSPOT_ACCESS_TOKEN`: Access token of your HubSpot account. [Get your access token](https://developers.hubspot.com/docs/api/private-apps)
113
-
114
- ### Instagram
115
- Required:
116
- - `INSTAGRAM_ACCESS_TOKEN`: Access token of your Instagram account. [Get your access token](https://developers.facebook.com/docs/instagram-api)
117
-
118
- ### LinkedIn
119
- Required:
120
- - `li_at` cookie: li_at cookie of your LinkedIn account. [Get your li_at cookie](https://www.notion.so/LinkedIn-driver-Get-your-cookies)
121
- - `JSESSIONID` cookie: JSESSIONID cookie of your LinkedIn account. [Get your JSESSIONID cookie](https://www.notion.so/LinkedIn-driver-Get-your-cookies)
122
-
123
- ### Mailchimp
124
- Required:
125
- - `MAILCHIMP_API_KEY`: API key of your Mailchimp account. [Get your API key](https://mailchimp.com/developer/api/)
126
- - `MAILCHIMP_SERVER_PREFIX`: Server prefix of your Mailchimp account. [Get your server prefix](https://mailchimp.com/developer/api/)
127
-
128
- ### Mercury
129
- Required:
130
- - `MERCURY_API_TOKEN`: API token of your Mercury account. [Get your API token](https://app.mercury.com/settings/tokens)
131
-
132
- ### NewsAPI
133
- Required:
134
- - `NEWSAPI_API_KEY`: API key of your NewsAPI account. [Get your API key](https://newsapi.org/register)
135
-
136
- ### Notion
137
- Required:
138
- - `NOTION_API_KEY`: API key of your Notion account. [Get your API key](https://www.notion.so/my-integrations)
139
-
140
- ### OneDrive
141
- Required:
142
- - `ONEDRIVE_ACCESS_TOKEN`: Access token of your OneDrive account. [Get your access token](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/getting-started/)
143
-
144
- ### Pennylane
145
- Required:
146
- - `PENNYLANE_API_TOKEN`: API token of your Pennylane account. [Get your API token](https://pennylane.readme.io/docs/get-my-api-token)
147
-
148
- ### Perplexity
149
- Required:
150
- - `PERPLEXITY_API_KEY`: API key of your Perplexity account. [Get your API key](https://docs.perplexity.ai/docs/getting-started)
151
-
152
- ### Pipedrive
153
- Required:
154
- - `PIPEDRIVE_API_KEY`: API key of your Pipedrive account. [Get your API key](https://app.pipedrive.com/settings/api)
155
-
156
- ### PostgreSQL
157
- Required:
158
- - `POSTGRES_HOST`: Host of your PostgreSQL database.
159
- - `POSTGRES_PORT`: Port of your PostgreSQL database.
160
- - `POSTGRES_DB`: Database name of your PostgreSQL database.
161
- - `POSTGRES_USER`: User of your PostgreSQL database.
162
- - `POSTGRES_PASSWORD`: Password of your PostgreSQL database.
163
-
164
- ### Qonto
165
- Required:
166
- - `QONTO_ORGANIZATION_SLUG`: Organization slug of your Qonto account. [Get your organization slug](https://support-fr.qonto.com/hc/en-us/articles/23947692362513)
167
- - `QONTO_SECRET_KEY`: Secret key of your Qonto account. [Get your secret key](https://support-fr.qonto.com/hc/en-us/articles/23947692362513)
168
-
169
- ### Replicate
170
- Required:
171
- - `REPLICATE_API_KEY`: API key of your Replicate account. [Get your API key](https://replicate.com/account/api-tokens)
172
-
173
- ### Serper
174
- Required:
175
- - `SERPER_API_KEY`: API key of your Serper account. [Get your API key](https://serper.dev/api-key)
176
-
177
- ### Slack
178
- Required:
179
- - `SLACK_BOT_TOKEN`: Bot token of your Slack account. [Get your bot token](https://api.slack.com/apps)
180
-
181
- ### Stripe
182
- Required:
183
- - `STRIPE_API_KEY`: API key of your Stripe account. [Get your API key](https://dashboard.stripe.com/apikeys)
184
-
185
- ### Supabase
186
- Required:
187
- - `SUPABASE_URL`: URL of your Supabase account. [Get your URL](https://app.supabase.com/project/_/settings/api)
188
- - `SUPABASE_KEY`: Key of your Supabase account. [Get your key](https://app.supabase.com/project/_/settings/api)
189
-
190
- ### TikTok
191
- Required:
192
- - `TIKTOK_ACCESS_TOKEN`: Access token of your TikTok account. [Get your access token](https://developers.tiktok.com/)
193
-
194
- ### WhatsApp
195
- Required:
196
- - `WHATSAPP_ACCESS_TOKEN`: Access token of your WhatsApp account. [Get your access token](https://developers.facebook.com/docs/whatsapp/cloud-api/get-started)
197
-
198
- ### Yahoo Finance
199
- Required:
200
- - `YAHOO_FINANCE_API_KEY`: API key of your Yahoo Finance account. [Get your API key](https://www.yahoofinanceapi.com/)
201
-
202
- ### YouTube
203
- Required:
204
- - `YOUTUBE_API_KEY`: API key of your YouTube account. [Get your API key](https://console.cloud.google.com/apis/credentials)
205
-
206
- ### ZeroBounce
207
- Required:
208
- - `ZEROBOUNCE_API_KEY`: API key of your ZeroBounce account. [Get your API key](https://app.zerobounce.net/)
209
-
210
- """,
211
- },
212
49
  {
213
50
  "name": "Agents",
214
51
  "description": """
@@ -129,7 +129,22 @@ class EngineConfiguration(BaseModel):
129
129
 
130
130
  def __getattr__(self, name):
131
131
  if self.secret_service is None:
132
- return 0
132
+ # This rule is used only when doing the first pass configuration to load the secret service.
133
+
134
+ # First priority is to check the environment variables.
135
+ if name in os.environ:
136
+ return os.environ.get(name)
137
+ else:
138
+ # If the environment variable is not found, we check the .env file. ONLY FOR THE FIRST PASS CONFIGURATION.
139
+ from dotenv import dotenv_values
140
+
141
+ secrets = dotenv_values()
142
+ if name in secrets:
143
+ return secrets.get(name)
144
+ else:
145
+ return f"Secret '{name}' not found while loading the secret service. Please provide it via the environment variables or .env file."
146
+ elif name in os.environ:
147
+ return os.environ.get(name)
133
148
  secret = self.secret_service.get(name)
134
149
  if secret is None:
135
150
  if not sys.stdin.isatty():
@@ -144,9 +159,6 @@ class EngineConfiguration(BaseModel):
144
159
  return value
145
160
  return secret
146
161
 
147
- def get(self, key, default=None):
148
- return 0
149
-
150
162
  first_pass_data = yaml.safe_load(
151
163
  StringIO(Template(yaml_content).render(secret=SecretServiceWrapper()))
152
164
  )
@@ -157,13 +169,11 @@ class EngineConfiguration(BaseModel):
157
169
  # Here we can now template the yaml by using `yaml_content` and the secret service.
158
170
  # Using Jinja2 template engine.
159
171
 
160
- logger.debug("Yaml content: {yaml_content}")
172
+ logger.debug(f"Yaml content: {yaml_content}")
161
173
 
162
174
  template = Template(yaml_content)
163
175
  templated_yaml = template.render(secret=SecretServiceWrapper(secret_service))
164
176
 
165
- logger.debug(f"Templated yaml: {templated_yaml}")
166
-
167
177
  data = yaml.safe_load(StringIO(templated_yaml))
168
178
 
169
179
  logger.debug(f"Data: {data}")
@@ -178,17 +188,28 @@ class EngineConfiguration(BaseModel):
178
188
  if configuration_yaml is not None:
179
189
  return cls.from_yaml_content(configuration_yaml)
180
190
 
181
- logger.debug(f"Loading configuration from {os.getenv('ENV')}")
191
+ # Get ENV value
192
+ from dotenv import dotenv_values
193
+
194
+ env = os.getenv("ENV")
195
+ if not env:
196
+ env = dotenv_values().get("ENV")
182
197
 
183
- if os.path.exists(f"config.{os.getenv('ENV')}.yaml"):
184
- return cls.from_yaml(f"config.{os.getenv('ENV')}.yaml")
198
+ # First we check the environment variable.
199
+ if os.path.exists(f"config.{env}.yaml"):
200
+ config_file = f"config.{env}.yaml"
201
+ # If the config.{env}.yaml file is not found, we check the config.yaml file.
185
202
  elif os.path.exists("config.yaml"):
186
- return cls.from_yaml("config.yaml")
203
+ config_file = "config.yaml"
187
204
  else:
188
205
  raise FileNotFoundError(
189
206
  "Configuration file not found. Please create a config.yaml file or config.{env}.yaml file."
190
207
  )
191
208
 
209
+ logger.debug(f"Loading configuration from {config_file}")
210
+
211
+ return cls.from_yaml(config_file)
212
+
192
213
 
193
214
  if __name__ == "__main__":
194
215
  config = EngineConfiguration.load_configuration()
@@ -17,18 +17,46 @@ from typing_extensions import Self
17
17
 
18
18
 
19
19
  class ObjectStorageAdapterFSConfiguration(BaseModel):
20
+ """Object storage adapter filesystem configuration.
21
+
22
+ object_storage_adapter:
23
+ adapter: "fs"
24
+ config:
25
+ base_path: "storage/datastore"
26
+ """
20
27
  base_path: str
21
28
 
22
29
 
23
30
  class ObjectStorageAdapterS3Configuration(BaseModel):
31
+ """Object storage adapter S3 configuration.
32
+
33
+ object_storage_adapter:
34
+ adapter: "s3"
35
+ config:
36
+ bucket_name: "my-bucket"
37
+ base_prefix: "my-prefix"
38
+ access_key_id: "{{ secret.AWS_ACCESS_KEY_ID }}"
39
+ secret_access_key: "{{ secret.AWS_SECRET_ACCESS_KEY }}"
40
+ session_token: "{{ secret.AWS_SESSION_TOKEN }}"
41
+ """
24
42
  bucket_name: str
43
+ base_prefix: str
25
44
  access_key_id: str
26
45
  secret_access_key: str
27
- base_prefix: str
28
46
  session_token: str | None = None
29
47
 
30
48
 
31
49
  class ObjectStorageAdapterNaasConfiguration(BaseModel):
50
+ """Object storage adapter Naas configuration.
51
+
52
+ object_storage_adapter:
53
+ adapter: "naas"
54
+ config:
55
+ naas_api_key: "{{ secret.NAAS_API_KEY }}"
56
+ workspace_id: "{{ secret.WORKSPACE_ID }}"
57
+ storage_name: "{{ secret.STORAGE_NAME }}"
58
+ base_prefix: "my-prefix"
59
+ """
32
60
  naas_api_key: str
33
61
  workspace_id: str
34
62
  storage_name: str
@@ -18,7 +18,38 @@ if TYPE_CHECKING:
18
18
  )
19
19
 
20
20
 
21
+ class DotenvSecretConfiguration(BaseModel):
22
+ """Dotenv secret configuration.
23
+
24
+ secret_adapters:
25
+ - adapter: "dotenv"
26
+ config: {}
27
+ """
28
+ pass
29
+
30
+
31
+ class NaasSecretConfiguration(BaseModel):
32
+ """Naas secret configuration.
33
+
34
+ secret_adapters:
35
+ - adapter: "naas"
36
+ config:
37
+ naas_api_key: "{{ secret.NAAS_API_KEY }}"
38
+ naas_api_url: "https://api.naas.ai"
39
+ """
40
+ naas_api_key: str
41
+ naas_api_url: str
42
+
43
+
21
44
  class Base64SecretConfiguration(BaseModel):
45
+ """Base64 secret configuration.
46
+
47
+ secret_adapters:
48
+ - adapter: "base64"
49
+ config:
50
+ secret_adapter: *secret_adapter
51
+ base64_secret_key: "{{ secret.BASE64_SECRET_KEY }}"
52
+ """
22
53
  secret_adapter: "SecretAdapterConfiguration"
23
54
  base64_secret_key: str
24
55
 
@@ -30,15 +61,6 @@ class Base64SecretConfiguration(BaseModel):
30
61
  return Base64Secret(self.secret_adapter.load(), self.base64_secret_key)
31
62
 
32
63
 
33
- class NaasSecretConfiguration(BaseModel):
34
- naas_api_key: str
35
- naas_api_url: str
36
-
37
-
38
- class DotenvSecretConfiguration(BaseModel):
39
- pass
40
-
41
-
42
64
  class SecretAdapterConfiguration(GenericLoader):
43
65
  adapter: Literal["dotenv", "naas", "base64", "custom"]
44
66
  config: (
@@ -0,0 +1,74 @@
1
+ from naas_abi_core.engine.engine_configuration.EngineConfiguration_SecretService import (
2
+ DotenvSecretConfiguration,
3
+ NaasSecretConfiguration,
4
+ SecretAdapterConfiguration,
5
+ SecretServiceConfiguration,
6
+ )
7
+ from naas_abi_core.services.secret.Secret import Secret
8
+ from naas_abi_core.services.secret.SecretPorts import ISecretAdapter
9
+
10
+
11
+ def test_secret_service_configuration():
12
+ from naas_abi_core.services.secret.adaptors.secondary.dotenv_secret_secondaryadaptor import (
13
+ DotenvSecretSecondaryAdaptor,
14
+ )
15
+
16
+ configuration = SecretServiceConfiguration(
17
+ secret_adapters=[
18
+ SecretAdapterConfiguration(
19
+ adapter="dotenv", config=DotenvSecretConfiguration()
20
+ )
21
+ ]
22
+ )
23
+ assert configuration.secret_adapters is not None
24
+ assert len(configuration.secret_adapters) == 1
25
+
26
+ secret_adapter = configuration.secret_adapters[0].load()
27
+
28
+ assert secret_adapter is not None
29
+ assert isinstance(secret_adapter, ISecretAdapter)
30
+ assert isinstance(secret_adapter, DotenvSecretSecondaryAdaptor)
31
+
32
+ secret_service = configuration.load()
33
+
34
+ assert secret_service is not None
35
+ assert isinstance(secret_service, Secret)
36
+
37
+
38
+ def test_secret_service_configuration_naas():
39
+ import os
40
+
41
+ from dotenv import load_dotenv
42
+ from naas_abi_core.services.secret.adaptors.secondary.NaasSecret import (
43
+ NaasSecret,
44
+ )
45
+
46
+ load_dotenv()
47
+
48
+ naas_api_key = os.getenv("NAAS_API_KEY")
49
+ if naas_api_key is None:
50
+ raise ValueError("NAAS_API_KEY is not set")
51
+
52
+ naas_api_url = os.getenv("NAAS_API_URL")
53
+ if naas_api_url is None:
54
+ raise ValueError("NAAS_API_URL is not set")
55
+
56
+ configuration = SecretServiceConfiguration(
57
+ secret_adapters=[
58
+ SecretAdapterConfiguration(
59
+ adapter="naas",
60
+ config=NaasSecretConfiguration(
61
+ naas_api_key=naas_api_key,
62
+ naas_api_url=naas_api_url,
63
+ ),
64
+ )
65
+ ]
66
+ )
67
+ assert configuration.secret_adapters is not None
68
+ assert len(configuration.secret_adapters) == 1
69
+
70
+ secret_adapter = configuration.secret_adapters[0].load()
71
+
72
+ assert secret_adapter is not None
73
+ assert isinstance(secret_adapter, ISecretAdapter)
74
+ assert isinstance(secret_adapter, NaasSecret)
@@ -28,6 +28,7 @@ class OxigraphAdapterConfiguration(BaseModel):
28
28
  oxigraph_url: "http://localhost:7878"
29
29
  timeout: 60
30
30
  """
31
+
31
32
  oxigraph_url: str = "http://localhost:7878"
32
33
  timeout: int = 60
33
34
 
@@ -38,11 +39,12 @@ class AWSNeptuneAdapterConfiguration(BaseModel):
38
39
  triple_store_adapter:
39
40
  adapter: "aws_neptune"
40
41
  config:
41
- aws_region_name: "eu-west-3"
42
+ aws_region_name: "{{ secret.AWS_REGION }}"
42
43
  aws_access_key_id: "{{ secret.AWS_ACCESS_KEY_ID }}"
43
44
  aws_secret_access_key: "{{ secret.AWS_SECRET_ACCESS_KEY }}"
44
- db_instance_identifier: "{{ secret.DB_INSTANCE_IDENTIFIER }}"
45
+ db_instance_identifier: "{{ secret.AWS_NEPTUNE_DB_INSTANCE_IDENTIFIER }}"
45
46
  """
47
+
46
48
  aws_region_name: str
47
49
  aws_access_key_id: str
48
50
  aws_secret_access_key: str
@@ -55,15 +57,16 @@ class AWSNeptuneSSHTunnelAdapterConfiguration(AWSNeptuneAdapterConfiguration):
55
57
  triple_store_adapter:
56
58
  adapter: "aws_neptune_sshtunnel"
57
59
  config:
58
- aws_region_name: "eu-west-3"
60
+ aws_region_name: "{{ secret.AWS_REGION }}"
59
61
  aws_access_key_id: "{{ secret.AWS_ACCESS_KEY_ID }}"
60
62
  aws_secret_access_key: "{{ secret.AWS_SECRET_ACCESS_KEY }}"
61
- db_instance_identifier: "{{ secret.DB_INSTANCE_IDENTIFIER }}"
62
- bastion_host: "bastion.example.com"
63
- bastion_port: 22
64
- bastion_user: "ubuntu"
65
- bastion_private_key: "{{ secret.BASTION_PRIVATE_KEY }}"
63
+ db_instance_identifier: "{{ secret.AWS_NEPTUNE_DB_INSTANCE_IDENTIFIER }}"
64
+ bastion_host: "{{ secret.AWS_BASTION_HOST }}"
65
+ bastion_port: "{{ secret.AWS_BASTION_PORT }}"
66
+ bastion_user: "{{ secret.AWS_BASTION_USER }}"
67
+ bastion_private_key: "{{ secret.AWS_BASTION_PRIVATE_KEY }}"
66
68
  """
69
+
67
70
  bastion_host: str
68
71
  bastion_port: int
69
72
  bastion_user: str
@@ -79,6 +82,7 @@ class TripleStoreAdapterFilesystemConfiguration(BaseModel):
79
82
  store_path: "storage/triplestore"
80
83
  triples_path: "triples"
81
84
  """
85
+
82
86
  store_path: str
83
87
  triples_path: str = "triples"
84
88
 
@@ -92,6 +96,7 @@ class TripleStoreAdapterObjectStorageConfiguration(BaseModel):
92
96
  object_storage_service: *object_storage_service
93
97
  triples_prefix: "triples"
94
98
  """
99
+
95
100
  object_storage_service: ObjectStorageServiceConfiguration
96
101
  triples_prefix: str = "triples"
97
102
 
@@ -0,0 +1,109 @@
1
+ from naas_abi_core.engine.engine_configuration.EngineConfiguration_TripleStoreService import (
2
+ AWSNeptuneSSHTunnelAdapterConfiguration,
3
+ OxigraphAdapterConfiguration,
4
+ TripleStoreAdapterConfiguration,
5
+ TripleStoreAdapterFilesystemConfiguration,
6
+ TripleStoreServiceConfiguration,
7
+ )
8
+ from naas_abi_core.services.triple_store.TripleStorePorts import ITripleStorePort
9
+ from naas_abi_core.services.triple_store.TripleStoreService import TripleStoreService
10
+
11
+
12
+ def test_triple_store_service_configuration():
13
+ from naas_abi_core.services.triple_store.adaptors.secondary.TripleStoreService__SecondaryAdaptor__Filesystem import (
14
+ TripleStoreService__SecondaryAdaptor__Filesystem,
15
+ )
16
+
17
+ configuration = TripleStoreServiceConfiguration(
18
+ triple_store_adapter=TripleStoreAdapterConfiguration(
19
+ adapter="fs",
20
+ config=TripleStoreAdapterFilesystemConfiguration(
21
+ store_path="storage/triplestore/test", triples_path="triples"
22
+ ),
23
+ )
24
+ )
25
+ assert configuration.triple_store_adapter is not None
26
+
27
+ triple_store_adapter = configuration.triple_store_adapter.load()
28
+
29
+ assert triple_store_adapter is not None
30
+ assert isinstance(triple_store_adapter, ITripleStorePort)
31
+ assert isinstance(
32
+ triple_store_adapter, TripleStoreService__SecondaryAdaptor__Filesystem
33
+ )
34
+
35
+ triple_store_service = configuration.load()
36
+
37
+ assert triple_store_service is not None
38
+ assert isinstance(triple_store_service, TripleStoreService)
39
+
40
+
41
+ def test_triple_store_service_configuration_naas():
42
+ from naas_abi_core.services.triple_store.adaptors.secondary.Oxigraph import (
43
+ Oxigraph,
44
+ )
45
+
46
+ configuration = TripleStoreServiceConfiguration(
47
+ triple_store_adapter=TripleStoreAdapterConfiguration(
48
+ adapter="oxigraph",
49
+ config=OxigraphAdapterConfiguration(
50
+ oxigraph_url="http://localhost:7878",
51
+ timeout=120,
52
+ ),
53
+ )
54
+ )
55
+ assert configuration.triple_store_adapter is not None
56
+
57
+ triple_store_adapter = configuration.triple_store_adapter.load()
58
+
59
+ assert triple_store_adapter is not None
60
+ assert isinstance(triple_store_adapter, ITripleStorePort)
61
+ assert isinstance(triple_store_adapter, Oxigraph)
62
+
63
+ triple_store_service = configuration.load()
64
+
65
+ assert triple_store_service is not None
66
+ assert isinstance(triple_store_service, TripleStoreService)
67
+
68
+
69
+ def test_triple_store_service_configuration_aws_neptune_sshtunnel():
70
+ import os
71
+
72
+ from dotenv import load_dotenv
73
+
74
+ load_dotenv()
75
+
76
+ from naas_abi_core.services.triple_store.adaptors.secondary.AWSNeptune import (
77
+ AWSNeptuneSSHTunnel,
78
+ )
79
+
80
+ configuration = TripleStoreServiceConfiguration(
81
+ triple_store_adapter=TripleStoreAdapterConfiguration(
82
+ adapter="aws_neptune_sshtunnel",
83
+ config=AWSNeptuneSSHTunnelAdapterConfiguration(
84
+ aws_region_name=os.environ.get("AWS_REGION"),
85
+ aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"),
86
+ aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY"),
87
+ db_instance_identifier=os.environ.get(
88
+ "AWS_NEPTUNE_DB_INSTANCE_IDENTIFIER"
89
+ ),
90
+ bastion_host=os.environ.get("AWS_BASTION_HOST"),
91
+ bastion_port=int(os.environ.get("AWS_BASTION_PORT")),
92
+ bastion_user=os.environ.get("AWS_BASTION_USER"),
93
+ bastion_private_key=os.environ.get("AWS_BASTION_PRIVATE_KEY"),
94
+ ),
95
+ ),
96
+ )
97
+
98
+ assert configuration.triple_store_adapter is not None
99
+
100
+ triple_store_adapter = configuration.triple_store_adapter.load()
101
+
102
+ assert triple_store_adapter is not None
103
+ assert isinstance(triple_store_adapter, ITripleStorePort)
104
+ assert isinstance(triple_store_adapter, AWSNeptuneSSHTunnel)
105
+
106
+ triple_store_service = configuration.load()
107
+
108
+ assert triple_store_service is not None
109
+ assert isinstance(triple_store_service, TripleStoreService)
@@ -12,6 +12,17 @@ from pydantic import BaseModel, model_validator
12
12
 
13
13
 
14
14
  class VectorStoreAdapterQdrantConfiguration(BaseModel):
15
+ """Qdrant vector store adapter configuration.
16
+
17
+ vector_store_adapter:
18
+ adapter: "qdrant"
19
+ config:
20
+ host: "{{ secret.QDRANT_HOST }}"
21
+ port: "{{ secret.QDRANT_PORT }}"
22
+ api_key: "{{ secret.QDRANT_API_KEY }}"
23
+ https: "{{ secret.QDRANT_HTTPS }}"
24
+ timeout: "{{ secret.QDRANT_TIMEOUT }}"
25
+ """
15
26
  host: str = "localhost"
16
27
  port: int = 6333
17
28
  api_key: str | None = None
@@ -0,0 +1,33 @@
1
+ from naas_abi_core.engine.engine_configuration.EngineConfiguration_VectorStoreService import (
2
+ VectorStoreAdapterConfiguration,
3
+ VectorStoreAdapterQdrantConfiguration,
4
+ VectorStoreServiceConfiguration,
5
+ )
6
+ from naas_abi_core.services.vector_store.IVectorStorePort import IVectorStorePort
7
+ from naas_abi_core.services.vector_store.VectorStoreService import VectorStoreService
8
+
9
+
10
+ def test_vector_store_service_configuration():
11
+ from naas_abi_core.services.vector_store.adapters.QdrantAdapter import (
12
+ QdrantAdapter,
13
+ )
14
+
15
+ qdrant_config = VectorStoreAdapterQdrantConfiguration()
16
+ configuration = VectorStoreServiceConfiguration(
17
+ vector_store_adapter=VectorStoreAdapterConfiguration(
18
+ adapter="qdrant",
19
+ config=qdrant_config.model_dump(),
20
+ )
21
+ )
22
+ assert configuration.vector_store_adapter is not None
23
+
24
+ vector_store_adapter = configuration.vector_store_adapter.load()
25
+
26
+ assert vector_store_adapter is not None
27
+ assert isinstance(vector_store_adapter, IVectorStorePort)
28
+ assert isinstance(vector_store_adapter, QdrantAdapter)
29
+
30
+ vector_store_service = configuration.load()
31
+
32
+ assert vector_store_service is not None
33
+ assert isinstance(vector_store_service, VectorStoreService)
@@ -2,6 +2,10 @@ from abc import ABC, abstractmethod
2
2
  from typing import Any, Dict, List
3
3
 
4
4
 
5
+ class SecretAuthenticationError(Exception):
6
+ pass
7
+
8
+
5
9
  class ISecretAdapter(ABC):
6
10
  @abstractmethod
7
11
  def get(self, key: str, default: Any = None) -> str | Any | None:
@@ -38,3 +42,4 @@ class ISecretService(ABC):
38
42
  @abstractmethod
39
43
  def list(self) -> Dict[str, str | None]:
40
44
  raise NotImplementedError()
45
+ raise NotImplementedError()
@@ -2,7 +2,10 @@ from typing import Any, Dict
2
2
 
3
3
  import requests
4
4
  from naas_abi_core import logger
5
- from naas_abi_core.services.secret.SecretPorts import ISecretAdapter
5
+ from naas_abi_core.services.secret.SecretPorts import (
6
+ ISecretAdapter,
7
+ SecretAuthenticationError,
8
+ )
6
9
 
7
10
  NAAS_API_URL = "https://api.naas.ai"
8
11
 
@@ -27,6 +30,10 @@ class NaasSecret(ISecretAdapter):
27
30
  except requests.exceptions.HTTPError as _:
28
31
  if response.status_code == 404:
29
32
  logger.debug(f"Secret {key} not found")
33
+ elif response.status_code == 401:
34
+ error_message = f"Authentication error on '{NAAS_API_URL}' with NAAS_API_KEY '{self.naas_api_key}'"
35
+ logger.error(error_message)
36
+ raise SecretAuthenticationError(error_message)
30
37
  else:
31
38
  logger.error(f"Error getting secret {key}: {response.status_code}")
32
39
  return default
@@ -251,7 +251,10 @@ class AWSNeptune(ITripleStorePort):
251
251
 
252
252
  self.neptune_port = cluster_endpoints[0]["Endpoint"]["Port"]
253
253
 
254
- self.credentials = self.session.get_credentials()
254
+ credentials = self.session.get_credentials()
255
+ if credentials is None:
256
+ raise ValueError("Failed to get credentials from session")
257
+ self.credentials = credentials
255
258
 
256
259
  self.neptune_sparql_url = (
257
260
  f"https://{self.neptune_sparql_endpoint}:{self.neptune_port}/sparql"
@@ -291,6 +294,9 @@ class AWSNeptune(ITripleStorePort):
291
294
  request = AWSRequest(
292
295
  method=method, url=url, data=data, params=params, headers=headers
293
296
  )
297
+ assert self.credentials is not None, (
298
+ "Credentials must be set during initialization"
299
+ )
294
300
  SigV4Auth(
295
301
  self.credentials, "neptune-db", region_name=self.aws_region_name
296
302
  ).add_auth(request)
@@ -947,7 +953,7 @@ class AWSNeptuneSSHTunnel(AWSNeptune):
947
953
  aws_secret_access_key: str,
948
954
  db_instance_identifier: str,
949
955
  bastion_host: str,
950
- bastion_port: int,
956
+ bastion_port: int | str,
951
957
  bastion_user: str,
952
958
  bastion_private_key: str,
953
959
  default_graph_name: URIRef = NEPTUNE_DEFAULT_GRAPH_NAME,
@@ -965,7 +971,7 @@ class AWSNeptuneSSHTunnel(AWSNeptune):
965
971
  aws_secret_access_key (str): AWS secret key for Neptune authentication
966
972
  db_instance_identifier (str): Neptune database instance identifier
967
973
  bastion_host (str): Hostname or IP address of the bastion host
968
- bastion_port (int): SSH port on the bastion host (typically 22)
974
+ bastion_port (int | str): SSH port on the bastion host (typically 22)
969
975
  bastion_user (str): SSH username for bastion host authentication
970
976
  bastion_private_key (str): Complete SSH private key content as a string
971
977
  default_graph_name (URIRef, optional): Default named graph URI
@@ -1002,6 +1008,16 @@ class AWSNeptuneSSHTunnel(AWSNeptune):
1002
1008
  )
1003
1009
 
1004
1010
  assert isinstance(bastion_host, str)
1011
+ if not isinstance(bastion_port, int):
1012
+ # This block is added because the "naas" secret adapter does not always manage int values:
1013
+ # it may provide 'bastion_port' as a string; convert it to int if needed.
1014
+ if isinstance(bastion_port, str):
1015
+ try:
1016
+ bastion_port = int(bastion_port)
1017
+ except ValueError:
1018
+ raise ValueError(
1019
+ f"bastion_port must be an int or a string convertible to int, got string: {bastion_port!r}"
1020
+ )
1005
1021
  assert isinstance(bastion_port, int)
1006
1022
  assert isinstance(bastion_user, str)
1007
1023
  assert isinstance(bastion_private_key, str)
@@ -2,15 +2,17 @@ import copy
2
2
  import random
3
3
 
4
4
  import pydash as _
5
- from naas_abi import services
6
5
  from rdflib import OWL, RDF, RDFS, Graph, URIRef
7
6
 
8
7
  from naas_abi_core import logger
8
+ from naas_abi_core.services.triple_store.TripleStorePorts import ITripleStoreService
9
9
 
10
10
 
11
11
  class OntologyYaml:
12
- def __init__(self):
13
- pass
12
+ __triple_store_service: ITripleStoreService
13
+
14
+ def __init__(self, triple_store_service: ITripleStoreService):
15
+ self.__triple_store_service = triple_store_service
14
16
 
15
17
  @staticmethod
16
18
  def rdf_to_yaml(
@@ -50,7 +52,7 @@ class Translator:
50
52
  self.mapping_oprop = {}
51
53
 
52
54
  # Init ontology schemas
53
- consolidated = services.triple_store_service.get_schema_graph()
55
+ consolidated = self.__triple_store_service.get_schema_graph()
54
56
  schema_graph = Graph()
55
57
 
56
58
  # Filter for desired types
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: naas-abi-core
3
- Version: 1.2.1
3
+ Version: 1.4.0
4
4
  Summary: Abi framework allowing you to build your AI system.
5
5
  Author-email: Maxime Jublou <maxime@naas.ai>, Florent Ravenel <florent@naas.ai>, Jeremy Ravenel <jeremy@naas.ai>
6
6
  Requires-Python: <4,>=3.10
@@ -28,14 +28,18 @@ Requires-Dist: spacy>=3.8.7
28
28
  Requires-Dist: sparqlwrapper>=2.0.0
29
29
  Requires-Dist: sse-starlette<3,>=2.1.3
30
30
  Requires-Dist: starlette>=0.46.2
31
+ Requires-Dist: types-paramiko>=4.0.0.20250822
32
+ Requires-Dist: types-pyyaml>=6.0.12.20250915
31
33
  Requires-Dist: types-tqdm>=4.67.0.20250809
32
34
  Provides-Extra: all
35
+ Requires-Dist: boto3-stubs>=1.42.19; extra == 'all'
33
36
  Requires-Dist: boto3<2,>=1.38.19; extra == 'all'
34
37
  Requires-Dist: langchain-openai>=0.3.35; extra == 'all'
35
38
  Requires-Dist: paramiko<4.0.0,>=3.5.1; extra == 'all'
36
39
  Requires-Dist: qdrant-client>=1.14.3; extra == 'all'
37
40
  Requires-Dist: sshtunnel>=0.4.0; extra == 'all'
38
41
  Provides-Extra: aws
42
+ Requires-Dist: boto3-stubs>=1.42.19; extra == 'aws'
39
43
  Requires-Dist: boto3<2,>=1.38.19; extra == 'aws'
40
44
  Provides-Extra: openrouter
41
45
  Requires-Dist: langchain-openai>=0.3.35; extra == 'openrouter'
@@ -1,7 +1,7 @@
1
1
  naas_abi_core/__init__.py,sha256=kR93ywABUBo8-tAWCHMbRcCDCJZjqq4hWwxMk3Cr9fI,56
2
2
  naas_abi_core/apps/api/api.py,sha256=C11ItO_Xn0qh7ZubZUnQ4-Mts0Cd-Ui_4KEkU2cshqI,7127
3
3
  naas_abi_core/apps/api/api_test.py,sha256=7H_VgnbsGqu6oGY-apAHjJr_yjIcGHY0heaEThWBsUk,10537
4
- naas_abi_core/apps/api/openapi_doc.py,sha256=JbwzcmSP-Yl1rbN0QvUwOSmOFf-yKXECZ-2ptI7fWoU,11834
4
+ naas_abi_core/apps/api/openapi_doc.py,sha256=q0F8EG1e9bUPWDmK0touHxs4RBnfHD2xhuk-aICv_Ko,4737
5
5
  naas_abi_core/apps/mcp/Dockerfile.mcp,sha256=936qaoMFGbMvTARjzkNHMgRfGVWnolpVCrz0fBJYrLA,826
6
6
  naas_abi_core/apps/mcp/mcp_server.py,sha256=U-wDl8rswMk4nefGg2SUByw4x8CM10M59FfLHxIKC-o,8391
7
7
  naas_abi_core/apps/mcp/mcp_server_test.py,sha256=8jixnDyERM_HjjDTRtPDQcJ_rzA0ESAn147sl2Gk8gw,5636
@@ -12,14 +12,17 @@ naas_abi_core/engine/EngineProxy.py,sha256=o-D8LlP-PjQ_Yct4JWrDZw7mA7yporxb2XrJF
12
12
  naas_abi_core/engine/Engine_test.py,sha256=8eLZEnkL0IR4VAr6LF8fJ_fxZzi9s1mXCLgTVOIsR3E,161
13
13
  naas_abi_core/engine/IEngine.py,sha256=u-m-Qrvt3SP3gYKWPFPVjV8rs05D6NGnzO3XA0FInnw,2865
14
14
  naas_abi_core/engine/conftest.py,sha256=Al-SRVLrEdbTrX8sxQ3bBK4w1bbzE4GoBkzoBK-aXlg,932
15
- naas_abi_core/engine/engine_configuration/EngineConfiguration.py,sha256=NdjfrECgQ5leU7TNxxV6-qackTi0eaKzebqyJXlRPXk,6735
15
+ naas_abi_core/engine/engine_configuration/EngineConfiguration.py,sha256=7_ACJLTwwUYsm2RyabvPenyr78kXxy3x3t1BpW4H4r0,7797
16
16
  naas_abi_core/engine/engine_configuration/EngineConfiguration_Deploy.py,sha256=7nqOnXWcNbQAp9G3afc3y58BrxCaIrrTpUz7yBngy14,163
17
17
  naas_abi_core/engine/engine_configuration/EngineConfiguration_GenericLoader.py,sha256=KK2TQx6cNmoqFcwr9En00NKrX4ckkZl4ecv9QCUwPyc,1995
18
- naas_abi_core/engine/engine_configuration/EngineConfiguration_ObjectStorageService.py,sha256=cPZBs5-2dqX-piIZ7KTqiOce6O6GbnDDwjPGcfDN_U4,4736
18
+ naas_abi_core/engine/engine_configuration/EngineConfiguration_ObjectStorageService.py,sha256=erngfACkUwwHHOilmjbN9rRN5IPmMjOz9-zPaAeS5dM,5569
19
19
  naas_abi_core/engine/engine_configuration/EngineConfiguration_ObjectStorageService_test.py,sha256=h1PdIbMTJWi_lG83YgpI6zg8gRo0WEWvGSE6R4uKQp4,1063
20
- naas_abi_core/engine/engine_configuration/EngineConfiguration_SecretService.py,sha256=nqQ7XmfZZIx4kUvSO_FkBsSf9mcrRdwpsF_vkEdKqgU,4064
21
- naas_abi_core/engine/engine_configuration/EngineConfiguration_TripleStoreService.py,sha256=Wy4866k9JykcMf9ZDqBZfIVFLp98oU3_NwIaDPHrykI,7756
22
- naas_abi_core/engine/engine_configuration/EngineConfiguration_VectorStoreService.py,sha256=aoO-cmC1dfaXT4gqFivrO1ntB0xK8rjFoWmruf-I67U,2210
20
+ naas_abi_core/engine/engine_configuration/EngineConfiguration_SecretService.py,sha256=yNAwPpDwElSto6QjgKxoQsysnzk5NzjGE0OkIcNilwQ,4589
21
+ naas_abi_core/engine/engine_configuration/EngineConfiguration_SecretService_test.py,sha256=5SyeB5LxPN1tYrgIzTXj7d-xcJttC5qm1XtJrixUyoE,2317
22
+ naas_abi_core/engine/engine_configuration/EngineConfiguration_TripleStoreService.py,sha256=vIWO-RQ5BetHUcG0hfSnPCVzqopx2qO51e4axw7lEbc,7876
23
+ naas_abi_core/engine/engine_configuration/EngineConfiguration_TripleStoreService_test.py,sha256=Q8V_2urBgYhHbgcmlruxd9zV-YbQxdHT_V2SwM_oj2U,4026
24
+ naas_abi_core/engine/engine_configuration/EngineConfiguration_VectorStoreService.py,sha256=1Ulqtbjw9zAjdiXFyqVETtoY-xiqiauPH6GeuPGKiZg,2552
25
+ naas_abi_core/engine/engine_configuration/EngineConfiguration_VectorStoreService_test.py,sha256=hy6OLrn0L-dpcAprbRZLXdKPPgpK0F-gVOdahAvjbf0,1258
23
26
  naas_abi_core/engine/engine_configuration/EngineConfiguration_test.py,sha256=PL4A4Dawq6tfyHsiIkqbHhovc7wkIHcVZra6llRI-CY,286
24
27
  naas_abi_core/engine/engine_configuration/utils/PydanticModelValidator.py,sha256=jZzLqLvR8HawpyGYiUJEng3NlebLHiN3mVFOzNDSWs8,504
25
28
  naas_abi_core/engine/engine_loaders/EngineModuleLoader.py,sha256=4VsGtPsaeslej2JuyksHUbHJEY6J096cnr3iuTrhnpY,12043
@@ -67,17 +70,17 @@ naas_abi_core/services/ontology/OntologyPorts.py,sha256=CANMwmXps5k2IB1pq1I5723H
67
70
  naas_abi_core/services/ontology/OntologyService.py,sha256=-shSDmL5zvEvNjTbDQ1pq2ziwnJvfR-ka6XJh1AcDuA,542
68
71
  naas_abi_core/services/ontology/adaptors/secondary/OntologyService_SecondaryAdaptor_NERPort.py,sha256=CNGnlvtoADUki8fEWnanD4Xe7_osQrpWDusZOLu1mgo,1303
69
72
  naas_abi_core/services/secret/Secret.py,sha256=7odnAtpkC12laA8CFzE_W2NOFpDyaW2TmoebUCFMSQE,5159
70
- naas_abi_core/services/secret/SecretPorts.py,sha256=E-oBxE49OZmVYbKTwbtsuxjaU58tVXFBMbblmVVbd7k,996
73
+ naas_abi_core/services/secret/SecretPorts.py,sha256=4JnkU1dPC4_p_GweOxmfiEE5RxwZztjNo3Ygnwo2sLw,1087
71
74
  naas_abi_core/services/secret/Secret_test.py,sha256=rRLAsBCNDMduUwCeCSdlWtIFwguqFeVdRp-3lF6R9mc,1581
72
75
  naas_abi_core/services/secret/adaptors/secondary/Base64Secret.py,sha256=Py7bBEBnkaBnuD9wtXO_tMI5HiM7olspOvfBRRq57Tw,1967
73
76
  naas_abi_core/services/secret/adaptors/secondary/Base64Secret_test.py,sha256=wwdfMJrkh6vFZabZie9xyQHYlTjPAfouV-sPI4pk8MM,1287
74
- naas_abi_core/services/secret/adaptors/secondary/NaasSecret.py,sha256=b31HLYCN3JzYwlWwsiTlQ3FM7t9sLFz7dF3eMmFnA6c,2755
77
+ naas_abi_core/services/secret/adaptors/secondary/NaasSecret.py,sha256=YyJCcMWadsnBg-1jvGbsGqBelKbMwsPtLDXKm92Pbwo,3064
75
78
  naas_abi_core/services/secret/adaptors/secondary/NaasSecret_test.py,sha256=gR2hjU8e3hbkWn_suhwj4kfWLjTZjZavj-5R-z93zjU,625
76
79
  naas_abi_core/services/secret/adaptors/secondary/dotenv_secret_secondaryadaptor.py,sha256=jNs1bTz25lD0B5HZUKjenxZ7x6qUm9kIESFmh2-QDs8,909
77
80
  naas_abi_core/services/triple_store/TripleStoreFactory.py,sha256=4cCWJUhmXo5-yB61fyDwc-pigIYZo_PzmPW_5pY5I-E,4560
78
81
  naas_abi_core/services/triple_store/TripleStorePorts.py,sha256=dRhDc5-uiXDZQWzscqUd972EPi_pafPLkj4sXwxF8Xs,6681
79
82
  naas_abi_core/services/triple_store/TripleStoreService.py,sha256=X1ty-fH0A1XyLhZpU6oc3h-BgOoarAHSMPzITBBVhlY,16274
80
- naas_abi_core/services/triple_store/adaptors/secondary/AWSNeptune.py,sha256=fJlkf1QIOj4FCBCSotCfmlv15QtbKDFONcGVtu_W5v8,49390
83
+ naas_abi_core/services/triple_store/adaptors/secondary/AWSNeptune.py,sha256=kma8SUufwMkFA_xYaRcjV9jRsZ-UtUUdBlHEmKiMTVw,50222
81
84
  naas_abi_core/services/triple_store/adaptors/secondary/AWSNeptune_test.py,sha256=b9LiXwQ3EWem5T_OplJWgXQ-cPwkrfomKO5MQx6zwF4,7662
82
85
  naas_abi_core/services/triple_store/adaptors/secondary/Oxigraph.py,sha256=1VXtc-Ew7unmqULTA95nN8gnaYWP0Leb3rKbuWe1vRo,20729
83
86
  naas_abi_core/services/triple_store/adaptors/secondary/Oxigraph_test.py,sha256=oVyBHGYsrZn9HpzC4aRBi3w515yU0vXG8Yo1mIZN1hk,57224
@@ -99,7 +102,7 @@ naas_abi_core/utils/JSON.py,sha256=onIs-E3GWz4fvRuWBQpyb9qRNXCOJPf9x1yV1-jDlqU,1
99
102
  naas_abi_core/utils/LazyLoader.py,sha256=rWrnFVuKCK1WrtNgeiegT_i7AkxGy9qK2hfhsXV4dCY,1120
100
103
  naas_abi_core/utils/Logger.py,sha256=emZwe1EKAWcEegDQGFkr2U8vLX-oDUZXX580o9kP_xc,203
101
104
  naas_abi_core/utils/OntologyReasoner.py,sha256=OgDgiymd7HuDI28XZfcS2-9QeR7_jY9o9LWBQu2AU7k,4591
102
- naas_abi_core/utils/OntologyYaml.disabled.py,sha256=y5dYzD6w3yByQ4I-T6km6T2J0t-sTNy6iNm8ocpffyA,25246
105
+ naas_abi_core/utils/OntologyYaml.py,sha256=YcLC9FyGwwb7WCfV6fyniJFH6HMNfwyBDh6WgQYM3u4,25437
103
106
  naas_abi_core/utils/SPARQL.py,sha256=Yjk2INdNIUuv8P26-ToqNik5odyUroybzWvijMsfcns,9313
104
107
  naas_abi_core/utils/Storage.py,sha256=XgB8KcYgnF8armlvxJrZbJPcsnPSb8ByNCnVchFMpo4,1205
105
108
  naas_abi_core/utils/StorageUtils.py,sha256=WFGuUSe9u44BXLi5JqnVoHEGmWGpZTFUZv1empbe5dU,13654
@@ -114,7 +117,8 @@ naas_abi_core/utils/onto2py/tests/ttl2py_test.py,sha256=5OZqSxPffjJYiX9T4rT1mV0P
114
117
  naas_abi_core/workflow/__init__.py,sha256=hZD58mCB1PApxITqftP_xgjxL7NeLvOfI-rJENg1ENs,250
115
118
  naas_abi_core/workflow/workflow.py,sha256=ZufSS073JztVl0OQRTqNyK7FepFvv7gXlc4j5FAEZCI,1216
116
119
  assets/favicon.ico,sha256=nWk8wrHZiJV3DeuWrP2MqilXxCuoNWKGtMZfYmEVQLw,666
117
- naas_abi_core-1.2.1.dist-info/METADATA,sha256=2XbMeXhQxZjvSdFv5OfAppq6CjkTn2cqEoXFzb5pEtY,3897
118
- naas_abi_core-1.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
119
- naas_abi_core-1.2.1.dist-info/entry_points.txt,sha256=IX0WUFxZuo1JU6H66fcRR6y7gYChMVw_XA9suPk9_1Q,70
120
- naas_abi_core-1.2.1.dist-info/RECORD,,
120
+ assets/logo.png,sha256=zUu9sNgMmtzJhfNCinDs85GP1LDNVfTy8kYLKRT_pxA,9334
121
+ naas_abi_core-1.4.0.dist-info/METADATA,sha256=-dHvZP15mu5wBnRUM9A6cU385cGhffxRMLueNqfWjpw,4092
122
+ naas_abi_core-1.4.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
123
+ naas_abi_core-1.4.0.dist-info/entry_points.txt,sha256=IX0WUFxZuo1JU6H66fcRR6y7gYChMVw_XA9suPk9_1Q,70
124
+ naas_abi_core-1.4.0.dist-info/RECORD,,