heyarchie 1.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.
Files changed (46) hide show
  1. heyarchie-1.0.0/.gitignore +217 -0
  2. heyarchie-1.0.0/PKG-INFO +74 -0
  3. heyarchie-1.0.0/README.md +36 -0
  4. heyarchie-1.0.0/examples/native_desktop_smoke.py +214 -0
  5. heyarchie-1.0.0/heyarchie/__init__.py +197 -0
  6. heyarchie-1.0.0/heyarchie/_http.py +316 -0
  7. heyarchie-1.0.0/heyarchie/adapters/__init__.py +26 -0
  8. heyarchie-1.0.0/heyarchie/adapters/_base.py +218 -0
  9. heyarchie-1.0.0/heyarchie/adapters/langchain.py +68 -0
  10. heyarchie-1.0.0/heyarchie/adapters/langgraph.py +133 -0
  11. heyarchie-1.0.0/heyarchie/adapters/openai_agents.py +99 -0
  12. heyarchie-1.0.0/heyarchie/cli/__init__.py +14 -0
  13. heyarchie-1.0.0/heyarchie/cli/__main__.py +35 -0
  14. heyarchie-1.0.0/heyarchie/cli/_client.py +179 -0
  15. heyarchie-1.0.0/heyarchie/cli/auth.py +101 -0
  16. heyarchie-1.0.0/heyarchie/cli/cmds/__init__.py +1 -0
  17. heyarchie-1.0.0/heyarchie/cli/cmds/login.py +46 -0
  18. heyarchie-1.0.0/heyarchie/cli/cmds/skills.py +233 -0
  19. heyarchie-1.0.0/heyarchie/cli/cmds/workstreams.py +298 -0
  20. heyarchie-1.0.0/heyarchie/client.py +313 -0
  21. heyarchie-1.0.0/heyarchie/errors.py +75 -0
  22. heyarchie-1.0.0/heyarchie/models.py +455 -0
  23. heyarchie-1.0.0/heyarchie/resources/__init__.py +39 -0
  24. heyarchie-1.0.0/heyarchie/resources/conversations.py +260 -0
  25. heyarchie-1.0.0/heyarchie/resources/documents.py +81 -0
  26. heyarchie-1.0.0/heyarchie/resources/drafts.py +121 -0
  27. heyarchie-1.0.0/heyarchie/resources/journal_entries.py +98 -0
  28. heyarchie-1.0.0/heyarchie/resources/keys.py +107 -0
  29. heyarchie-1.0.0/heyarchie/resources/messages.py +120 -0
  30. heyarchie-1.0.0/heyarchie/resources/reports.py +82 -0
  31. heyarchie-1.0.0/heyarchie/resources/search.py +81 -0
  32. heyarchie-1.0.0/heyarchie/resources/skills.py +381 -0
  33. heyarchie-1.0.0/heyarchie/resources/standards.py +76 -0
  34. heyarchie-1.0.0/heyarchie/resources/triggers.py +130 -0
  35. heyarchie-1.0.0/heyarchie/resources/workstreams.py +717 -0
  36. heyarchie-1.0.0/pyproject.toml +57 -0
  37. heyarchie-1.0.0/tests/__init__.py +0 -0
  38. heyarchie-1.0.0/tests/cli/__init__.py +0 -0
  39. heyarchie-1.0.0/tests/cli/test_auth.py +89 -0
  40. heyarchie-1.0.0/tests/cli/test_skills.py +76 -0
  41. heyarchie-1.0.0/tests/test_client.py +204 -0
  42. heyarchie-1.0.0/tests/test_messages.py +228 -0
  43. heyarchie-1.0.0/tests/test_streaming.py +110 -0
  44. heyarchie-1.0.0/tests/test_workstreams_cycles.py +206 -0
  45. heyarchie-1.0.0/tests/test_workstreams_namespaces.py +110 -0
  46. heyarchie-1.0.0/uv.lock +423 -0
