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.
- struai-1.0.2/.github/workflows/release.yml +139 -0
- struai-1.0.2/.pre-commit-config.yaml +13 -0
- struai-1.0.2/CHANGELOG.md +26 -0
- {struai-0.2.0 → struai-1.0.2}/PKG-INFO +55 -4
- {struai-0.2.0 → struai-1.0.2}/README.md +54 -3
- {struai-0.2.0 → struai-1.0.2}/js/README.md +30 -2
- {struai-0.2.0 → struai-1.0.2}/js/package.json +1 -1
- {struai-0.2.0 → struai-1.0.2}/js/src/index.ts +1 -1
- {struai-0.2.0 → struai-1.0.2}/pyproject.toml +13 -1
- {struai-0.2.0 → struai-1.0.2}/src/struai/__init__.py +29 -28
- {struai-0.2.0 → struai-1.0.2}/src/struai/_client.py +6 -3
- {struai-0.2.0 → struai-1.0.2}/src/struai/_version.py +1 -1
- {struai-0.2.0 → struai-1.0.2}/src/struai/models/common.py +1 -1
- struai-0.2.0/.github/workflows/publish-npm.yml +0 -68
- struai-0.2.0/.github/workflows/publish-python.yml +0 -54
- {struai-0.2.0 → struai-1.0.2}/.github/workflows/ci.yml +0 -0
- {struai-0.2.0 → struai-1.0.2}/.gitignore +0 -0
- {struai-0.2.0 → struai-1.0.2}/js/.gitignore +0 -0
- {struai-0.2.0 → struai-1.0.2}/js/tsconfig.json +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/_base.py +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/_exceptions.py +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/models/__init__.py +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/models/drawings.py +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/models/entities.py +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/models/projects.py +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/models/search.py +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/py.typed +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/resources/__init__.py +0 -0
- {struai-0.2.0 → struai-1.0.2}/src/struai/resources/drawings.py +0 -0
- {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
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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
|
-
|
|
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:
|
|
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
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* ```typescript
|
|
6
6
|
* import { StruAI } from 'struai';
|
|
7
7
|
*
|
|
8
|
-
* const client = new StruAI({ apiKey:
|
|
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
|
|
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="
|
|
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 .
|
|
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
|
-
|
|
25
|
+
ConnectionError,
|
|
26
|
+
InternalServerError,
|
|
27
|
+
JobFailedError,
|
|
27
28
|
NotFoundError,
|
|
28
|
-
|
|
29
|
+
PermissionDeniedError,
|
|
29
30
|
RateLimitError,
|
|
30
|
-
|
|
31
|
+
StruAIError,
|
|
31
32
|
TimeoutError,
|
|
32
|
-
|
|
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
|
-
|
|
39
|
-
Point,
|
|
39
|
+
Annotations,
|
|
40
40
|
BBox,
|
|
41
|
-
|
|
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
|
|
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
|
-
>>>
|
|
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
|
-
>>>
|
|
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
|
|
2
|
+
__version__ = "1.0.2"
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|