struai 0.2.0__tar.gz → 1.0.2__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.
Files changed (30) hide show
  1. struai-1.0.2/.github/workflows/release.yml +139 -0
  2. struai-1.0.2/.pre-commit-config.yaml +13 -0
  3. struai-1.0.2/CHANGELOG.md +26 -0
  4. {struai-0.2.0 → struai-1.0.2}/PKG-INFO +55 -4
  5. {struai-0.2.0 → struai-1.0.2}/README.md +54 -3
  6. {struai-0.2.0 → struai-1.0.2}/js/README.md +30 -2
  7. {struai-0.2.0 → struai-1.0.2}/js/package.json +1 -1
  8. {struai-0.2.0 → struai-1.0.2}/js/src/index.ts +1 -1
  9. {struai-0.2.0 → struai-1.0.2}/pyproject.toml +13 -1
  10. {struai-0.2.0 → struai-1.0.2}/src/struai/__init__.py +29 -28
  11. {struai-0.2.0 → struai-1.0.2}/src/struai/_client.py +6 -3
  12. {struai-0.2.0 → struai-1.0.2}/src/struai/_version.py +1 -1
  13. {struai-0.2.0 → struai-1.0.2}/src/struai/models/common.py +1 -1
  14. struai-0.2.0/.github/workflows/publish-npm.yml +0 -68
  15. struai-0.2.0/.github/workflows/publish-python.yml +0 -54
  16. {struai-0.2.0 → struai-1.0.2}/.github/workflows/ci.yml +0 -0
  17. {struai-0.2.0 → struai-1.0.2}/.gitignore +0 -0
  18. {struai-0.2.0 → struai-1.0.2}/js/.gitignore +0 -0
  19. {struai-0.2.0 → struai-1.0.2}/js/tsconfig.json +0 -0
  20. {struai-0.2.0 → struai-1.0.2}/src/struai/_base.py +0 -0
  21. {struai-0.2.0 → struai-1.0.2}/src/struai/_exceptions.py +0 -0
  22. {struai-0.2.0 → struai-1.0.2}/src/struai/models/__init__.py +0 -0
  23. {struai-0.2.0 → struai-1.0.2}/src/struai/models/drawings.py +0 -0
  24. {struai-0.2.0 → struai-1.0.2}/src/struai/models/entities.py +0 -0
  25. {struai-0.2.0 → struai-1.0.2}/src/struai/models/projects.py +0 -0
  26. {struai-0.2.0 → struai-1.0.2}/src/struai/models/search.py +0 -0
  27. {struai-0.2.0 → struai-1.0.2}/src/struai/py.typed +0 -0
  28. {struai-0.2.0 → struai-1.0.2}/src/struai/resources/__init__.py +0 -0
  29. {struai-0.2.0 → struai-1.0.2}/src/struai/resources/drawings.py +0 -0
  30. {struai-0.2.0 → struai-1.0.2}/src/struai/resources/projects.py +0 -0