@@ -0,0 +1,217 @@
1
+ # Agent 365 CLI generated config — contains plaintext client secret on non-Windows
2
+ a365.generated.config.json
3
+ # Root-level a365.config.json auto-created by CLI; canonical config lives at apps/api/a365.config.json
4
+ /a365.config.json
5
+
6
+ # Node.js dependencies
7
+ node_modules/
8
+ **/node_modules/
9
+
10
+ # pnpm
11
+ .pnpm-store/
12
+
13
+
14
+ # Linear Integration
15
+ .env
16
+ .env.*
17
+ !.env.example
18
+ !.env.vault.example
19
+ !.env.test
20
+ !.env.observability.example
21
+ linear-tickets.json
22
+ linear-issue-mapping.json
23
+ *.tickets.json
24
+ .cloudflare_credentials
25
+
26
+ # Deleted orchestrator — V2 killed, V3 renamed to orchestrator/. Never re-add.
27
+ **/orchestrator_v3/
28
+ **/orchestrator_v2/
29
+
30
+ # Workstream Studio build artifacts + Playwright run output. Never commit.
31
+ apps/workstream-studio/dist/
32
+ apps/workstream-studio/e2e/screenshots/
33
+ apps/workstream-studio/e2e/test-results/
34
+ apps/workstream-studio/playwright-report/
35
+ apps/workstream-studio/test-results/
36
+
37
+ # Python Environment (UV + Ruff)
38
+ .venv/
39
+ venv/
40
+ __pycache__/
41
+ *.pyc
42
+ *.pyo
43
+ *.pyd
44
+ .Python
45
+ pip-log.txt
46
+ pip-delete-this-directory.txt
47
+ .pytest_cache/
48
+ .mypy_cache/
49
+ .ruff_cache/
50
+ htmlcov/
51
+ .coverage
52
+ .coverage.*
53
+ coverage.xml
54
+ *.cover
55
+ .hypothesis/
56
+
57
+ # File Ingestion Service - Test files and uploads
58
+ src/services/file-ingestion/test_*.py
59
+ src/services/file-ingestion/test_*.json
60
+ src/services/file-ingestion/data/uploads/
61
+ src/services/file-ingestion/seeds/
62
+ src/services/file-ingestion/examples/
63
+
64
+ # Test scripts and temporary files (root level only, not in tests/ directories)
65
+ /test_*.py
66
+ /test-*.sh
67
+ /start-*.sh
68
+ /stop-*.sh
69
+
70
+ # macOS
71
+ .DS_Store
72
+
73
+ # Vite build artifacts
74
+ **/node_modules/.vite/
75
+ **/node_modules/.vite/deps_temp_*
76
+
77
+ # Build artifacts
78
+ /dist
79
+ apps/teams/dist/
80
+
81
+ # .NET build output
82
+ **/bin/
83
+ **/obj/
84
+
85
+ # Terraform local environments
86
+ /terraform/environments/dev
87
+
88
+ # Playwright test results and reports
89
+ test-results/
90
+ playwright-report/
91
+
92
+ # Claude Flow generated files
93
+ .claude/settings.local.json
94
+ .mcp.json
95
+ claude-flow.config.json
96
+ .swarm/
97
+ .hive-mind/
98
+ .claude-flow/
99
+ memory/
100
+ coordination/
101
+ # Allow the orchestrator memory module (Python package, not claude-flow data)
102
+ !apps/api/src/orchestrator/memory/
103
+ # Same module after the V4 consolidation move (Epic 14 issue #3517).
104
+ !apps/api/src/orchestrator/v4/memory/
105
+ # Allow the scoped memory services module (Epic aemm00l)
106
+ !apps/api/src/services/memory/
107
+ # Allow memory unit tests
108
+ !tests/unit/memory/
109
+ !apps/api/tests/orchestrator/memory/
110
+ memory/claude-flow-data.json
111
+ memory/sessions/*
112
+ !memory/sessions/README.md
113
+ memory/agents/*
114
+ !memory/agents/README.md
115
+ coordination/memory_bank/*
116
+ coordination/subtasks/*
117
+ coordination/orchestration/*
118
+ *.db
119
+ *.db-journal
120
+ *.db-wal
121
+ *.sqlite
122
+ *.sqlite-journal
123
+ *.sqlite-wal
124
+ claude-flow
125
+ # Removed Windows wrapper files per user request
126
+ hive-mind-prompt-*.txt
127
+
128
+ # Infrastructure files with secrets (do not commit)
129
+ infrastructure/docker/migration-job.yaml
130
+
131
+ # Playwright auth state (generated at runtime, contains session tokens)
132
+ tests/e2e/.auth/user.json
133
+ tests/smoke/.auth/user.json
134
+
135
+ # Frontend lock file
136
+ apps/frontend/package-lock.json
137
+
138
+ # Martha test workflow tracker
139
+ .test-tracker.json
140
+
141
+ # Worktree-specific configuration
142
+ .worktree-config.json
143
+
144
+ # Test reports (generated by pytest)
145
+ apps/api/reports/
146
+ **/reports/*.xml
147
+ **/reports/*.html
148
+ .env.copilot-tests
149
+
150
+ # Sidebar v2 sample files (do not commit)
151
+ .archie-sidebar-v2-samples/
152
+ ~/.archie-sidebar-v2-samples/
153
+
154
+ # GitHub Actions local secrets
155
+ .act.secrets
156
+
157
+ # CEA manifest packages (built from manifest source files)
158
+ apps/archie-m365/manifest/archie-cea-*.zip
159
+ apps/archie-m365/manifest-da/archie-da-*.zip
160
+ apps/api/static/archie-cea-*.zip
161
+
162
+ # OpenAPI Generator CLI config (tool-specific)
163
+ openapitools.json
164
+
165
+ # Smoke test tracking
166
+ .smoke-tracker.json
167
+
168
+ # Render environment file (contains secrets - DO NOT COMMIT)
169
+ env.render
170
+ *.render.env
171
+
172
+ # UI library build output
173
+ packages/ui/dist/
174
+ packages/ui/storybook-static/
175
+
176
+ # Windows desktop app build artifacts (Inno Setup installer + staging)
177
+ apps/archie-desktop-win/dist/
178
+ apps/archie-desktop-win/ArchieDesktop/bin/
179
+ apps/archie-desktop-win/ArchieDesktop/obj/
180
+
181
+ # Script output (locale comparisons, debug exports)
182
+ scripts/output/
183
+
184
+ # Rust/Tauri build artifacts
185
+ **/target/
186
+ **/src-tauri/target/
187
+ Cargo.lock
188
+ !apps/workstreams-studio/src-tauri/Cargo.lock
189
+
190
+ # Auto-generated by sprite executor
191
+ .claude-task-*
192
+ .claude/worktrees/
193
+
194
+ # Deleted standalone orchestrator service — do not re-add
195
+ services/orchestrator/
196
+ .claude/plans/
197
+ .claude/scheduled_tasks.lock
198
+ # Playwright MCP browser test artifacts
199
+ .playwright-mcp/
200
+ apps/developers-portal/.next
201
+ tsconfig.tsbuildinfo
202
+ apps/developers-portal/next-env.d.ts
203
+
204
+ # Martha active-issue marker (per-session, never tracked)
205
+ .claude/active-issue
206
+ .claude/.turn-needs-martha
207
+ .claude/.last-martha-update
208
+
209
+ # Orchestrator V4 autonomous build loop — append-only journal + pause flag
210
+ # Journal lives at worktree root (not .claude/) so it bypasses Claude Code's
211
+ # .claude/ sensitivity prompts.
212
+ orchv4-build-journal.md
213
+ orchv4-interior-journal.md
214
+ .claude/orchv4-PAUSE
215
+ .claude/orchv4-interior-PAUSE
216
+ .env.test
217
+ .alpha-deploy-state/
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.4
2
+ Name: heyarchie
3
+ Version: 1.0.0
4
+ Summary: Python SDK + CLI for Archie — accounting AI. `import heyarchie` for the SDK; `archie` for the CLI.
5
+ Project-URL: Homepage, https://developers.heyarchie.ai
6
+ Project-URL: Documentation, https://developers.heyarchie.ai/docs/sdk/python
7
+ Project-URL: Source, https://github.com/heyarchie-ai/archie-platform-v2/tree/alpha/apps/sdk-python
8
+ Author-email: Archie <hey@archie.ai>
9
+ License: MIT
10
+ Keywords: accounting,ai,api,archie,cli,sdk
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Office/Business :: Financial :: Accounting
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: click<9.0,>=8.1
23
+ Requires-Dist: httpx<1.0,>=0.28
24
+ Requires-Dist: pydantic<3.0,>=2.9
25
+ Requires-Dist: rich<15.0,>=13.7
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
28
+ Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
29
+ Requires-Dist: pytest>=8.0; extra == 'dev'
30
+ Requires-Dist: respx>=0.22; extra == 'dev'
31
+ Requires-Dist: ruff>=0.6; extra == 'dev'
32
+ Provides-Extra: langchain
33
+ Requires-Dist: langchain-core>=0.3; extra == 'langchain'
34
+ Requires-Dist: langgraph>=0.2; extra == 'langchain'
35
+ Provides-Extra: openai-agents
36
+ Requires-Dist: openai-agents>=0.1; extra == 'openai-agents'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # heyarchie
40
+
41
+ Python SDK for the [Archie Connect API](https://developers.heyarchie.ai/docs/api-reference).
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ pip install heyarchie
47
+ ```
48
+
49
+ ## Quick start
50
+
51
+ ```python
52
+ import heyarchie
53
+
54
+ archie = heyarchie.Archie(api_key="ak_test_...")
55
+ message = archie.messages.create(
56
+ "Summarise the BAS for Q1 2026",
57
+ client_id="client_test_growthwise",
58
+ )
59
+ print(message.content)
60
+ ```
61
+
62
+ ## Async
63
+
64
+ ```python
65
+ import asyncio
66
+ import heyarchie
67
+
68
+ async def main():
69
+ async with heyarchie.AsyncArchie(api_key="ak_test_...") as archie:
70
+ message = await archie.messages.create("Summarise BAS Q1 2026")
71
+ print(message.content)
72
+
73
+ asyncio.run(main())
74
+ ```
@@ -0,0 +1,36 @@
1
+ # heyarchie
2
+
3
+ Python SDK for the [Archie Connect API](https://developers.heyarchie.ai/docs/api-reference).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install heyarchie
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```python
14
+ import heyarchie
15
+
16
+ archie = heyarchie.Archie(api_key="ak_test_...")
17
+ message = archie.messages.create(
18
+ "Summarise the BAS for Q1 2026",
19
+ client_id="client_test_growthwise",
20
+ )
21
+ print(message.content)
22
+ ```
23
+
24
+ ## Async
25
+
26
+ ```python
27
+ import asyncio
28
+ import heyarchie
29
+
30
+ async def main():
31
+ async with heyarchie.AsyncArchie(api_key="ak_test_...") as archie:
32
+ message = await archie.messages.create("Summarise BAS Q1 2026")
33
+ print(message.content)
34
+
35
+ asyncio.run(main())
36
+ ```
@@ -0,0 +1,214 @@
1
+ #!/usr/bin/env python3
2
+ """End-to-end smoke harness for the Archie Native Desktop contract surface.
3
+
4
+ Exercises the four N1-N4 endpoints introduced for AND in PR #3140 plus the
5
+ COL/IM endpoints from #3134 that AND-TX builds against.
6
+
7
+ Usage::
8
+
9
+ python apps/sdk-python/examples/native_desktop_smoke.py \\
10
+ --base-url http://localhost:8001 \\
11
+ --token dev-mock-token-for-local-testing
12
+
13
+ Exit code 0 = all checkpoints passed.
14
+
15
+ The harness uses the raw HTTP client (httpx) rather than the generated
16
+ SDK resource classes because:
17
+ 1. The SSE sync stream is most naturally consumed as a long-lived stream,
18
+ not a one-shot resource call.
19
+ 2. PKCE auth needs the native client to manage code_verifier locally —
20
+ wrapping it in a one-line SDK call would hide the security model.
21
+ 3. Demonstrates exactly the wire format AND will speak.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import argparse
27
+ import asyncio
28
+ import contextlib
29
+ import json
30
+ import sys
31
+ from datetime import datetime
32
+ from typing import Any
33
+
34
+ import httpx
35
+
36
+
37
+ CHECKPOINT_OK = " ✓"
38
+ CHECKPOINT_FAIL = " ✗"
39
+
40
+
41
+ class SmokeFailure(Exception):
42
+ pass
43
+
44
+
45
+ def expect(condition: bool, label: str, *, fatal: bool = True) -> None:
46
+ if condition:
47
+ print(f"{CHECKPOINT_OK} {label}")
48
+ return
49
+ print(f"{CHECKPOINT_FAIL} {label}")
50
+ if fatal:
51
+ raise SmokeFailure(label)
52
+
53
+
54
+ async def run(base_url: str, token: str) -> int:
55
+ headers = {"Authorization": f"Bearer {token}"}
56
+ async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=15.0) as http:
57
+ # 0. Health
58
+ r = await http.get("/health")
59
+ expect(r.status_code == 200, f"health 200 (got {r.status_code})")
60
+
61
+ # 1. PKCE login URL — verifies desktop scheme is allowlisted
62
+ import base64
63
+ import hashlib
64
+ import secrets
65
+
66
+ verifier = secrets.token_urlsafe(64)
67
+ challenge = (
68
+ base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest())
69
+ .rstrip(b"=")
70
+ .decode()
71
+ )
72
+ r = await http.post(
73
+ "/api/v1/auth/mobile/login",
74
+ json={
75
+ "code_challenge": challenge,
76
+ "code_challenge_method": "S256",
77
+ "callback_scheme": "ie.arch.archie.desktop",
78
+ },
79
+ )
80
+ expect(r.status_code == 200, f"pkce login (desktop scheme) 200 (got {r.status_code})")
81
+ login_body = r.json()
82
+ expect("authorization_url" in login_body, "pkce login returns authorization_url")
83
+ expect("workos.com" in login_body.get("authorization_url", ""), "auth URL is WorkOS")
84
+
85
+ # 2. Register a device
86
+ r = await http.post(
87
+ "/api/v1/devices",
88
+ json={
89
+ "platform": "apns",
90
+ "push_token": f"smoke-token-{secrets.token_hex(8)}",
91
+ "app_version": "0.1.0-smoke",
92
+ "device_name": "AND smoke harness",
93
+ },
94
+ )
95
+ expect(r.status_code == 201, f"register device 201 (got {r.status_code})")
96
+ device = r.json()
97
+ device_id = device["id"]
98
+ expect(device.get("platform") == "apns", "device platform=apns")
99
+
100
+ # Idempotent re-register
101
+ r = await http.post(
102
+ "/api/v1/devices",
103
+ json={
104
+ "platform": "apns",
105
+ "push_token": device.get("push_token") or "", # not returned, refresh by id only
106
+ "app_version": "0.2.0-smoke",
107
+ "device_name": "AND smoke harness v2",
108
+ },
109
+ )
110
+ # Re-register requires the same push_token; the response from POST doesn't echo it,
111
+ # so we test idempotency by listing instead.
112
+
113
+ # 3. List devices
114
+ r = await http.get("/api/v1/devices")
115
+ expect(r.status_code == 200, f"list devices 200 (got {r.status_code})")
116
+ expect(any(d["id"] == device_id for d in r.json()), "registered device appears in list")
117
+
118
+ # 4. List topics
119
+ r = await http.get("/api/v1/topics")
120
+ expect(r.status_code == 200, f"list topics 200 (got {r.status_code})")
121
+ topics_payload = r.json()
122
+ topics = topics_payload.get("topics") if isinstance(topics_payload, dict) else topics_payload
123
+ expect(isinstance(topics, list), "topics list is a list")
124
+ topic_id = topics[0]["id"] if topics else None
125
+ if topic_id:
126
+ print(f" using topic {topic_id} for subsequent calls")
127
+
128
+ # 5. Soft-lock acquire + release
129
+ if topic_id:
130
+ r = await http.post(
131
+ f"/api/v1/topics/{topic_id}/locks/acquire",
132
+ json={"section_key": "smoke-harness:section", "ttl_seconds": 60},
133
+ )
134
+ expect(r.status_code == 201, f"acquire soft lock 201 (got {r.status_code})")
135
+
136
+ r = await http.get(f"/api/v1/topics/{topic_id}/locks")
137
+ expect(r.status_code == 200, f"list locks 200 (got {r.status_code})")
138
+ expect(
139
+ any(lk["section_key"] == "smoke-harness:section" for lk in r.json()),
140
+ "lock appears in list",
141
+ )
142
+
143
+ r = await http.post(
144
+ f"/api/v1/topics/{topic_id}/locks/release",
145
+ json={"section_key": "smoke-harness:section"},
146
+ )
147
+ expect(r.status_code == 204, f"release lock 204 (got {r.status_code})")
148
+
149
+ # 6. SSE sync stream — open, expect at least one heartbeat or event
150
+ async with http.stream(
151
+ "GET",
152
+ "/api/v1/sync/stream",
153
+ params={"since": "2020-01-01T00:00:00Z"},
154
+ timeout=10.0,
155
+ ) as stream:
156
+ expect(
157
+ stream.status_code == 200,
158
+ f"sse stream open 200 (got {stream.status_code})",
159
+ )
160
+ # Read up to 4 lines or 4 seconds, whichever comes first.
161
+ collected: list[str] = []
162
+
163
+ async def _collect() -> None:
164
+ async for line in stream.aiter_lines():
165
+ if line:
166
+ collected.append(line)
167
+ if len(collected) >= 4:
168
+ return
169
+
170
+ with contextlib.suppress(asyncio.TimeoutError):
171
+ await asyncio.wait_for(_collect(), timeout=4.0)
172
+
173
+ expect(
174
+ any(line.startswith(("event:", "data:")) for line in collected),
175
+ f"sse emitted SSE-shaped lines (saw {len(collected)} lines)",
176
+ )
177
+
178
+ # 7. Memory commit
179
+ r = await http.post(
180
+ "/api/v1/auth/status", # used only as a workspace probe
181
+ )
182
+ # workspace_id needed for memory; pull from /me-style fallback. Some
183
+ # deployments expose it under /api/v1/auth/me. Skip if not available.
184
+
185
+ # 8. Cleanup — deregister the device
186
+ r = await http.delete(f"/api/v1/devices/{device_id}")
187
+ expect(r.status_code == 204, f"deregister device 204 (got {r.status_code})")
188
+
189
+ print("\n All N1-N4 native-desktop checkpoints passed.")
190
+ return 0
191
+
192
+
193
+ def main() -> int:
194
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
195
+ parser.add_argument("--base-url", default="http://localhost:8001")
196
+ parser.add_argument("--token", default="dev-mock-token-for-local-testing")
197
+ args = parser.parse_args()
198
+
199
+ print(f"\n Native Desktop smoke harness")
200
+ print(f" base-url: {args.base_url}")
201
+ print(f" token: {args.token[:24]}...\n")
202
+
203
+ try:
204
+ return asyncio.run(run(args.base_url, args.token))
205
+ except SmokeFailure as exc:
206
+ print(f"\n FAIL: {exc}", file=sys.stderr)
207
+ return 1
208
+ except Exception as exc:
209
+ print(f"\n ERROR: {type(exc).__name__}: {exc}", file=sys.stderr)
210
+ return 2
211
+
212
+
213
+ if __name__ == "__main__":
214
+ sys.exit(main())