ltcai 3.1.0 → 3.2.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 +34 -8
- package/docs/CHANGELOG.md +53 -0
- package/docs/V3_2_AUDIT.md +82 -0
- package/docs/V3_FRONTEND.md +1 -1
- package/docs/architecture.md +6 -0
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agent_registry.py +103 -0
- package/latticeai/api/hooks.py +113 -0
- package/latticeai/api/marketplace.py +13 -0
- package/latticeai/api/memory.py +109 -0
- package/latticeai/core/agent_registry.py +234 -0
- package/latticeai/core/hooks.py +284 -0
- package/latticeai/core/marketplace.py +87 -2
- package/latticeai/core/multi_agent.py +1 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/server_app.py +41 -0
- package/latticeai/services/memory_service.py +324 -0
- package/package.json +2 -2
- package/scripts/build_v3_assets.mjs +1 -1
- package/static/v3/asset-manifest.json +16 -8
- package/static/v3/js/{app.46fb61d9.js → app.a5adc0f3.js} +1 -1
- package/static/v3/js/core/{api.22a41d42.js → api.603b978f.js} +64 -0
- package/static/v3/js/core/api.js +64 -0
- package/static/v3/js/core/{routes.f935dd50.js → routes.07ad6696.js} +11 -0
- package/static/v3/js/core/routes.js +11 -0
- package/static/v3/js/core/{shell.1b6199d6.js → shell.ea0b9ae5.js} +2 -2
- package/static/v3/js/views/{agents.14e48bdd.js → agents.c373d48c.js} +100 -0
- package/static/v3/js/views/agents.js +100 -0
- package/static/v3/js/views/hooks.f3edebca.js +99 -0
- package/static/v3/js/views/hooks.js +99 -0
- package/static/v3/js/views/marketplace.ab0583d4.js +141 -0
- package/static/v3/js/views/marketplace.js +141 -0
- package/static/v3/js/views/mcp.99b5c6a7.js +114 -0
- package/static/v3/js/views/mcp.js +114 -0
- package/static/v3/js/views/memory.d2ed7a7c.js +146 -0
- package/static/v3/js/views/memory.js +146 -0
- package/static/v3/js/views/planning.9ac3e313.js +153 -0
- package/static/v3/js/views/planning.js +153 -0
- package/static/v3/js/views/skills.c6c2f965.js +109 -0
- package/static/v3/js/views/skills.js +109 -0
- package/static/v3/js/views/tools.e4f11276.js +108 -0
- package/static/v3/js/views/tools.js +108 -0
- package/static/v3/js/views/workflows.26c57290.js +128 -0
- package/static/v3/js/views/workflows.js +128 -0
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
[](https://www.npmjs.com/package/ltcai)
|
|
17
17
|
[](https://marketplace.visualstudio.com/items?itemName=parktaesoo.ltcai)
|
|
18
18
|
[](https://open-vsx.org/extension/parktaesoo/ltcai)
|
|
19
|
-
[](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.
|
|
19
|
+
[](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.2.0)
|
|
20
20
|
[](LICENSE)
|
|
21
21
|
[](https://www.python.org/)
|
|
22
22
|
[](https://marketplace.visualstudio.com/items?itemName=parktaesoo.ltcai)
|
|
@@ -49,7 +49,7 @@ Install the coding extension:
|
|
|
49
49
|
|
|
50
50
|
- [VS Code Marketplace: parktaesoo.ltcai](https://marketplace.visualstudio.com/items?itemName=parktaesoo.ltcai)
|
|
51
51
|
- [Open VSX: parktaesoo.ltcai](https://open-vsx.org/extension/parktaesoo/ltcai)
|
|
52
|
-
- [GitHub Release v3.
|
|
52
|
+
- [GitHub Release v3.2.0](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.2.0)
|
|
53
53
|
|
|
54
54
|
## Quick Start
|
|
55
55
|
|
|
@@ -122,11 +122,36 @@ and disconnected automations. Lattice AI keeps those parts together:
|
|
|
122
122
|
- multi-agent workflows leave behind replayable plans, reviews, retries, and
|
|
123
123
|
outcomes.
|
|
124
124
|
|
|
125
|
-
## v3.
|
|
126
|
-
|
|
127
|
-
Lattice AI v3.
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
## v3.2.0 Highlights
|
|
126
|
+
|
|
127
|
+
Lattice AI v3.2.0 is the feature-complete release for all non-enterprise use
|
|
128
|
+
cases. Every platform capability is operable from `/app` with no Classic
|
|
129
|
+
dependency — built on real backends with honest live/unavailable states (never
|
|
130
|
+
fabricated data).
|
|
131
|
+
|
|
132
|
+
- **Multi-agent collaboration** — Planner → Researcher → Executor → Reviewer
|
|
133
|
+
with handoffs, shared context packets, and replayable timelines.
|
|
134
|
+
- **Agent Registry** — every agent (built-in role + custom) carries registry
|
|
135
|
+
metadata: type, version, capabilities, and configuration. No hardcoded lists.
|
|
136
|
+
- **Marketplace & Templates** — an offline catalog with five named agent
|
|
137
|
+
templates (Research Assistant, Coding Assistant, Knowledge Curator,
|
|
138
|
+
Documentation Writer, Workflow Builder) plus clone / export / import / install.
|
|
139
|
+
- **Workflow Agents** — trigger → agent chain → tools → memory → result, with a
|
|
140
|
+
run ledger and replay.
|
|
141
|
+
- **Autonomous Planning** — goal → plan → execute → review → replan, with
|
|
142
|
+
inspect/replay and bounded-retry safeguards.
|
|
143
|
+
- **Long-Term Memory + Memory Manager** — workspace, project, agent,
|
|
144
|
+
conversation, graph, and vector tiers unified behind one service, with
|
|
145
|
+
recall, inspect, prune, compact, rebuild, and clear.
|
|
146
|
+
- **Skills, Hooks, Tool Registry, and MCP Manager** — install/enable/disable
|
|
147
|
+
skills; lifecycle hooks across runs/tools/agents/pipelines/workflows; a
|
|
148
|
+
governed tool registry; and connected MCP servers, tools, and health.
|
|
149
|
+
|
|
150
|
+
The earlier v3.1 work (Classic retired from normal workflows, retrieval wired
|
|
151
|
+
through a shared service layer, hash-manifested assets) remains the foundation.
|
|
152
|
+
|
|
153
|
+
Release audit: [docs/V3_2_AUDIT.md](docs/V3_2_AUDIT.md) records the v3.2.0
|
|
154
|
+
claim audit, fixes, tests, real-app browser validation, and artifact checks.
|
|
130
155
|
|
|
131
156
|
- Native v3 Chat lives inside `/app#/chat` and streams through the real
|
|
132
157
|
`POST /chat` backend while showing friendly setup guidance when no model is
|
|
@@ -265,7 +290,8 @@ Core areas:
|
|
|
265
290
|
|
|
266
291
|
| Version | Theme |
|
|
267
292
|
| --- | --- |
|
|
268
|
-
| **3.
|
|
293
|
+
| **3.2.0** | Feature-complete platform — multi-agent collaboration, agent registry, marketplace + templates, workflow agents, autonomous planning, long-term memory + manager, skills/hooks/tool registries, MCP manager, all operable from `/app` |
|
|
294
|
+
| 3.1.0 | Mainline platform completion — native `/app` workflows, Classic retired from normal paths, production embedding profiles, AgentRuntime/registries, hashed v3 assets |
|
|
269
295
|
| 3.0.1 | Release-blocker remediation — provider-backed embeddings (Hash/MLX/Ollama/OpenAI/Custom), unified AgentRuntime boundary, every v3 surface connected or clearly unavailable |
|
|
270
296
|
| 3.0.0 | v3 local-first AI workspace platform — `/app`, Native Chat, Knowledge Graph, Vector Index, Hybrid Search, workspace modes |
|
|
271
297
|
| 2.2.7 | Visual system stabilization — cohesive dark/light screens, crisp chat composer, dark graph canvas, Workspace OS polish |
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.2.0] - 2026-06-08
|
|
4
|
+
|
|
5
|
+
> v3.2 — Feature-Complete Platform. Multi-agent collaboration, an agent
|
|
6
|
+
> registry, marketplace + templates, workflow agents, autonomous planning, a
|
|
7
|
+
> long-term memory platform + manager, and skills/hooks/tool/MCP registries are
|
|
8
|
+
> all operable from `/app`. Enterprise (SSO/SCIM/RBAC/compliance/DLP/VPC/
|
|
9
|
+
> governance/multi-tenant controls) remains future work.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Agent Registry** — `latticeai/core/agent_registry.py` +
|
|
14
|
+
`/agents/api/registry*`: built-in roles projected from `multi_agent`,
|
|
15
|
+
persisted custom agents, capability discovery, and per-agent config.
|
|
16
|
+
- **Hooks platform** — `latticeai/core/hooks.py` + `/api/hooks/*`: persisted
|
|
17
|
+
lifecycle registry (pre_run/post_run/pre_tool/post_tool/agent/pipeline/
|
|
18
|
+
workflow) with enable/disable/reorder/register/inspect.
|
|
19
|
+
- **Long-term memory platform + Memory Manager** —
|
|
20
|
+
`latticeai/services/memory_service.py` + `/api/memory/*`: unifies workspace
|
|
21
|
+
memories, agent snapshots, conversation history, and KG graph/vector behind
|
|
22
|
+
one façade; recall/inspect/prune/compact/rebuild/clear + usage/sources/health.
|
|
23
|
+
- **Agent templates** — five named templates in `latticeai/core/marketplace.py`
|
|
24
|
+
plus a `clone` endpoint; `MARKETPLACE_VERSION`/`PLUGIN_SDK_VERSION`/
|
|
25
|
+
`MULTI_AGENT_VERSION` → `3.2.0`.
|
|
26
|
+
- **MCP Manager surface** — `create_mcp_router` mounted through the tools router
|
|
27
|
+
in `server_app`, reviving `/mcp/*`, `/skills/marketplace`,
|
|
28
|
+
`/plugins/directory`, `/mcp/call`.
|
|
29
|
+
- **Eight `/app` views** — memory, planning, workflows, marketplace, skills,
|
|
30
|
+
hooks, tools, mcp; a Platform nav group; fallback-safe `api.js` adapters.
|
|
31
|
+
- **Release claim audit** — `docs/V3_2_AUDIT.md` records a strict 20-claim
|
|
32
|
+
PASS/PARTIAL/FAIL matrix with implementation evidence, fixes, validation,
|
|
33
|
+
artifact readiness, and release metadata policy.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Version bumped to 3.2.0 across Python, npm, the VS Code extension, the v3
|
|
38
|
+
asset manifest, and runtime version constants.
|
|
39
|
+
- `/app#/agents` now exposes the Agent Registry API directly, including
|
|
40
|
+
registry metadata, capability discovery, enablement, and custom-agent
|
|
41
|
+
registration.
|
|
42
|
+
- `/app#/skills` now normalizes the live `/workspace/skills` response shape
|
|
43
|
+
(`installed`, `available`, and object/array `registry`) instead of only a
|
|
44
|
+
legacy `skills` array.
|
|
45
|
+
- MCP/skills/plugin-directory routes are mounted once through the tools router;
|
|
46
|
+
route compatibility tests now guard against duplicate public path/method
|
|
47
|
+
registrations.
|
|
48
|
+
|
|
49
|
+
### Notes
|
|
50
|
+
|
|
51
|
+
- Validation covered lint, typecheck, Python compile, 365 unit tests, live
|
|
52
|
+
integration tests, 90 Playwright tests, real `/app` browser route validation,
|
|
53
|
+
Python/npm/VSIX builds, and exact-version release artifact validation.
|
|
54
|
+
- No packages were published and nothing was deployed.
|
|
55
|
+
|
|
3
56
|
## [3.1.0] - 2026-06-07
|
|
4
57
|
|
|
5
58
|
> v3.1 — Mainline Product Platform Completion. `/app` is now the full
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Lattice AI v3.2.0 Release Claim Audit
|
|
2
|
+
|
|
3
|
+
Audit date: 2026-06-08
|
|
4
|
+
Target version: 3.2.0
|
|
5
|
+
Scope: code, API routes, frontend views, adapters, tests, runtime/browser behavior, artifacts, tag/release metadata.
|
|
6
|
+
|
|
7
|
+
## Verdict
|
|
8
|
+
|
|
9
|
+
Final source verdict: PASS after release-hardening fixes.
|
|
10
|
+
|
|
11
|
+
The audit found two UI wiring gaps and one release-route hygiene issue:
|
|
12
|
+
|
|
13
|
+
- `/app#/agents` showed AgentRuntime state but did not expose the Agent Registry controls and capability index from `/agents/api/registry*`.
|
|
14
|
+
- `/app#/skills` called the live skill registry but only normalized a legacy `{ skills: [...] }` shape, so the real `{ installed, available, registry }` payload rendered as empty.
|
|
15
|
+
- `server_app` registered the MCP router twice because `create_tools_router` already mounted the MCP/skills/plugin-directory routes.
|
|
16
|
+
|
|
17
|
+
All three were fixed and covered by tests. No product scope was added.
|
|
18
|
+
|
|
19
|
+
## PASS / PARTIAL / FAIL Matrix
|
|
20
|
+
|
|
21
|
+
| # | Claim | Status | Evidence |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| 1 | Multi-Agent Collaboration | PASS | `latticeai/core/multi_agent.py`, `latticeai/services/agent_runtime.py`, `/agents/api/run`, handoffs/context packets/replay tests in `tests/unit/test_multi_agent.py` and `tests/unit/test_agent_platform_maturity.py`. |
|
|
24
|
+
| 2 | Agent Registry | PASS | `latticeai/core/agent_registry.py`, `latticeai/api/agent_registry.py`, `/agents/api/registry*`, `/app#/agents` registry section, visual coverage in `tests/visual/v3.spec.js`. |
|
|
25
|
+
| 3 | Agent Marketplace | PASS | `latticeai/core/marketplace.py`, `latticeai/api/marketplace.py`, `/marketplace/templates`, `/app#/marketplace`. Offline local catalog; no cloud marketplace is claimed. |
|
|
26
|
+
| 4 | Agent Templates | PASS | Five named agent templates: Research Assistant, Coding Assistant, Knowledge Curator, Documentation Writer, Workflow Builder; clone/export/import/install covered in `tests/unit/test_v32_platform.py`. |
|
|
27
|
+
| 5 | Workflow Agents | PASS | `latticeai/core/workflow_engine.py`, `latticeai/api/workflow_designer.py`, `PlatformRuntime.build_workflow_runners`, `/app#/workflows`, workflow run/replay tests. |
|
|
28
|
+
| 6 | Autonomous Planning | PASS | Planner/executor/reviewer flow via `/agents/api/run`, bounded retry/replan history in `MultiAgentOrchestrator`, `/app#/planning`, retry tests. |
|
|
29
|
+
| 7 | Long-Term Memory Platform | PASS | `latticeai/services/memory_service.py` unifies workspace/project/agent/conversation/graph/vector tiers; `/api/memory/*`. |
|
|
30
|
+
| 8 | Memory Manager | PASS | Usage/sources/health plus recall/inspect/prune/compact/rebuild/clear in `MemoryService` and `/app#/memory`. |
|
|
31
|
+
| 9 | Skills Registry | PASS | `WorkspaceOSStore.list_skill_registry`, `/workspace/skills*`, `/app#/skills`; fixed live payload normalization and added visual coverage. |
|
|
32
|
+
| 10 | Hooks Registry | PASS | `latticeai/core/hooks.py`, `latticeai/api/hooks.py`, `/api/hooks*`, `/app#/hooks`, unit tests for toggle/register/inspect/remove. |
|
|
33
|
+
| 11 | Tool Registry | PASS | `latticeai/core/tool_registry.py`, `latticeai/services/tool_dispatch.py`, `/tools/permissions`, `/mcp/tools`, `/app#/tools`, route duplicate guard. |
|
|
34
|
+
| 12 | MCP Foundation / MCP Manager | PASS | `latticeai/api/mcp.py`, `/mcp/tools`, `/mcp/installed`, `/mcp/custom`, `/mcp/claude-code-servers`, `/app#/mcp`; duplicate mount removed. |
|
|
35
|
+
| 13 | Retrieval & Memory Integration | PASS | `latticeai/api/search.py`, `latticeai/services/search_service.py`, `MemoryService.recall`, `/api/search/hybrid`, `/api/index/status`, `/api/graph`, `/api/memory/recall`. |
|
|
36
|
+
| 14 | UX Completion Pass | PASS | `/app` routes render without Classic dependency, console errors, app 404/500 responses, or horizontal overflow in real browser validation. Light/dark toggle validated. |
|
|
37
|
+
| 15 | Documentation refresh | PASS | README, release notes/changelogs, release guide, and this audit document updated for the hardening pass. |
|
|
38
|
+
| 16 | Architecture refresh | PASS | Architecture docs already describe the v3.2 runtime/registry boundaries; code now matches those boundaries without duplicate MCP route registration. |
|
|
39
|
+
| 17 | Version 3.2.0 consistency | PASS | `package.json`, `pyproject.toml`, `vscode-extension/package.json`, runtime constants, and expected artifacts remain at 3.2.0. |
|
|
40
|
+
| 18 | Tests | PASS | Lint/typecheck/python compile, 365 unit tests, live integration tests, 90 Playwright tests, and real-app browser route validation passed. |
|
|
41
|
+
| 19 | Build artifacts | PASS | Rebuilt Python sdist/wheel, npm tarball, VSIX, and validated exact v3.2.0 artifact names. |
|
|
42
|
+
| 20 | Git tag and GitHub Release metadata | PASS | Source policy keeps version 3.2.0; tag/release metadata should point at the final validated main commit. No package assets were attached or published. |
|
|
43
|
+
|
|
44
|
+
## Fixes Applied
|
|
45
|
+
|
|
46
|
+
### Agent Registry UI wiring
|
|
47
|
+
|
|
48
|
+
- Finding: Agent Registry backend and adapter existed, but `/app#/agents` only rendered the runtime roster.
|
|
49
|
+
- Affected files: `static/v3/js/views/agents.js`, hashed v3 assets, `tests/visual/v3.spec.js`, `tests/visual/mock_server.cjs`.
|
|
50
|
+
- Expected behavior: `/app#/agents` exposes built-in/custom registry metadata, versions, capabilities, enabled state, and registration.
|
|
51
|
+
- Actual behavior before fix: Registry data was reachable only through API/adapters, not the product view.
|
|
52
|
+
- Fix: Added a live Agent Registry section, custom-agent registration controls, capability index display, enable/disable/remove actions, and Playwright coverage.
|
|
53
|
+
|
|
54
|
+
### Skills registry live payload normalization
|
|
55
|
+
|
|
56
|
+
- Finding: `/workspace/skills` returned `{ installed, available, registry }`, but `/app#/skills` only accepted a legacy `{ skills }` array.
|
|
57
|
+
- Affected files: `static/v3/js/views/skills.js`, hashed v3 assets, `tests/visual/v3.spec.js`, `tests/visual/mock_server.cjs`.
|
|
58
|
+
- Expected behavior: installed and available skills render from the real registry payload.
|
|
59
|
+
- Actual behavior before fix: live registry payload could render as an empty state.
|
|
60
|
+
- Fix: Normalized installed, available, array registry, and object registry shapes with de-duplication by skill name.
|
|
61
|
+
|
|
62
|
+
### Duplicate MCP route registration
|
|
63
|
+
|
|
64
|
+
- Finding: `create_tools_router` already included the MCP router, and `server_app` mounted it again.
|
|
65
|
+
- Affected files: `latticeai/server_app.py`, `tests/unit/test_route_compatibility.py`.
|
|
66
|
+
- Expected behavior: every public path/method has one handler.
|
|
67
|
+
- Actual behavior before fix: duplicate MCP/skills/plugin-directory path registrations.
|
|
68
|
+
- Fix: Removed the second MCP include and added a route duplicate guard.
|
|
69
|
+
|
|
70
|
+
## Validation Summary
|
|
71
|
+
|
|
72
|
+
- `npm run lint`: PASS
|
|
73
|
+
- `npm run typecheck`: PASS
|
|
74
|
+
- `npm run check:python`: PASS
|
|
75
|
+
- `./venv/bin/python -m pytest tests/unit -v`: PASS, 365 passed
|
|
76
|
+
- `LTCAI_TEST_BASE_URL=http://127.0.0.1:8899 ./venv/bin/python -m pytest tests/integration -v`: PASS, 9 passed
|
|
77
|
+
- `npx playwright test`: PASS, 90 passed
|
|
78
|
+
- Real app browser validation: PASS for `/app`, `/app#/chat`, `/app#/planning`, `/app#/workflows`, `/app#/marketplace`, `/app#/memory`, `/app#/skills`, `/app#/hooks`, `/app#/tools`, `/app#/mcp`, `/app#/agents`, `/app#/models`, `/app#/knowledge-graph`, `/app#/hybrid-search`, `/app#/settings` across desktop/mobile, including no console/page errors, no app 404/500 responses, no horizontal overflow, no Classic dependency text, and light/dark toggle.
|
|
79
|
+
|
|
80
|
+
## Release Readiness
|
|
81
|
+
|
|
82
|
+
READY FOR MANUAL PACKAGE PUBLICATION once the v3.2.0 tag and GitHub Release notes point at the final validated main commit. No package publication or deployment was performed by this audit.
|
package/docs/V3_FRONTEND.md
CHANGED
|
@@ -98,7 +98,7 @@ first and returns `{ ok, status, data, source }` where `source` is `"live"` or
|
|
|
98
98
|
`"unavailable"`. Unavailable responses carry empty data so primary surfaces do
|
|
99
99
|
not invent counters, sample graphs, fake health, or fake run history.
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
Core live surfaces established before v3.2.0:
|
|
102
102
|
|
|
103
103
|
| Adapter | Endpoint | Unavailable state |
|
|
104
104
|
| --- | --- | --- |
|
package/docs/architecture.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Lattice AI Architecture
|
|
2
2
|
|
|
3
|
+
> v3.2.0 — feature-complete for non-enterprise use cases. The agent ecosystem
|
|
4
|
+
> (registry, marketplace + templates, workflow agents, autonomous planning),
|
|
5
|
+
> the long-term memory platform + manager, and the skills/hooks/tool/MCP
|
|
6
|
+
> registries are all operable from `/app`. Enterprise controls remain future
|
|
7
|
+
> work.
|
|
8
|
+
|
|
3
9
|
Lattice AI is a local-first **AI workspace, AI pipeline platform, Knowledge
|
|
4
10
|
Graph platform, and multi-agent workflow platform**. The architecture is
|
|
5
11
|
organized around one durable center: the Knowledge Graph. Models, tools,
|
package/latticeai/__init__.py
CHANGED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Agent Registry API router (v3.2.0).
|
|
2
|
+
|
|
3
|
+
Exposes :class:`~latticeai.core.agent_registry.AgentRegistry` so registration,
|
|
4
|
+
discovery, metadata, versioning, capabilities, and configuration are reachable
|
|
5
|
+
from the /app Agents view. Paths sit under ``/agents/api/registry`` alongside
|
|
6
|
+
the existing runtime endpoints. Full paths in decorators (no ``prefix=``).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
from fastapi import APIRouter, HTTPException, Request
|
|
14
|
+
from pydantic import BaseModel
|
|
15
|
+
|
|
16
|
+
from latticeai.core.agent_registry import AgentRegistry
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AgentRegisterRequest(BaseModel):
|
|
20
|
+
name: str
|
|
21
|
+
type: str = "custom"
|
|
22
|
+
description: str = ""
|
|
23
|
+
capabilities: List[str] = []
|
|
24
|
+
config: Dict[str, Any] = {}
|
|
25
|
+
version: str = "1.0.0"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class AgentConfigRequest(BaseModel):
|
|
29
|
+
config: Dict[str, Any] = {}
|
|
30
|
+
enabled: Optional[bool] = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def create_agent_registry_router(
|
|
34
|
+
*,
|
|
35
|
+
registry: AgentRegistry,
|
|
36
|
+
require_user: Callable[[Request], str],
|
|
37
|
+
append_audit_event: Callable[..., None],
|
|
38
|
+
) -> APIRouter:
|
|
39
|
+
router = APIRouter()
|
|
40
|
+
|
|
41
|
+
@router.get("/agents/api/registry")
|
|
42
|
+
async def list_registry(request: Request, type: Optional[str] = None):
|
|
43
|
+
require_user(request)
|
|
44
|
+
return registry.list(agent_type=type)
|
|
45
|
+
|
|
46
|
+
@router.get("/agents/api/registry/capabilities")
|
|
47
|
+
async def registry_capabilities(request: Request):
|
|
48
|
+
require_user(request)
|
|
49
|
+
return {"capabilities": registry.capabilities()}
|
|
50
|
+
|
|
51
|
+
@router.get("/agents/api/registry/discover")
|
|
52
|
+
async def registry_discover(request: Request, capability: str = ""):
|
|
53
|
+
require_user(request)
|
|
54
|
+
return {"capability": capability, "agents": registry.discover(capability)}
|
|
55
|
+
|
|
56
|
+
@router.post("/agents/api/registry")
|
|
57
|
+
async def register_agent(req: AgentRegisterRequest, request: Request):
|
|
58
|
+
user = require_user(request)
|
|
59
|
+
try:
|
|
60
|
+
entry = registry.register(
|
|
61
|
+
name=req.name,
|
|
62
|
+
agent_type=req.type,
|
|
63
|
+
description=req.description,
|
|
64
|
+
capabilities=req.capabilities,
|
|
65
|
+
config=req.config,
|
|
66
|
+
version=req.version,
|
|
67
|
+
)
|
|
68
|
+
except ValueError as exc:
|
|
69
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
70
|
+
append_audit_event("agent_register", user_email=user, agent_id=entry["id"], type=entry["type"])
|
|
71
|
+
return {"agent": entry}
|
|
72
|
+
|
|
73
|
+
@router.get("/agents/api/registry/{agent_id:path}")
|
|
74
|
+
async def get_agent(agent_id: str, request: Request):
|
|
75
|
+
require_user(request)
|
|
76
|
+
agent = registry.get(agent_id)
|
|
77
|
+
if agent is None:
|
|
78
|
+
raise HTTPException(status_code=404, detail=f"Agent not found: {agent_id}")
|
|
79
|
+
return {"agent": agent}
|
|
80
|
+
|
|
81
|
+
@router.patch("/agents/api/registry/{agent_id:path}")
|
|
82
|
+
async def update_agent(agent_id: str, req: AgentConfigRequest, request: Request):
|
|
83
|
+
user = require_user(request)
|
|
84
|
+
try:
|
|
85
|
+
agent = registry.update_config(agent_id, req.config, enabled=req.enabled)
|
|
86
|
+
except KeyError as exc:
|
|
87
|
+
raise HTTPException(status_code=404, detail=f"Agent not found: {agent_id}") from exc
|
|
88
|
+
append_audit_event("agent_config", user_email=user, agent_id=agent_id)
|
|
89
|
+
return {"agent": agent}
|
|
90
|
+
|
|
91
|
+
@router.delete("/agents/api/registry/{agent_id:path}")
|
|
92
|
+
async def remove_agent(agent_id: str, request: Request):
|
|
93
|
+
user = require_user(request)
|
|
94
|
+
try:
|
|
95
|
+
result = registry.remove(agent_id)
|
|
96
|
+
except KeyError as exc:
|
|
97
|
+
raise HTTPException(status_code=404, detail=f"Agent not found: {agent_id}") from exc
|
|
98
|
+
except ValueError as exc:
|
|
99
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
100
|
+
append_audit_event("agent_remove", user_email=user, agent_id=agent_id)
|
|
101
|
+
return result
|
|
102
|
+
|
|
103
|
+
return router
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Hooks platform API router (v3.2.0).
|
|
2
|
+
|
|
3
|
+
Exposes the lifecycle :class:`~latticeai.core.hooks.HooksRegistry` over HTTP so
|
|
4
|
+
the /app Hooks view can list, inspect, enable/disable, reorder, and register
|
|
5
|
+
hooks. Full paths live in the decorators (no ``prefix=``), matching the rest of
|
|
6
|
+
the API.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any, Callable, List, Optional
|
|
12
|
+
|
|
13
|
+
from fastapi import APIRouter, HTTPException, Request
|
|
14
|
+
from pydantic import BaseModel
|
|
15
|
+
|
|
16
|
+
from latticeai.core.hooks import HooksRegistry
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class HookToggleRequest(BaseModel):
|
|
20
|
+
hook_id: str
|
|
21
|
+
enabled: bool = True
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class HookReorderRequest(BaseModel):
|
|
25
|
+
kind: str
|
|
26
|
+
ordered_ids: List[str] = []
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class HookRegisterRequest(BaseModel):
|
|
30
|
+
name: str
|
|
31
|
+
kind: str
|
|
32
|
+
description: str = ""
|
|
33
|
+
command: str = ""
|
|
34
|
+
order: Optional[int] = None
|
|
35
|
+
enabled: bool = True
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def create_hooks_router(
|
|
39
|
+
*,
|
|
40
|
+
registry: HooksRegistry,
|
|
41
|
+
require_user: Callable[[Request], str],
|
|
42
|
+
append_audit_event: Callable[..., None],
|
|
43
|
+
) -> APIRouter:
|
|
44
|
+
router = APIRouter()
|
|
45
|
+
|
|
46
|
+
@router.get("/api/hooks")
|
|
47
|
+
async def list_hooks(request: Request, kind: Optional[str] = None):
|
|
48
|
+
require_user(request)
|
|
49
|
+
return registry.list(kind=kind)
|
|
50
|
+
|
|
51
|
+
@router.get("/api/hooks/{hook_id:path}")
|
|
52
|
+
async def inspect_hook(hook_id: str, request: Request):
|
|
53
|
+
require_user(request)
|
|
54
|
+
try:
|
|
55
|
+
return {"hook": registry.inspect(hook_id)}
|
|
56
|
+
except KeyError as exc:
|
|
57
|
+
raise HTTPException(status_code=404, detail=f"Hook not found: {hook_id}") from exc
|
|
58
|
+
|
|
59
|
+
@router.post("/api/hooks/enable")
|
|
60
|
+
async def enable_hook(req: HookToggleRequest, request: Request):
|
|
61
|
+
user = require_user(request)
|
|
62
|
+
try:
|
|
63
|
+
hook = registry.set_enabled(req.hook_id, req.enabled)
|
|
64
|
+
except KeyError as exc:
|
|
65
|
+
raise HTTPException(status_code=404, detail=f"Hook not found: {req.hook_id}") from exc
|
|
66
|
+
append_audit_event("hook_toggle", user_email=user, hook_id=req.hook_id, enabled=req.enabled)
|
|
67
|
+
return {"hook": hook}
|
|
68
|
+
|
|
69
|
+
@router.post("/api/hooks/disable")
|
|
70
|
+
async def disable_hook(req: HookToggleRequest, request: Request):
|
|
71
|
+
user = require_user(request)
|
|
72
|
+
try:
|
|
73
|
+
hook = registry.set_enabled(req.hook_id, False)
|
|
74
|
+
except KeyError as exc:
|
|
75
|
+
raise HTTPException(status_code=404, detail=f"Hook not found: {req.hook_id}") from exc
|
|
76
|
+
append_audit_event("hook_toggle", user_email=user, hook_id=req.hook_id, enabled=False)
|
|
77
|
+
return {"hook": hook}
|
|
78
|
+
|
|
79
|
+
@router.post("/api/hooks/reorder")
|
|
80
|
+
async def reorder_hooks(req: HookReorderRequest, request: Request):
|
|
81
|
+
require_user(request)
|
|
82
|
+
return registry.reorder(req.kind, req.ordered_ids)
|
|
83
|
+
|
|
84
|
+
@router.post("/api/hooks/register")
|
|
85
|
+
async def register_hook(req: HookRegisterRequest, request: Request):
|
|
86
|
+
user = require_user(request)
|
|
87
|
+
try:
|
|
88
|
+
entry = registry.register(
|
|
89
|
+
name=req.name,
|
|
90
|
+
kind=req.kind,
|
|
91
|
+
description=req.description,
|
|
92
|
+
command=req.command,
|
|
93
|
+
order=req.order,
|
|
94
|
+
enabled=req.enabled,
|
|
95
|
+
)
|
|
96
|
+
except ValueError as exc:
|
|
97
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
98
|
+
append_audit_event("hook_register", user_email=user, hook_id=entry["id"], kind=entry["kind"])
|
|
99
|
+
return {"hook": entry}
|
|
100
|
+
|
|
101
|
+
@router.delete("/api/hooks/{hook_id:path}")
|
|
102
|
+
async def remove_hook(hook_id: str, request: Request):
|
|
103
|
+
user = require_user(request)
|
|
104
|
+
try:
|
|
105
|
+
result = registry.remove(hook_id)
|
|
106
|
+
except KeyError as exc:
|
|
107
|
+
raise HTTPException(status_code=404, detail=f"Hook not found: {hook_id}") from exc
|
|
108
|
+
except ValueError as exc:
|
|
109
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
110
|
+
append_audit_event("hook_remove", user_email=user, hook_id=hook_id)
|
|
111
|
+
return result
|
|
112
|
+
|
|
113
|
+
return router
|
|
@@ -16,6 +16,10 @@ class TemplateInstallRequest(BaseModel):
|
|
|
16
16
|
data: Dict[str, Any] = {}
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
class TemplateCloneRequest(BaseModel):
|
|
20
|
+
name: Optional[str] = None
|
|
21
|
+
|
|
22
|
+
|
|
19
23
|
def create_marketplace_router(
|
|
20
24
|
*,
|
|
21
25
|
store,
|
|
@@ -72,6 +76,15 @@ def create_marketplace_router(
|
|
|
72
76
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
73
77
|
return {"installed": installed}
|
|
74
78
|
|
|
79
|
+
@router.post("/marketplace/templates/{kind}/{template_id}/clone")
|
|
80
|
+
async def clone_template(kind: str, template_id: str, req: TemplateCloneRequest, request: Request):
|
|
81
|
+
require_user(request)
|
|
82
|
+
gate_read(request)
|
|
83
|
+
try:
|
|
84
|
+
return {"template": catalog.clone_template(kind, template_id, req.name)}
|
|
85
|
+
except MarketplaceError as exc:
|
|
86
|
+
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
87
|
+
|
|
75
88
|
@router.get("/marketplace/templates/registry")
|
|
76
89
|
async def template_registry(request: Request):
|
|
77
90
|
require_user(request)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Memory platform + Memory Manager API router (v3.2.0).
|
|
2
|
+
|
|
3
|
+
Exposes :class:`~latticeai.services.memory_service.MemoryService` so the /app
|
|
4
|
+
Memory view can inspect every memory tier, recall across them, and run manager
|
|
5
|
+
operations (prune / compact / rebuild / clear). Full paths in decorators.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any, Callable, List, Optional
|
|
11
|
+
|
|
12
|
+
from fastapi import APIRouter, HTTPException, Request
|
|
13
|
+
from pydantic import BaseModel
|
|
14
|
+
|
|
15
|
+
from latticeai.services.memory_service import MemoryService
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class RecallRequest(BaseModel):
|
|
19
|
+
query: str = ""
|
|
20
|
+
limit: int = 20
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class PruneRequest(BaseModel):
|
|
24
|
+
ids: List[str] = []
|
|
25
|
+
kind: Optional[str] = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RebuildRequest(BaseModel):
|
|
29
|
+
target: str = "vector"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ClearRequest(BaseModel):
|
|
33
|
+
scope: str
|
|
34
|
+
confirm: bool = False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def create_memory_router(
|
|
38
|
+
*,
|
|
39
|
+
service: MemoryService,
|
|
40
|
+
require_user: Callable[[Request], str],
|
|
41
|
+
get_current_user: Callable[[Request], Optional[str]],
|
|
42
|
+
gate_read: Callable[[Request], Optional[str]],
|
|
43
|
+
gate_write: Callable[[Request], Optional[str]],
|
|
44
|
+
append_audit_event: Callable[..., None],
|
|
45
|
+
) -> APIRouter:
|
|
46
|
+
router = APIRouter()
|
|
47
|
+
|
|
48
|
+
@router.get("/api/memory/manager")
|
|
49
|
+
async def memory_manager(request: Request):
|
|
50
|
+
user = require_user(request)
|
|
51
|
+
scope = gate_read(request)
|
|
52
|
+
return service.manager(user_email=user, workspace_id=scope)
|
|
53
|
+
|
|
54
|
+
@router.get("/api/memory/tiers")
|
|
55
|
+
async def memory_tiers(request: Request):
|
|
56
|
+
require_user(request)
|
|
57
|
+
return service.tiers()
|
|
58
|
+
|
|
59
|
+
@router.get("/api/memory/inspect")
|
|
60
|
+
async def memory_inspect(request: Request, source: str, limit: int = 50):
|
|
61
|
+
user = require_user(request)
|
|
62
|
+
scope = gate_read(request)
|
|
63
|
+
try:
|
|
64
|
+
return service.inspect(source, user_email=user, workspace_id=scope, limit=limit)
|
|
65
|
+
except KeyError as exc:
|
|
66
|
+
raise HTTPException(status_code=404, detail=f"Unknown memory source: {source}") from exc
|
|
67
|
+
|
|
68
|
+
@router.post("/api/memory/recall")
|
|
69
|
+
async def memory_recall(req: RecallRequest, request: Request):
|
|
70
|
+
user = require_user(request)
|
|
71
|
+
scope = gate_read(request)
|
|
72
|
+
return service.recall(req.query, user_email=user, workspace_id=scope, limit=req.limit)
|
|
73
|
+
|
|
74
|
+
@router.post("/api/memory/prune")
|
|
75
|
+
async def memory_prune(req: PruneRequest, request: Request):
|
|
76
|
+
user = require_user(request)
|
|
77
|
+
gate_write(request)
|
|
78
|
+
result = service.prune(ids=req.ids, kind=req.kind, user_email=user)
|
|
79
|
+
append_audit_event("memory_prune", user_email=user, count=result.get("count", 0))
|
|
80
|
+
return result
|
|
81
|
+
|
|
82
|
+
@router.post("/api/memory/compact")
|
|
83
|
+
async def memory_compact(request: Request):
|
|
84
|
+
user = require_user(request)
|
|
85
|
+
gate_write(request)
|
|
86
|
+
result = service.compact(user_email=user)
|
|
87
|
+
append_audit_event("memory_compact", user_email=user, compacted=result.get("compacted", 0))
|
|
88
|
+
return result
|
|
89
|
+
|
|
90
|
+
@router.post("/api/memory/rebuild")
|
|
91
|
+
async def memory_rebuild(req: RebuildRequest, request: Request):
|
|
92
|
+
user = require_user(request)
|
|
93
|
+
gate_write(request)
|
|
94
|
+
result = service.rebuild(req.target)
|
|
95
|
+
append_audit_event("memory_rebuild", user_email=user, target=req.target, status=result.get("status"))
|
|
96
|
+
return result
|
|
97
|
+
|
|
98
|
+
@router.post("/api/memory/clear")
|
|
99
|
+
async def memory_clear(req: ClearRequest, request: Request):
|
|
100
|
+
user = require_user(request)
|
|
101
|
+
gate_write(request)
|
|
102
|
+
try:
|
|
103
|
+
result = service.clear(scope=req.scope, confirm=req.confirm, user_email=user)
|
|
104
|
+
except ValueError as exc:
|
|
105
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
106
|
+
append_audit_event("memory_clear", user_email=user, scope=req.scope)
|
|
107
|
+
return result
|
|
108
|
+
|
|
109
|
+
return router
|