ltcai 8.2.0 → 8.3.0
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.
- package/README.md +21 -19
- package/docs/CHANGELOG.md +32 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +43 -0
- package/docs/DEVELOPMENT.md +8 -8
- package/docs/LEGACY_COMPATIBILITY.md +22 -2
- package/docs/ONBOARDING.md +38 -0
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +5 -4
- package/docs/kg-schema.md +3 -3
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/graph/ingest.py +40 -8
- package/lattice_brain/runtime/agent_runtime.py +22 -37
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/lattice_brain/workflow.py +26 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/knowledge_graph.py +33 -0
- package/latticeai/api/local_files.py +2 -0
- package/latticeai/api/tools.py +1 -0
- package/latticeai/api/workflow_designer.py +5 -4
- package/latticeai/core/legacy_compatibility.py +174 -0
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/services/architecture_readiness.py +37 -3
- package/latticeai/services/model_engines.py +12 -21
- package/latticeai/services/model_runtime.py +7 -26
- package/latticeai/services/product_readiness.py +36 -14
- package/llm_router.py +7 -28
- package/mcp_registry.py +7 -24
- package/package.json +1 -1
- package/scripts/pts-claudecode-discord-bridge.mjs +2 -1
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +10 -10
- package/static/app/assets/{Act-D9jIknFd.js → Act-D5mo4tE4.js} +1 -1
- package/static/app/assets/{Brain-CFOtWbPN.js → Brain-BVWyQw8A.js} +1 -1
- package/static/app/assets/{Capture-Q4WYzwr5.js → Capture-C1R6GT0t.js} +1 -1
- package/static/app/assets/{Library-C5Q2yWee.js → Library-C2wIxpTs.js} +1 -1
- package/static/app/assets/{System-BLbjdr1_.js → System-DE5GRyQR.js} +1 -1
- package/static/app/assets/{index-BqammyNu.js → index-CoiuIFFP.js} +3 -3
- package/static/app/assets/{primitives-Br8uSfZ4.js → primitives-BdsUNXa6.js} +1 -1
- package/static/app/assets/{textarea-BnhNs1_X.js → textarea-e7qaj6Hm.js} +1 -1
- package/static/app/index.html +1 -1
- package/static/sw.js +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lattice AI
|
|
2
2
|
|
|
3
|
-
**Lattice AI 8.0 is the local-first Digital Brain platform with
|
|
3
|
+
**Lattice AI 8.3.0 is the local-first Digital Brain platform with managed legacy compatibility, stronger AgentRuntime/workflow orchestration, and graph ingestion coverage that keeps workspace memory isolated.**
|
|
4
4
|
|
|
5
5
|
**Lattice AI는 모델이 바뀌어도 내 지식과 맥락을 보존하는 로컬 우선 AI 브레인입니다.**
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ downloads, update checks, and other external communication happen only after
|
|
|
11
11
|
explicit consent.
|
|
12
12
|
|
|
13
13
|
It is not a ChatGPT clone, a model launcher, a graph database, or a note app.
|
|
14
|
-
It is the finished private AI memory layer wrapped in a Living Brain experience — now with
|
|
14
|
+
It is the finished private AI memory layer wrapped in a Living Brain experience — now with an 8.3.0 product-readiness contract behind onboarding, orchestration, graph ingestion, and the plugin/community path.
|
|
15
15
|
|
|
16
16
|
[](https://pypi.org/project/ltcai/)
|
|
17
17
|
[](https://www.npmjs.com/package/ltcai)
|
|
@@ -64,9 +64,10 @@ You need Lattice AI when:
|
|
|
64
64
|
|
|
65
65
|
## Living Brain Flow
|
|
66
66
|
|
|
67
|
-
The screenshots below are
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
The screenshots below are the latest checked-in visual evidence captures from
|
|
68
|
+
the 8.2 Brain Home release. The 8.3 line keeps that first-run flow focused on
|
|
69
|
+
the Brain while adding clearer onboarding, stronger workflow/runtime
|
|
70
|
+
boundaries, and better ingestion proof behind the scenes.
|
|
70
71
|
|
|
71
72
|
### 1. Wake Brain
|
|
72
73
|
|
|
@@ -203,27 +204,27 @@ See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for developer workflow details.
|
|
|
203
204
|
|
|
204
205
|
## Current Release
|
|
205
206
|
|
|
206
|
-
The current release is **8.
|
|
207
|
+
The current release is **8.3.0 — Orchestrated Brain Readiness**:
|
|
207
208
|
|
|
208
|
-
-
|
|
209
|
-
-
|
|
210
|
-
-
|
|
211
|
-
-
|
|
212
|
-
-
|
|
213
|
-
-
|
|
209
|
+
- Legacy compatibility is now tracked as a managed inventory in `latticeai.core.legacy_compatibility`, so root shims have owners, replacements, and removal phases instead of living as hidden debt.
|
|
210
|
+
- AgentRuntime and workflow orchestration expose clearer lifecycle/config boundaries while preserving compatibility for legacy run records.
|
|
211
|
+
- `/knowledge-graph/ingest` now routes through the unified ingestion pipeline when available, giving MCP/note/message writes the same provenance and hook lifecycle as files and browser sources.
|
|
212
|
+
- Graph ingestion now keeps duplicate content isolated per workspace, avoiding cross-workspace metadata overwrites while preserving content-hash duplicate detection.
|
|
213
|
+
- Upload failures surface honest client errors, and upload-to-KG behavior is covered by integration-style unit tests.
|
|
214
|
+
- Onboarding, community, plugin, and release docs now define the five-minute first-run path and ecosystem growth path for 8.3.0.
|
|
214
215
|
|
|
215
|
-
Expected artifacts for 8.
|
|
216
|
+
Expected artifacts for 8.3.0 release must use exact filenames:
|
|
216
217
|
|
|
217
|
-
- `dist/ltcai-8.
|
|
218
|
-
- `dist/ltcai-8.
|
|
219
|
-
- `ltcai-8.
|
|
220
|
-
- `dist/ltcai-8.
|
|
221
|
-
- `src-tauri/target/release/bundle/dmg/Lattice AI_8.
|
|
218
|
+
- `dist/ltcai-8.3.0-py3-none-any.whl`
|
|
219
|
+
- `dist/ltcai-8.3.0.tar.gz`
|
|
220
|
+
- `ltcai-8.3.0.tgz`
|
|
221
|
+
- `dist/ltcai-8.3.0.vsix`
|
|
222
|
+
- `src-tauri/target/release/bundle/dmg/Lattice AI_8.3.0_aarch64.dmg`
|
|
222
223
|
|
|
223
224
|
Do not use wildcard artifact uploads. Package registry publishing remains owner-run.
|
|
224
225
|
|
|
225
226
|
See [docs/ROADMAP_RECOMMENDATIONS.md](docs/ROADMAP_RECOMMENDATIONS.md) for the
|
|
226
|
-
strategic roadmap slices applied through 8.
|
|
227
|
+
strategic roadmap slices applied through 8.3.0 and the follow-up tracks.
|
|
227
228
|
|
|
228
229
|
## Known Limitations
|
|
229
230
|
|
|
@@ -240,6 +241,7 @@ strategic roadmap slices applied through 8.2.0 and the follow-up tracks.
|
|
|
240
241
|
|
|
241
242
|
| Version | Theme |
|
|
242
243
|
| --- | --- |
|
|
244
|
+
| 8.3.0 | Orchestrated Brain Readiness: managed legacy shim inventory, stronger AgentRuntime/workflow boundaries, unified graph ingestion, workspace-safe duplicate content, first-run onboarding, and explicit community/plugin growth path |
|
|
243
245
|
| 8.2.0 | Brain Brief: evidence-backed home briefing, honest empty-state guidance, recall/graph/model-proof next actions, and continued model/workspace runtime extraction |
|
|
244
246
|
| 8.1.0 | Intuitive Brain Home: living Brain, recent memory, connected topic, next action, and composer are visible in one product-first screen with refreshed 8.1.0 evidence and artifacts |
|
|
245
247
|
| 8.0.0 | Runtime Architecture Contract: AgentRuntime, ToolRegistry, central Config, server decomposition, and KG hardening are captured as machine-checkable release boundaries with exact 8.0.0 artifacts |
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,38 @@ existed at that release.
|
|
|
8
8
|
|
|
9
9
|
No unreleased changes.
|
|
10
10
|
|
|
11
|
+
## [8.3.0] - 2026-07-01
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Added a managed legacy compatibility report for remaining root shims,
|
|
15
|
+
including owners, replacements, reasons, removal phases, and readiness
|
|
16
|
+
metrics.
|
|
17
|
+
- Added AgentRuntime/workflow maturity evidence through lifecycle helper reuse,
|
|
18
|
+
legacy event compatibility, WorkflowEngine boundary/config inspection, and
|
|
19
|
+
centralized legacy workflow step projection.
|
|
20
|
+
- Added graph ingestion coverage for upload-to-pipeline behavior and
|
|
21
|
+
workspace-safe duplicate content.
|
|
22
|
+
- Added 8.3.0 onboarding and community/plugin growth documentation.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- Routed `/knowledge-graph/ingest` through the unified `IngestionPipeline` when
|
|
26
|
+
available, preserving provenance and hook lifecycle behavior for MCP notes and
|
|
27
|
+
messages.
|
|
28
|
+
- Isolated text/web/note graph node identity by workspace while preserving the
|
|
29
|
+
content hash used for duplicate detection.
|
|
30
|
+
- Converted `mcp_registry.py` and `llm_router.py` into physical module aliases
|
|
31
|
+
for their current implementations.
|
|
32
|
+
- Improved upload client error handling so failed uploads cannot look
|
|
33
|
+
successful.
|
|
34
|
+
- Synchronized package/runtime/static/Tauri metadata and current-release docs to
|
|
35
|
+
8.3.0.
|
|
36
|
+
|
|
37
|
+
### Upgrade Notes
|
|
38
|
+
- Existing legacy-global text/web/note graph nodes are not rewritten in place.
|
|
39
|
+
Re-ingesting the same content with a workspace id can create a separate
|
|
40
|
+
workspace-scoped node; re-index existing sources after upgrading when you want
|
|
41
|
+
provenance to converge on workspace scopes.
|
|
42
|
+
|
|
11
43
|
## [8.2.0] - 2026-06-27
|
|
12
44
|
|
|
13
45
|
### Added
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Community And Plugins
|
|
2
|
+
|
|
3
|
+
Current release: **8.3.0 - Orchestrated Brain Readiness**.
|
|
4
|
+
|
|
5
|
+
LatticeAI 8.3.0 defines the path from a strong local-first framework to a
|
|
6
|
+
product ecosystem. The immediate goal is small and practical: make it clear how
|
|
7
|
+
contributors can extend the Brain without weakening local-first trust,
|
|
8
|
+
workspace scoping, or release quality.
|
|
9
|
+
|
|
10
|
+
## Community Entry Points
|
|
11
|
+
|
|
12
|
+
- Start with the product docs: `README.md`, `docs/WHY_LATTICE.md`, and
|
|
13
|
+
`docs/ONBOARDING.md`.
|
|
14
|
+
- Use `docs/DEVELOPMENT.md` for local setup, validation, and release gates.
|
|
15
|
+
- Use `docs/PLUGIN_SDK.md` for plugin manifests, compatibility, permissions,
|
|
16
|
+
lifecycle state, catalog endpoints, and install flows.
|
|
17
|
+
- Use `plugins/hello-world/plugin.json` as the minimum working plugin shape.
|
|
18
|
+
|
|
19
|
+
## Plugin Direction
|
|
20
|
+
|
|
21
|
+
Plugins should add one bounded capability at a time:
|
|
22
|
+
|
|
23
|
+
- new ingestion sources that still route through `IngestionPipeline`;
|
|
24
|
+
- graph-aware tools that preserve workspace scoping;
|
|
25
|
+
- workflow templates that declare permissions explicitly;
|
|
26
|
+
- editor or automation helpers that keep secrets out of logs and audit payloads;
|
|
27
|
+
- local-first integrations that require explicit opt-in before network access.
|
|
28
|
+
|
|
29
|
+
## Guardrails
|
|
30
|
+
|
|
31
|
+
- No plugin should bypass the ToolRegistry, permission model, or audit hooks.
|
|
32
|
+
- No plugin should write graph data without provenance.
|
|
33
|
+
- No plugin should assume a cloud model, remote registry, or network connection.
|
|
34
|
+
- Compatibility requirements belong in `lattice_version`, and examples should
|
|
35
|
+
use current host-compatible values.
|
|
36
|
+
|
|
37
|
+
## 8.3.0 Ecosystem Tasks
|
|
38
|
+
|
|
39
|
+
- Keep the hello-world plugin valid and boring.
|
|
40
|
+
- Expand examples only when they exercise real extension seams.
|
|
41
|
+
- Add tests before treating a plugin API as stable.
|
|
42
|
+
- Prefer documentation that helps a first contributor build one useful plugin
|
|
43
|
+
over broad ecosystem promises.
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Lattice AI Development
|
|
2
2
|
|
|
3
|
-
Current release: **8.
|
|
3
|
+
Current release: **8.3.0 - Orchestrated Brain Readiness**.
|
|
4
4
|
|
|
5
5
|
This document is for contributors working on the local-first Digital Brain
|
|
6
6
|
codebase. Product positioning and quick start stay in `README.md`; release
|
|
7
|
-
history is intentionally limited to 7.0.0-8.
|
|
7
|
+
history is intentionally limited to 7.0.0-8.3.0 in `docs/CHANGELOG.md` and
|
|
8
8
|
`RELEASE.md`.
|
|
9
9
|
|
|
10
10
|
## Product Contract
|
|
@@ -112,10 +112,10 @@ For user-facing, API, runtime, release, or packaging changes, check:
|
|
|
112
112
|
Release/publish examples must use exact target-version filenames. Do not
|
|
113
113
|
document wildcard artifact upload commands.
|
|
114
114
|
|
|
115
|
-
For 8.
|
|
115
|
+
For 8.3.0 release work, exact artifacts are:
|
|
116
116
|
|
|
117
|
-
- `dist/ltcai-8.
|
|
118
|
-
- `dist/ltcai-8.
|
|
119
|
-
- `ltcai-8.
|
|
120
|
-
- `dist/ltcai-8.
|
|
121
|
-
- `src-tauri/target/release/bundle/dmg/Lattice AI_8.
|
|
117
|
+
- `dist/ltcai-8.3.0-py3-none-any.whl`
|
|
118
|
+
- `dist/ltcai-8.3.0.tar.gz`
|
|
119
|
+
- `ltcai-8.3.0.tgz`
|
|
120
|
+
- `dist/ltcai-8.3.0.vsix`
|
|
121
|
+
- `src-tauri/target/release/bundle/dmg/Lattice AI_8.3.0_aarch64.dmg`
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
# Legacy Compatibility Map
|
|
2
2
|
|
|
3
|
-
Current release: **8.
|
|
3
|
+
Current release: **8.3.0 - Orchestrated Brain Readiness**.
|
|
4
4
|
|
|
5
5
|
Lattice AI is moving toward a smaller, modular architecture centered on
|
|
6
6
|
`lattice_brain`, `latticeai.services`, `latticeai.api`, and `latticeai.runtime`.
|
|
7
7
|
Some root-level modules remain packaged for compatibility with older imports,
|
|
8
8
|
CLI entrypoints, or extension workflows. Their presence does not define the
|
|
9
|
-
current 8.
|
|
9
|
+
current 8.3.0 architecture.
|
|
10
|
+
|
|
11
|
+
8.3.0 also tracks the inner compatibility layers that sit below the root
|
|
12
|
+
modules. The managed inventory lives in `latticeai.core.legacy_compatibility`
|
|
13
|
+
and groups shims by layer:
|
|
14
|
+
|
|
15
|
+
- `root`: historical repo-root imports such as `knowledge_graph.py`.
|
|
16
|
+
- `brain-flat`: pre-graph-package imports such as `lattice_brain.store`.
|
|
17
|
+
- `deprecated-namespace`: older `latticeai.brain.*` package imports.
|
|
18
|
+
- `service-alias`: service paths that now alias Brain runtime modules.
|
|
10
19
|
|
|
11
20
|
## Current Policy
|
|
12
21
|
|
|
@@ -17,6 +26,9 @@ current 8.2.0 architecture.
|
|
|
17
26
|
- Add deprecation notes before removal.
|
|
18
27
|
- Avoid breaking package users during a minor release.
|
|
19
28
|
- Do not silently remove rollback, backup, restore, or migration paths.
|
|
29
|
+
- Track every remaining shim through `latticeai.core.legacy_compatibility` so
|
|
30
|
+
release readiness can report owner, replacement, reason, removal phase, and
|
|
31
|
+
missing files.
|
|
20
32
|
|
|
21
33
|
## Root Module Map
|
|
22
34
|
|
|
@@ -35,6 +47,14 @@ current 8.2.0 architecture.
|
|
|
35
47
|
| `setup_wizard.py` | setup and model recommendation services | Compatibility for first-run recommendation calls |
|
|
36
48
|
| `server.py` | lazy proxy to `latticeai.server_app` / `latticeai.app_factory` | Preserves historical `server.app` imports without import-time construction |
|
|
37
49
|
|
|
50
|
+
## Inner Shim Layers
|
|
51
|
+
|
|
52
|
+
| Legacy layer | Example module | Current home / direction | Why it remains |
|
|
53
|
+
| --- | --- | --- | --- |
|
|
54
|
+
| `brain-flat` | `lattice_brain.store`, `lattice_brain.ingest`, `lattice_brain.retrieval` | `lattice_brain.graph.*` | Preserves imports from before graph modules were split into a package |
|
|
55
|
+
| `deprecated-namespace` | `latticeai.brain.store`, `latticeai.brain.ingest` | `lattice_brain.graph.*` | Preserves the old application-package Brain namespace |
|
|
56
|
+
| `service-alias` | `latticeai.services.agent_runtime` | `lattice_brain.runtime.agent_runtime` | Preserves service-layer imports while runtime ownership sits in Brain Core |
|
|
57
|
+
|
|
38
58
|
## Packaging Notes
|
|
39
59
|
|
|
40
60
|
`pyproject.toml` and `package.json` still include several root modules because
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Lattice AI Onboarding
|
|
2
|
+
|
|
3
|
+
Current release: **8.3.0 - Orchestrated Brain Readiness**.
|
|
4
|
+
|
|
5
|
+
The first-run goal is a five-minute path from "I opened the app" to "my Brain
|
|
6
|
+
has a source, a question, and proof." This page is the product contract behind
|
|
7
|
+
that flow; the UI should make these steps obvious without asking a new user to
|
|
8
|
+
read the docs first.
|
|
9
|
+
|
|
10
|
+
## Five-Minute Flow
|
|
11
|
+
|
|
12
|
+
1. Wake the Brain and confirm the local owner profile.
|
|
13
|
+
2. Let Lattice inspect local model/runtime readiness.
|
|
14
|
+
3. Pick the recommended Brain voice or skip model loading.
|
|
15
|
+
4. Add one source: upload a file, connect a folder, save a note, or capture a
|
|
16
|
+
browser/source event.
|
|
17
|
+
5. Ask one grounded question and inspect the answer proof.
|
|
18
|
+
6. Open the Knowledge Graph only when the user wants source-level evidence.
|
|
19
|
+
7. Back up the Brain once useful memory exists.
|
|
20
|
+
|
|
21
|
+
## Product Promises
|
|
22
|
+
|
|
23
|
+
- The user starts in the Brain, not in an admin dashboard.
|
|
24
|
+
- Empty states suggest one concrete next action without claiming proof that does
|
|
25
|
+
not exist yet.
|
|
26
|
+
- Upload, note, browser, and message ingestion all converge through the unified
|
|
27
|
+
ingestion pipeline when it is available.
|
|
28
|
+
- Workspace-scoped content must not leak or overwrite another workspace's graph
|
|
29
|
+
metadata.
|
|
30
|
+
- Advanced runtime, workflow, plugin, and admin surfaces are available, but they
|
|
31
|
+
do not block the first conversation.
|
|
32
|
+
|
|
33
|
+
## Release Gate
|
|
34
|
+
|
|
35
|
+
8.3.0 treats onboarding as a release gate, not marketing copy. The current
|
|
36
|
+
machine-checkable product readiness report requires this five-minute contract,
|
|
37
|
+
the Brain Home surface, setup helpers, graph ingestion tests, and exact release
|
|
38
|
+
artifact documentation before the release can be called complete.
|
package/docs/TRUST_MODEL.md
CHANGED
package/docs/WHY_LATTICE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Why Lattice AI Exists
|
|
2
2
|
|
|
3
|
-
Current release: **8.
|
|
3
|
+
Current release: **8.3.0 - Orchestrated Brain Readiness**.
|
|
4
4
|
|
|
5
5
|
**Lattice AI is a local-first Digital Brain that keeps your knowledge durable
|
|
6
6
|
across any AI model.**
|
|
@@ -32,9 +32,10 @@ The graph matters, but it is not the product identity. The product identity is a
|
|
|
32
32
|
local-first Digital Brain: a place where the user can talk, add sources, watch
|
|
33
33
|
memory grow, and inspect the Knowledge Graph when they need proof.
|
|
34
34
|
|
|
35
|
-
In 8.
|
|
36
|
-
conversation composer,
|
|
37
|
-
user immediately knows what matters
|
|
35
|
+
In 8.3.0 the first screen is intentionally not a dashboard. The living Brain,
|
|
36
|
+
conversation composer, evidence-backed Brain Brief, and five-minute onboarding
|
|
37
|
+
path appear together so the user immediately knows what matters, what to add,
|
|
38
|
+
and why the answer is grounded in local memory.
|
|
38
39
|
|
|
39
40
|
## Practical Reasons To Use It
|
|
40
41
|
|
package/docs/kg-schema.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Knowledge Graph Schema
|
|
2
2
|
|
|
3
|
-
Current release: **8.
|
|
3
|
+
Current release: **8.3.0 - Orchestrated Brain Readiness**.
|
|
4
4
|
|
|
5
5
|
명세 출처: `lattice_ai_full_spec.pptx` 슬라이드 20·21·22
|
|
6
6
|
구현: `kg_schema.py`
|
|
@@ -90,7 +90,7 @@ Edge {
|
|
|
90
90
|
|
|
91
91
|
## Current Knowledge Graph First 엔티티/관계
|
|
92
92
|
|
|
93
|
-
8.
|
|
93
|
+
8.3.0 은 "모든 데이터 소스가 Knowledge Graph 로 수렴한다"는 원칙을 1급 스키마로
|
|
94
94
|
승격한다. 아래 타입은 **추가형(additive)**이다 — 기존 enum/legacy 매핑을 깨지 않고
|
|
95
95
|
`from_legacy` 가 무손실로 정규화하며, 알 수 없는 타입은 여전히 `CONCEPT`/`MENTIONS` 로
|
|
96
96
|
폴백한다. 스키마는 **확장 가능**하게 유지한다: 새 도메인 엔티티는 enum 멤버 1개 +
|
|
@@ -138,7 +138,7 @@ provenance(source_type, source_uri, content_hash, captured_at, modified_at,
|
|
|
138
138
|
- provenance 는 노드 `metadata.provenance` 에 임베드되며, 동시에 감사 가능한
|
|
139
139
|
`ingestion_provenance` 테이블에 기록된다 (`KnowledgeGraphStore.get_provenance(node_id)`).
|
|
140
140
|
|
|
141
|
-
구현: `
|
|
141
|
+
구현: `lattice_brain/ingestion.py` (`IngestionPipeline`) 가 단일 진입점이며,
|
|
142
142
|
파일/로컬폴더/URL/브라우저 탭/텍스트를 모두 이 형태로 정규화한다.
|
|
143
143
|
|
|
144
144
|
---
|
|
@@ -490,8 +490,6 @@ class KnowledgeGraphIngestMixin:
|
|
|
490
490
|
is derived from (source_type, source_uri | content_hash) so re-ingesting
|
|
491
491
|
the same origin reuses the same SOURCE node (idempotent).
|
|
492
492
|
"""
|
|
493
|
-
key = source_uri or content_hash or content_node_id
|
|
494
|
-
source_id = f"source:{_sha256_text(f'{source_type}|{key}')[:24]}"
|
|
495
493
|
meta = {
|
|
496
494
|
"source_type": source_type,
|
|
497
495
|
"source_uri": source_uri,
|
|
@@ -499,6 +497,9 @@ class KnowledgeGraphIngestMixin:
|
|
|
499
497
|
"captured_at": captured_at or _now(),
|
|
500
498
|
**(extra or {}),
|
|
501
499
|
}
|
|
500
|
+
key = source_uri or content_hash or content_node_id
|
|
501
|
+
source_scope = meta.get("workspace_id") or "legacy-global"
|
|
502
|
+
source_id = f"source:{_sha256_text(f'{source_scope}|{source_type}|{key}')[:24]}"
|
|
502
503
|
label = title or source_uri or source_type
|
|
503
504
|
self._upsert_node(
|
|
504
505
|
conn,
|
|
@@ -551,7 +552,8 @@ class KnowledgeGraphIngestMixin:
|
|
|
551
552
|
)
|
|
552
553
|
captured_at = captured_at or _now()
|
|
553
554
|
content_hash = _sha256_text(f"{source_type}|{source_uri or ''}|{text}")
|
|
554
|
-
|
|
555
|
+
identity_hash = _sha256_text(f"{workspace_id or 'legacy-global'}|{content_hash}")
|
|
556
|
+
content_id = f"webdoc:{identity_hash[:24]}"
|
|
555
557
|
full_text = f"{title}\n{text}"
|
|
556
558
|
node_meta = {
|
|
557
559
|
"source_type": source_type,
|
|
@@ -581,6 +583,8 @@ class KnowledgeGraphIngestMixin:
|
|
|
581
583
|
summary=(text or title)[:500],
|
|
582
584
|
metadata=node_meta,
|
|
583
585
|
raw=node_meta,
|
|
586
|
+
owner=owner,
|
|
587
|
+
workspace_id=workspace_id,
|
|
584
588
|
)
|
|
585
589
|
# ── SOURCE 노드 + indexed_from 엣지 (출처 추적) ──────────────────
|
|
586
590
|
source_node_id = self._attach_source_node(
|
|
@@ -597,13 +601,27 @@ class KnowledgeGraphIngestMixin:
|
|
|
597
601
|
if owner:
|
|
598
602
|
person_id = f"person:{_slug(owner)}"
|
|
599
603
|
self._upsert_node(
|
|
600
|
-
conn,
|
|
604
|
+
conn,
|
|
605
|
+
person_id,
|
|
606
|
+
"Person",
|
|
607
|
+
owner,
|
|
608
|
+
metadata={"email": owner, "workspace_id": workspace_id},
|
|
609
|
+
owner=owner,
|
|
610
|
+
workspace_id=workspace_id,
|
|
601
611
|
)
|
|
602
612
|
self._upsert_edge(conn, person_id, content_id, "업로드함", weight=1.0)
|
|
603
613
|
# ── 대화 연결 ───────────────────────────────────────────────────
|
|
604
614
|
if conversation_id:
|
|
605
615
|
conv_id = f"conversation:{_slug(conversation_id)}"
|
|
606
|
-
self._upsert_node(
|
|
616
|
+
self._upsert_node(
|
|
617
|
+
conn,
|
|
618
|
+
conv_id,
|
|
619
|
+
"Chat",
|
|
620
|
+
conversation_id,
|
|
621
|
+
metadata={"conversation_id": conversation_id, "workspace_id": workspace_id},
|
|
622
|
+
owner=owner,
|
|
623
|
+
workspace_id=workspace_id,
|
|
624
|
+
)
|
|
607
625
|
self._upsert_edge(conn, conv_id, content_id, "언급함", weight=0.8)
|
|
608
626
|
# ── RAG 청크 ────────────────────────────────────────────────────
|
|
609
627
|
for index, chunk in enumerate(_chunks(text)):
|
|
@@ -615,7 +633,9 @@ class KnowledgeGraphIngestMixin:
|
|
|
615
633
|
"Chunk",
|
|
616
634
|
f"{title} chunk {index + 1}",
|
|
617
635
|
summary=chunk[:500],
|
|
618
|
-
metadata={"index": index, "source_node": content_id},
|
|
636
|
+
metadata={"index": index, "source_node": content_id, "workspace_id": workspace_id},
|
|
637
|
+
owner=owner,
|
|
638
|
+
workspace_id=workspace_id,
|
|
619
639
|
)
|
|
620
640
|
self._upsert_chunk(
|
|
621
641
|
conn,
|
|
@@ -636,7 +656,13 @@ class KnowledgeGraphIngestMixin:
|
|
|
636
656
|
cid,
|
|
637
657
|
node_t,
|
|
638
658
|
concept,
|
|
639
|
-
metadata={
|
|
659
|
+
metadata={
|
|
660
|
+
"auto_extracted": True,
|
|
661
|
+
"source_type": source_type,
|
|
662
|
+
"workspace_id": workspace_id,
|
|
663
|
+
},
|
|
664
|
+
owner=owner,
|
|
665
|
+
workspace_id=workspace_id,
|
|
640
666
|
)
|
|
641
667
|
self._upsert_edge(conn, content_id, cid, "포함함", weight=0.8)
|
|
642
668
|
for triple in triples:
|
|
@@ -662,8 +688,14 @@ class KnowledgeGraphIngestMixin:
|
|
|
662
688
|
sem_type,
|
|
663
689
|
sem_title,
|
|
664
690
|
summary=item["summary"],
|
|
665
|
-
metadata={
|
|
691
|
+
metadata={
|
|
692
|
+
"auto_extracted": True,
|
|
693
|
+
"source_node": content_id,
|
|
694
|
+
"workspace_id": workspace_id,
|
|
695
|
+
},
|
|
666
696
|
raw=item,
|
|
697
|
+
owner=owner,
|
|
698
|
+
workspace_id=workspace_id,
|
|
667
699
|
)
|
|
668
700
|
self._upsert_edge(conn, content_id, sem_id, "포함함", weight=0.9)
|
|
669
701
|
|
|
@@ -266,7 +266,7 @@ class AgentRuntime:
|
|
|
266
266
|
unknown_roles = [role for role in requested_roles if role not in AGENT_ROLES]
|
|
267
267
|
health = self.health()
|
|
268
268
|
goal_ready = bool(str(goal or "").strip())
|
|
269
|
-
retry_budget =
|
|
269
|
+
retry_budget = self._clamp_retries(max_retries)
|
|
270
270
|
blocking_reasons: List[str] = []
|
|
271
271
|
if not goal_ready:
|
|
272
272
|
blocking_reasons.append("goal is required")
|
|
@@ -324,6 +324,7 @@ class AgentRuntime:
|
|
|
324
324
|
def events(self, run_id: str, *, scope: Optional[str] = None) -> Dict[str, Any]:
|
|
325
325
|
run = self._store.get_agent_run(run_id, workspace_id=scope)
|
|
326
326
|
status = str(run.get("status") or "")
|
|
327
|
+
contract = extract_contract(run)
|
|
327
328
|
return {
|
|
328
329
|
"run_id": run_id,
|
|
329
330
|
"status": status,
|
|
@@ -331,7 +332,7 @@ class AgentRuntime:
|
|
|
331
332
|
"current_role": run.get("current_role"),
|
|
332
333
|
"timeline": run.get("timeline") or [],
|
|
333
334
|
"handoffs": run.get("handoffs") or [],
|
|
334
|
-
"contract": contract_view(
|
|
335
|
+
"contract": contract_view(contract) if contract is not None else None,
|
|
335
336
|
}
|
|
336
337
|
|
|
337
338
|
# ── execution ─────────────────────────────────────────────────────────
|
|
@@ -360,6 +361,9 @@ class AgentRuntime:
|
|
|
360
361
|
raise PermissionError(pre_dispatch.get("block_reason") or "Agent run blocked by a pre_run hook.")
|
|
361
362
|
return pre_dispatch
|
|
362
363
|
|
|
364
|
+
def _clamp_retries(self, max_retries: int) -> int:
|
|
365
|
+
return max(0, min(int(max_retries or 0), self._max_retries_cap))
|
|
366
|
+
|
|
363
367
|
@staticmethod
|
|
364
368
|
def _result_patch(result: Any, goal: str) -> Dict[str, Any]:
|
|
365
369
|
return {
|
|
@@ -488,7 +492,7 @@ class AgentRuntime:
|
|
|
488
492
|
workspace_id=scope,
|
|
489
493
|
inputs=inputs or {},
|
|
490
494
|
roles=roles or None,
|
|
491
|
-
max_retries=
|
|
495
|
+
max_retries=self._clamp_retries(max_retries),
|
|
492
496
|
)
|
|
493
497
|
except Exception as exc:
|
|
494
498
|
failed = self._store.update_agent_run(
|
|
@@ -571,25 +575,13 @@ class AgentRuntime:
|
|
|
571
575
|
if not str(goal or "").strip():
|
|
572
576
|
raise ValueError("goal is required")
|
|
573
577
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
"pre_run", "agent.run",
|
|
582
|
-
payload={"goal": goal, "roles": roles or None, "max_retries": max_retries},
|
|
583
|
-
user_email=user_email, workspace_id=scope,
|
|
584
|
-
)
|
|
585
|
-
if pre_dispatch.get("blocked"):
|
|
586
|
-
self._append_audit_event(
|
|
587
|
-
"multi_agent_run_blocked",
|
|
588
|
-
user_email=user_email,
|
|
589
|
-
reason=pre_dispatch.get("block_reason"),
|
|
590
|
-
)
|
|
591
|
-
raise PermissionError(pre_dispatch.get("block_reason") or "Agent run blocked by a pre_run hook.")
|
|
592
|
-
|
|
578
|
+
pre_dispatch = self._fire_pre_run(
|
|
579
|
+
goal=goal,
|
|
580
|
+
roles=roles,
|
|
581
|
+
max_retries=max_retries,
|
|
582
|
+
user_email=user_email,
|
|
583
|
+
scope=scope,
|
|
584
|
+
)
|
|
593
585
|
orchestrator = self._live_orchestrator(user_email, scope)
|
|
594
586
|
result = orchestrator.run(
|
|
595
587
|
goal,
|
|
@@ -597,7 +589,7 @@ class AgentRuntime:
|
|
|
597
589
|
workspace_id=scope,
|
|
598
590
|
inputs=inputs or {},
|
|
599
591
|
roles=roles or None,
|
|
600
|
-
max_retries=
|
|
592
|
+
max_retries=self._clamp_retries(max_retries),
|
|
601
593
|
)
|
|
602
594
|
run = self._store.record_agent_run(
|
|
603
595
|
agent_id=result.agent_id,
|
|
@@ -626,20 +618,13 @@ class AgentRuntime:
|
|
|
626
618
|
retries=result.retries,
|
|
627
619
|
)
|
|
628
620
|
|
|
629
|
-
|
|
630
|
-
post_dispatch
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
"run_id": run_id,
|
|
637
|
-
"agent_id": result.agent_id,
|
|
638
|
-
"status": result.status,
|
|
639
|
-
"retries": result.retries,
|
|
640
|
-
},
|
|
641
|
-
user_email=user_email, workspace_id=scope,
|
|
642
|
-
)
|
|
621
|
+
run_id = run.get("id") or run.get("run_id") if isinstance(run, dict) else None
|
|
622
|
+
post_dispatch = self._post_run_hooks(
|
|
623
|
+
run_id=run_id,
|
|
624
|
+
result=result,
|
|
625
|
+
user_email=user_email,
|
|
626
|
+
scope=scope,
|
|
627
|
+
)
|
|
643
628
|
|
|
644
629
|
result_payload = result.as_dict()
|
|
645
630
|
result_payload["contract"] = multi_agent_contract(result=result, goal=goal, run_id=run.get("id") if isinstance(run, dict) else None)
|
|
@@ -21,7 +21,7 @@ from typing import Any, Callable, Dict, List, Optional
|
|
|
21
21
|
from .contracts import multi_agent_contract
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
MULTI_AGENT_VERSION = "8.
|
|
24
|
+
MULTI_AGENT_VERSION = "8.3.0"
|
|
25
25
|
|
|
26
26
|
AGENT_ROLES = ("researcher", "planner", "executor", "reviewer", "release")
|
|
27
27
|
CORE_PIPELINE = ("planner", "executor", "reviewer")
|
|
@@ -27,7 +27,7 @@ from dataclasses import dataclass, field
|
|
|
27
27
|
from datetime import datetime
|
|
28
28
|
from typing import Any, Callable, Dict, List, Optional
|
|
29
29
|
|
|
30
|
-
from lattice_brain.runtime.contracts import workflow_run_contract
|
|
30
|
+
from lattice_brain.runtime.contracts import runtime_boundary_contract, workflow_run_contract
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
WORKFLOW_ENGINE_VERSION = "2.2.0"
|
|
@@ -106,6 +106,11 @@ def normalize_definition(workflow: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
def legacy_steps_from_nodes(nodes: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
110
|
+
"""Return the compact legacy ``steps`` projection for node workflows."""
|
|
111
|
+
return [{"action": node.get("type"), "node": node.get("id")} for node in nodes]
|
|
112
|
+
|
|
113
|
+
|
|
109
114
|
def validate_definition(workflow: Dict[str, Any]) -> List[str]:
|
|
110
115
|
"""Return a list of validation errors ([] means valid)."""
|
|
111
116
|
errors: List[str] = []
|
|
@@ -269,6 +274,26 @@ class WorkflowEngine:
|
|
|
269
274
|
# against the workflow lifecycle actually executes.
|
|
270
275
|
self.hooks = hooks
|
|
271
276
|
|
|
277
|
+
def boundary(self) -> Dict[str, Any]:
|
|
278
|
+
return runtime_boundary_contract(
|
|
279
|
+
name="WorkflowEngine",
|
|
280
|
+
runtime="workflow",
|
|
281
|
+
entrypoint="lattice_brain.workflow.WorkflowEngine",
|
|
282
|
+
surface="/workflows",
|
|
283
|
+
owns="typed workflow validation, execution, approval suspension, resume, export, and import",
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def config(self) -> Dict[str, Any]:
|
|
287
|
+
return {
|
|
288
|
+
"version": WORKFLOW_ENGINE_VERSION,
|
|
289
|
+
"boundary": self.boundary(),
|
|
290
|
+
"node_types": list(NODE_TYPES),
|
|
291
|
+
"runner_families": dict(_RUNNER_FOR),
|
|
292
|
+
"max_steps": _MAX_STEPS,
|
|
293
|
+
"approval_suspend": True,
|
|
294
|
+
"legacy_steps_projection": "lattice_brain.workflow.legacy_steps_from_nodes",
|
|
295
|
+
}
|
|
296
|
+
|
|
272
297
|
def run(self, workflow: Dict[str, Any], *, inputs: Optional[Dict[str, Any]] = None) -> WorkflowRun:
|
|
273
298
|
definition = normalize_definition(workflow)
|
|
274
299
|
errors = validate_definition(definition)
|
package/latticeai/__init__.py
CHANGED