@@ -0,0 +1,139 @@
1
+ name: Release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ publish_only:
7
+ description: 'Just publish current version (skip version bump)'
8
+ required: false
9
+ default: 'false'
10
+ type: choice
11
+ options:
12
+ - 'false'
13
+ - 'true'
14
+ push:
15
+ branches: [main]
16
+
17
+ permissions:
18
+ contents: write
19
+ id-token: write
20
+
21
+ jobs:
22
+ release:
23
+ runs-on: ubuntu-latest
24
+ concurrency: release
25
+ if: github.repository_owner == 'bhoshaga' && inputs.publish_only != 'true'
26
+ outputs:
27
+ released: ${{ steps.version.outputs.release }}
28
+ version: ${{ steps.version.outputs.version }}
29
+
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ with:
33
+ fetch-depth: 0
34
+ token: ${{ secrets.GITHUB_TOKEN }}
35
+
36
+ - name: Set up Python
37
+ uses: actions/setup-python@v5
38
+ with:
39
+ python-version: '3.11'
40
+
41
+ - name: Set up Node.js
42
+ uses: actions/setup-node@v4
43
+ with:
44
+ node-version: '20'
45
+
46
+ - name: Install python-semantic-release
47
+ run: pip install python-semantic-release
48
+
49
+ - name: Get next version
50
+ id: version
51
+ run: |
52
+ # Get the next version without making changes
53
+ NEXT_VERSION=$(semantic-release version --print 2>/dev/null || echo "")
54
+ if [ -z "$NEXT_VERSION" ]; then
55
+ echo "No release needed"
56
+ echo "release=false" >> $GITHUB_OUTPUT
57
+ else
58
+ echo "Next version: $NEXT_VERSION"
59
+ echo "release=true" >> $GITHUB_OUTPUT
60
+ echo "version=$NEXT_VERSION" >> $GITHUB_OUTPUT
61
+ fi
62
+
63
+ - name: Update npm package version
64
+ if: steps.version.outputs.release == 'true'
65
+ run: |
66
+ cd js
67
+ npm version ${{ steps.version.outputs.version }} --no-git-tag-version
68
+
69
+ - name: Python Semantic Release
70
+ if: steps.version.outputs.release == 'true'
71
+ env:
72
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
73
+ run: |
74
+ git config user.name "github-actions[bot]"
75
+ git config user.email "github-actions[bot]@users.noreply.github.com"
76
+
77
+ # Add the npm package.json change
78
+ git add js/package.json
79
+
80
+ # Run semantic-release (will update Python version, commit, tag, and create release)
81
+ semantic-release version
82
+
83
+ # Push changes and tags
84
+ git push origin main --follow-tags
85
+
86
+ publish-python:
87
+ needs: release
88
+ if: always() && (needs.release.outputs.released == 'true' || inputs.publish_only == 'true')
89
+ runs-on: ubuntu-latest
90
+ environment: pypi
91
+ permissions:
92
+ id-token: write
93
+
94
+ steps:
95
+ - uses: actions/checkout@v4
96
+
97
+ - name: Set up Python
98
+ uses: actions/setup-python@v5
99
+ with:
100
+ python-version: '3.11'
101
+
102
+ - name: Install build tools
103
+ run: pip install build
104
+
105
+ - name: Build package
106
+ run: python -m build
107
+
108
+ - name: Publish to PyPI
109
+ uses: pypa/gh-action-pypi-publish@release/v1
110
+ with:
111
+ skip-existing: true
112
+
113
+ publish-npm:
114
+ needs: release
115
+ if: always() && (needs.release.outputs.released == 'true' || inputs.publish_only == 'true')
116
+ runs-on: ubuntu-latest
117
+ defaults:
118
+ run:
119
+ working-directory: js
120
+
121
+ steps:
122
+ - uses: actions/checkout@v4
123
+
124
+ - name: Set up Node.js
125
+ uses: actions/setup-node@v4
126
+ with:
127
+ node-version: '20'
128
+ registry-url: 'https://registry.npmjs.org'
129
+
130
+ - name: Install dependencies
131
+ run: npm install
132
+
133
+ - name: Build
134
+ run: npm run build
135
+
136
+ - name: Publish to npm
137
+ run: npm publish --access public
138
+ env:
139
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,13 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.9.4
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+
9
+ - repo: https://github.com/compilerla/conventional-pre-commit
10
+ rev: v3.6.0
11
+ hooks:
12
+ - id: conventional-pre-commit
13
+ stages: [commit-msg]
@@ -0,0 +1,26 @@
1
+ # CHANGELOG
2
+
3
+ <!-- version list -->
4
+
5
+ ## v1.0.2 (2026-02-04)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **ci**: Add publish_only option for re-publishing
10
+ ([`0806b1e`](https://github.com/bhoshaga/struai/commit/0806b1eb6dba6d518df9f43a199b9255d1776d6a))
11
+
12
+ - **ci**: Consolidate to single release workflow
13
+ ([`91e94b0`](https://github.com/bhoshaga/struai/commit/91e94b00f5eb6e123adb2cfae01a473ed4cd5cbd))
14
+
15
+
16
+ ## v1.0.1 (2026-02-04)
17
+
18
+ ### Bug Fixes
19
+
20
+ - **ci**: Include publish jobs directly in release workflow
21
+ ([`02436eb`](https://github.com/bhoshaga/struai/commit/02436eb55c63cbaa54eac8ca456a54d30125fada))
22
+
23
+
24
+ ## v1.0.0 (2026-02-04)
25
+
26
+ - Initial Release
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: struai
3
- Version: 0.2.0
3
+ Version: 1.0.2
4
4
  Summary: StruAI Drawing Analysis SDK - AI-powered construction drawing analysis
5
5
  Project-URL: Homepage, https://struai.com
6
6
  Project-URL: Documentation, https://docs.struai.com/python
@@ -42,13 +42,20 @@ pip install struai
42
42
 
43
43
  ## Quick Start
44
44
 
45
+ Get an API key from `stru.ai` and set it as an environment variable:
46
+
47
+ ```bash
48
+ export STRUAI_API_KEY="YOUR_API_KEY"
49
+ ```
50
+
45
51
  ```python
52
+ import os
46
53
  from struai import StruAI
47
54
 
48
- client = StruAI(api_key="sk-xxx") # or set STRUAI_API_KEY env var
55
+ client = StruAI(api_key=os.environ["STRUAI_API_KEY"])
49
56
 
50
57
  # Optional: override base URL (http://localhost:8000 or http://localhost:8000/v1)
51
- client = StruAI(api_key="sk-xxx", base_url="http://localhost:8000")
58
+ client = StruAI(api_key=os.environ["STRUAI_API_KEY"], base_url="http://localhost:8000")
52
59
  ```
53
60
 
54
61
  ## Tier 1: Raw Detection ($0.02/page)
@@ -76,6 +83,49 @@ drawing = client.drawings.get("drw_7f8a9b2c")
76
83
  client.drawings.delete("drw_7f8a9b2c")
77
84
  ```
78
85
 
86
+ ## HTTP Endpoints (Reference)
87
+
88
+ All endpoints are under `/v1`. Use `Authorization: Bearer <API_KEY>`.
89
+
90
+ Tier 1 (raw detection):
91
+ - `POST /v1/drawings` — multipart form with `file` (PDF) and `page` (1-indexed)
92
+ - `GET /v1/drawings/{id}`
93
+ - `DELETE /v1/drawings/{id}`
94
+
95
+ Tier 2 (graph + search):
96
+ - `POST /v1/projects`
97
+ - `GET /v1/projects`
98
+ - `GET /v1/projects/{id}`
99
+ - `DELETE /v1/projects/{id}`
100
+ - `POST /v1/projects/{project_id}/sheets` — multipart form with `file` + `page`
101
+ - `GET /v1/projects/{project_id}/jobs/{job_id}`
102
+ - `GET /v1/projects/{project_id}/sheets`
103
+ - `GET /v1/projects/{project_id}/sheets/{sheet_id}`
104
+ - `DELETE /v1/projects/{project_id}/sheets/{sheet_id}`
105
+ - `POST /v1/projects/{project_id}/search`
106
+ - `POST /v1/projects/{project_id}/query`
107
+ - `GET /v1/projects/{project_id}/entities`
108
+ - `GET /v1/projects/{project_id}/entities/{entity_id}`
109
+ - `GET /v1/projects/{project_id}/relationships`
110
+
111
+ Example (raw detection):
112
+
113
+ ```bash
114
+ curl -X POST "https://api.stru.ai/v1/drawings" \
115
+ -H "Authorization: Bearer YOUR_API_KEY" \
116
+ -F "file=@structural.pdf" \
117
+ -F "page=4"
118
+ ```
119
+
120
+ Example (project sheet ingestion):
121
+
122
+ ```bash
123
+ curl -X POST "https://api.stru.ai/v1/projects/{project_id}/sheets" \
124
+ -H "Authorization: Bearer YOUR_API_KEY" \
125
+ -F "file=@structural.pdf" \
126
+ -F "page=4"
127
+ ```
128
+
79
129
  ## Tier 2: Graph + Search ($0.15/page)
80
130
 
81
131
  Full pipeline: detection → LLM enrichment → knowledge graph → semantic search.
@@ -118,9 +168,10 @@ entity = project.entities.get("ent_abc123")
118
168
  ## Async Support
119
169
 
120
170
  ```python
171
+ import os
121
172
  from struai import AsyncStruAI
122
173
 
123
- async with AsyncStruAI(api_key="sk-xxx") as client:
174
+ async with AsyncStruAI(api_key=os.environ["STRUAI_API_KEY"]) as client:
124
175
  # Tier 1
125
176
  result = await client.drawings.analyze("structural.pdf", page=4)
126
177
 
@@ -10,13 +10,20 @@ pip install struai
10
10
 
11
11
  ## Quick Start
12
12
 
13
+ Get an API key from `stru.ai` and set it as an environment variable:
14
+
15
+ ```bash
16
+ export STRUAI_API_KEY="YOUR_API_KEY"
17
+ ```
18
+
13
19
  ```python
20
+ import os
14
21
  from struai import StruAI
15
22
 
16
- client = StruAI(api_key="sk-xxx") # or set STRUAI_API_KEY env var
23
+ client = StruAI(api_key=os.environ["STRUAI_API_KEY"])
17
24
 
18
25
  # Optional: override base URL (http://localhost:8000 or http://localhost:8000/v1)
19
- client = StruAI(api_key="sk-xxx", base_url="http://localhost:8000")
26
+ client = StruAI(api_key=os.environ["STRUAI_API_KEY"], base_url="http://localhost:8000")
20
27
  ```
21
28
 
22
29
  ## Tier 1: Raw Detection ($0.02/page)
@@ -44,6 +51,49 @@ drawing = client.drawings.get("drw_7f8a9b2c")
44
51
  client.drawings.delete("drw_7f8a9b2c")
45
52
  ```
46
53
 
54
+ ## HTTP Endpoints (Reference)
55
+
56
+ All endpoints are under `/v1`. Use `Authorization: Bearer <API_KEY>`.
57
+
58
+ Tier 1 (raw detection):
59
+ - `POST /v1/drawings` — multipart form with `file` (PDF) and `page` (1-indexed)
60
+ - `GET /v1/drawings/{id}`
61
+ - `DELETE /v1/drawings/{id}`
62
+
63
+ Tier 2 (graph + search):
64
+ - `POST /v1/projects`
65
+ - `GET /v1/projects`
66
+ - `GET /v1/projects/{id}`
67
+ - `DELETE /v1/projects/{id}`
68
+ - `POST /v1/projects/{project_id}/sheets` — multipart form with `file` + `page`
69
+ - `GET /v1/projects/{project_id}/jobs/{job_id}`
70
+ - `GET /v1/projects/{project_id}/sheets`
71
+ - `GET /v1/projects/{project_id}/sheets/{sheet_id}`
72
+ - `DELETE /v1/projects/{project_id}/sheets/{sheet_id}`
73
+ - `POST /v1/projects/{project_id}/search`
74
+ - `POST /v1/projects/{project_id}/query`
75
+ - `GET /v1/projects/{project_id}/entities`
76
+ - `GET /v1/projects/{project_id}/entities/{entity_id}`
77
+ - `GET /v1/projects/{project_id}/relationships`
78
+
79
+ Example (raw detection):
80
+
81
+ ```bash
82
+ curl -X POST "https://api.stru.ai/v1/drawings" \
83
+ -H "Authorization: Bearer YOUR_API_KEY" \
84
+ -F "file=@structural.pdf" \
85
+ -F "page=4"
86
+ ```
87
+
88
+ Example (project sheet ingestion):
89
+
90
+ ```bash
91
+ curl -X POST "https://api.stru.ai/v1/projects/{project_id}/sheets" \
92
+ -H "Authorization: Bearer YOUR_API_KEY" \
93
+ -F "file=@structural.pdf" \
94
+ -F "page=4"
95
+ ```
96
+
47
97
  ## Tier 2: Graph + Search ($0.15/page)
48
98
 
49
99
  Full pipeline: detection → LLM enrichment → knowledge graph → semantic search.
@@ -86,9 +136,10 @@ entity = project.entities.get("ent_abc123")
86
136
  ## Async Support
87
137
 
88
138
  ```python
139
+ import os
89
140
  from struai import AsyncStruAI
90
141
 
91
- async with AsyncStruAI(api_key="sk-xxx") as client:
142
+ async with AsyncStruAI(api_key=os.environ["STRUAI_API_KEY"]) as client:
92
143
  # Tier 1
93
144
  result = await client.drawings.analyze("structural.pdf", page=4)
94
145
 
@@ -12,13 +12,16 @@ npm install struai
12
12
 
13
13
  ## Quick Start
14
14
 
15
+ Get an API key from `stru.ai` and set `STRUAI_API_KEY`.
16
+
15
17
  ```typescript
16
18
  import { StruAI } from 'struai';
17
19
 
18
- const client = new StruAI({ apiKey: 'sk-xxx' });
20
+ // Get an API key from stru.ai and set STRUAI_API_KEY
21
+ const client = new StruAI({ apiKey: process.env.STRUAI_API_KEY! });
19
22
 
20
23
  // Optional: override base URL (http://localhost:8000 or http://localhost:8000/v1)
21
- const local = new StruAI({ apiKey: 'sk-xxx', baseUrl: 'http://localhost:8000' });
24
+ const local = new StruAI({ apiKey: process.env.STRUAI_API_KEY!, baseUrl: 'http://localhost:8000' });
22
25
  ```
23
26
 
24
27
  ## Tier 1: Raw Detection ($0.02/page)
@@ -68,6 +71,31 @@ const entities = await project.entities.list({ type: 'Component', limit: 50 });
68
71
  const entity = await project.entities.get('ent_abc123');
69
72
  ```
70
73
 
74
+ ## HTTP Endpoints (Reference)
75
+
76
+ All endpoints are under `/v1`. Use `Authorization: Bearer <API_KEY>`.
77
+
78
+ Tier 1 (raw detection):
79
+ - `POST /v1/drawings` — multipart form with `file` (PDF) and `page` (1-indexed)
80
+ - `GET /v1/drawings/{id}`
81
+ - `DELETE /v1/drawings/{id}`
82
+
83
+ Tier 2 (graph + search):
84
+ - `POST /v1/projects`
85
+ - `GET /v1/projects`
86
+ - `GET /v1/projects/{id}`
87
+ - `DELETE /v1/projects/{id}`
88
+ - `POST /v1/projects/{project_id}/sheets` — multipart form with `file` + `page`
89
+ - `GET /v1/projects/{project_id}/jobs/{job_id}`
90
+ - `GET /v1/projects/{project_id}/sheets`
91
+ - `GET /v1/projects/{project_id}/sheets/{sheet_id}`
92
+ - `DELETE /v1/projects/{project_id}/sheets/{sheet_id}`
93
+ - `POST /v1/projects/{project_id}/search`
94
+ - `POST /v1/projects/{project_id}/query`
95
+ - `GET /v1/projects/{project_id}/entities`
96
+ - `GET /v1/projects/{project_id}/entities/{entity_id}`
97
+ - `GET /v1/projects/{project_id}/relationships`
98
+
71
99
  ## License
72
100
 
73
101
  MIT
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "struai",
3
- "version": "0.2.0",
3
+ "version": "1.0.2",
4
4
  "description": "StruAI Drawing Analysis SDK - AI-powered construction drawing analysis",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -5,7 +5,7 @@
5
5
  * ```typescript
6
6
  * import { StruAI } from 'struai';
7
7
  *
8
- * const client = new StruAI({ apiKey: 'sk-xxx' });
8
+ * const client = new StruAI({ apiKey: process.env.STRUAI_API_KEY });
9
9
  *
10
10
  * // Tier 1: Raw detection
11
11
  * const result = await client.drawings.analyze('structural.pdf', { page: 4 });
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "struai"
7
- version = "0.2.0"
7
+ version = "1.0.2"
8
8
  description = "StruAI Drawing Analysis SDK - AI-powered construction drawing analysis"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -72,3 +72,15 @@ warn_unused_ignores = true
72
72
 
73
73
  [tool.pytest.ini_options]
74
74
  asyncio_mode = "auto"
75
+
76
+ [tool.semantic_release]
77
+ version_toml = ["pyproject.toml:project.version"]
78
+ version_variables = ["src/struai/_version.py:__version__"]
79
+ branch = "main"
80
+ build_command = "pip install build && python -m build"
81
+ commit_message = "chore(release): {version}\n\nAutomatically generated by python-semantic-release"
82
+
83
+ [tool.semantic_release.commit_parser_options]
84
+ allowed_tags = ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test"]
85
+ minor_tags = ["feat"]
86
+ patch_tags = ["fix", "perf"]
@@ -1,9 +1,10 @@
1
1
  """StruAI Python SDK - Drawing Analysis API client.
2
2
 
3
3
  Example:
4
+ >>> import os
4
5
  >>> from struai import StruAI
5
6
  >>>
6
- >>> client = StruAI(api_key="sk-xxx")
7
+ >>> client = StruAI(api_key=os.environ["STRUAI_API_KEY"])
7
8
  >>>
8
9
  >>> # Tier 1: Raw detection ($0.02/page)
9
10
  >>> result = client.drawings.analyze("plans.pdf", page=4)
@@ -17,52 +18,52 @@ Example:
17
18
  >>> results = project.search("W12x26 beam connections")
18
19
  """
19
20
 
20
- from ._version import __version__
21
- from ._client import StruAI, AsyncStruAI
21
+ from ._client import AsyncStruAI, StruAI
22
22
  from ._exceptions import (
23
- StruAIError,
24
23
  APIError,
25
24
  AuthenticationError,
26
- PermissionDeniedError,
25
+ ConnectionError,
26
+ InternalServerError,
27
+ JobFailedError,
27
28
  NotFoundError,
28
- ValidationError,
29
+ PermissionDeniedError,
29
30
  RateLimitError,
30
- InternalServerError,
31
+ StruAIError,
31
32
  TimeoutError,
32
- ConnectionError,
33
- JobFailedError,
33
+ ValidationError,
34
34
  )
35
+ from ._version import __version__
35
36
 
36
37
  # Re-export commonly used models
37
38
  from .models import (
38
- # Common
39
- Point,
39
+ Annotations,
40
40
  BBox,
41
- TextSpan,
41
+ DetailTag,
42
42
  Dimensions,
43
43
  # Tier 1 - Drawings
44
44
  DrawingResult,
45
- Annotations,
46
- Leader,
47
- SectionTag,
48
- DetailTag,
49
- RevisionTriangle,
50
- RevisionCloud,
51
- TitleBlock,
52
- # Tier 2 - Projects
53
- Project,
54
- Sheet,
55
- JobStatus,
56
- SheetResult,
57
- # Search
58
- SearchResponse,
59
- SearchHit,
60
- QueryResponse,
61
45
  # Entities
62
46
  Entity,
63
47
  EntityListItem,
64
48
  EntityRelation,
65
49
  Fact,
50
+ JobStatus,
51
+ Leader,
52
+ # Common
53
+ Point,
54
+ # Tier 2 - Projects
55
+ Project,
56
+ QueryResponse,
57
+ RevisionCloud,
58
+ RevisionTriangle,
59
+ SearchHit,
60
+ # Search
61
+ SearchResponse,
62
+ SectionTag,
63
+ Sheet,
64
+ SheetResult,
65
+ TextSpan,
66
+ TitleBlock,
66
67
  )
67
68
 
68
69
  __all__ = [
@@ -1,9 +1,10 @@
1
1
  """Main StruAI client classes."""
2
+
2
3
  import os
3
4
  from functools import cached_property
4
5
  from typing import Optional
5
6
 
6
- from ._base import AsyncBaseClient, BaseClient, DEFAULT_BASE_URL, DEFAULT_TIMEOUT
7
+ from ._base import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, AsyncBaseClient, BaseClient
7
8
  from ._exceptions import StruAIError
8
9
  from .resources.drawings import AsyncDrawings, Drawings
9
10
  from .resources.projects import AsyncProjects, Projects
@@ -20,7 +21,8 @@ class StruAI(BaseClient):
20
21
  max_retries: Max retry attempts for failed requests. Default 2.
21
22
 
22
23
  Example:
23
- >>> client = StruAI(api_key="sk-xxx")
24
+ >>> import os
25
+ >>> client = StruAI(api_key=os.environ["STRUAI_API_KEY"])
24
26
  >>>
25
27
  >>> # Tier 1: Raw detection
26
28
  >>> result = client.drawings.analyze("structural.pdf", page=4)
@@ -71,7 +73,8 @@ class AsyncStruAI(AsyncBaseClient):
71
73
  """Async StruAI client for drawing analysis API.
72
74
 
73
75
  Example:
74
- >>> async with AsyncStruAI(api_key="sk-xxx") as client:
76
+ >>> import os
77
+ >>> async with AsyncStruAI(api_key=os.environ["STRUAI_API_KEY"]) as client:
75
78
  ... result = await client.drawings.analyze("structural.pdf", page=4)
76
79
  ...
77
80
  ... project = await client.projects.create("Building A")
@@ -1,2 +1,2 @@
1
1
  """Version information."""
2
- __version__ = "0.2.0"
2
+ __version__ = "1.0.2"
@@ -1,5 +1,5 @@
1
1
  """Common types shared across models."""
2
- from typing import List, Tuple
2
+ from typing import Tuple
3
3
 
4
4
  from pydantic import BaseModel
5
5
 
@@ -1,68 +0,0 @@
1
- name: Publish npm Package
2
-
3
- on:
4
- workflow_dispatch:
5
- push:
6
- branches: [main]
7
- paths:
8
- - 'js/**'
9
- - '.github/workflows/publish-npm.yml'
10
- release:
11
- types: [published]
12
-
13
- jobs:
14
- build:
15
- runs-on: ubuntu-latest
16
- defaults:
17
- run:
18
- working-directory: js
19
- steps:
20
- - uses: actions/checkout@v4
21
-
22
- - name: Set up Node.js
23
- uses: actions/setup-node@v4
24
- with:
25
- node-version: '20'
26
- registry-url: 'https://registry.npmjs.org'
27
-
28
- - name: Install dependencies
29
- run: npm install
30
-
31
- - name: Build
32
- run: npm run build
33
-
34
- - name: Upload artifacts
35
- uses: actions/upload-artifact@v4
36
- with:
37
- name: npm-dist
38
- path: js/dist/
39
-
40
- publish:
41
- needs: build
42
- runs-on: ubuntu-latest
43
- if: github.event_name == 'release' || github.ref == 'refs/heads/main'
44
- defaults:
45
- run:
46
- working-directory: js
47
- steps:
48
- - uses: actions/checkout@v4
49
-
50
- - name: Set up Node.js
51
- uses: actions/setup-node@v4
52
- with:
53
- node-version: '20'
54
- registry-url: 'https://registry.npmjs.org'
55
-
56
- - name: Install dependencies
57
- run: npm install
58
-
59
- - name: Download artifacts
60
- uses: actions/download-artifact@v4
61
- with:
62
- name: npm-dist
63
- path: js/dist/
64
-
65
- - name: Publish to npm
66
- run: npm publish --access public
67
- env:
68
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,54 +0,0 @@
1
- name: Publish Python Package
2
-
3
- on:
4
- workflow_dispatch:
5
- push:
6
- branches: [main]
7
- paths:
8
- - 'src/**'
9
- - 'pyproject.toml'
10
- - '.github/workflows/publish-python.yml'
11
- release:
12
- types: [published]
13
-
14
- jobs:
15
- build:
16
- runs-on: ubuntu-latest
17
- steps:
18
- - uses: actions/checkout@v4
19
-
20
- - name: Set up Python
21
- uses: actions/setup-python@v5
22
- with:
23
- python-version: '3.11'
24
-
25
- - name: Install build tools
26
- run: pip install build twine
27
-
28
- - name: Build package
29
- run: python -m build
30
-
31
- - name: Upload artifacts
32
- uses: actions/upload-artifact@v4
33
- with:
34
- name: python-dist
35
- path: dist/
36
-
37
- publish:
38
- needs: build
39
- runs-on: ubuntu-latest
40
- if: github.event_name == 'release' || github.ref == 'refs/heads/main'
41
- environment: pypi
42
- permissions:
43
- id-token: write
44
- steps:
45
- - name: Download artifacts
46
- uses: actions/download-artifact@v4
47
- with:
48
- name: python-dist
49
- path: dist/
50
-
51
- - name: Publish to PyPI
52
- uses: pypa/gh-action-pypi-publish@release/v1
53
- with:
54
- skip-existing: true
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes