ltcai 3.1.0 → 3.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.
Files changed (54) hide show
  1. package/README.md +35 -8
  2. package/docs/CHANGELOG.md +53 -0
  3. package/docs/V3_2_AUDIT.md +82 -0
  4. package/docs/V3_FRONTEND.md +1 -1
  5. package/docs/architecture.md +6 -0
  6. package/latticeai/__init__.py +1 -1
  7. package/latticeai/api/agent_registry.py +103 -0
  8. package/latticeai/api/hooks.py +113 -0
  9. package/latticeai/api/marketplace.py +13 -0
  10. package/latticeai/api/memory.py +109 -0
  11. package/latticeai/core/agent_registry.py +234 -0
  12. package/latticeai/core/hooks.py +284 -0
  13. package/latticeai/core/marketplace.py +87 -2
  14. package/latticeai/core/multi_agent.py +1 -1
  15. package/latticeai/core/workspace_os.py +1 -1
  16. package/latticeai/server_app.py +41 -0
  17. package/latticeai/services/memory_service.py +324 -0
  18. package/package.json +2 -2
  19. package/scripts/build_v3_assets.mjs +7 -1
  20. package/static/css/{tokens.5a595671.css → tokens.8b8e31bd.css} +1 -1
  21. package/static/css/tokens.css +1 -1
  22. package/static/v3/asset-manifest.json +22 -14
  23. package/static/v3/css/{lattice.views.3ee19d4e.css → lattice.views.1d326beb.css} +5 -0
  24. package/static/v3/css/lattice.views.css +5 -0
  25. package/static/v3/js/{app.46fb61d9.js → app.cf5bb712.js} +1 -1
  26. package/static/v3/js/core/{api.22a41d42.js → api.113660c5.js} +123 -4
  27. package/static/v3/js/core/api.js +123 -4
  28. package/static/v3/js/core/{routes.f935dd50.js → routes.07ad6696.js} +11 -0
  29. package/static/v3/js/core/routes.js +11 -0
  30. package/static/v3/js/core/{shell.1b6199d6.js → shell.9e707234.js} +2 -2
  31. package/static/v3/js/views/{agents.14e48bdd.js → agents.c373d48c.js} +100 -0
  32. package/static/v3/js/views/agents.js +100 -0
  33. package/static/v3/js/views/{chat.718144ce.js → chat.c48fd9e2.js} +1 -1
  34. package/static/v3/js/views/chat.js +1 -1
  35. package/static/v3/js/views/{files.4935197e.js → files.8464634a.js} +64 -18
  36. package/static/v3/js/views/files.js +64 -18
  37. package/static/v3/js/views/hooks.f3edebca.js +99 -0
  38. package/static/v3/js/views/hooks.js +99 -0
  39. package/static/v3/js/views/marketplace.ab0583d4.js +141 -0
  40. package/static/v3/js/views/marketplace.js +141 -0
  41. package/static/v3/js/views/mcp.99b5c6a7.js +114 -0
  42. package/static/v3/js/views/mcp.js +114 -0
  43. package/static/v3/js/views/memory.4ebdf474.js +147 -0
  44. package/static/v3/js/views/memory.js +147 -0
  45. package/static/v3/js/views/planning.9ac3e313.js +153 -0
  46. package/static/v3/js/views/planning.js +153 -0
  47. package/static/v3/js/views/{settings.4f777210.js → settings.c7b0cc05.js} +16 -2
  48. package/static/v3/js/views/settings.js +16 -2
  49. package/static/v3/js/views/skills.c6c2f965.js +109 -0
  50. package/static/v3/js/views/skills.js +109 -0
  51. package/static/v3/js/views/tools.e4f11276.js +108 -0
  52. package/static/v3/js/views/tools.js +108 -0
  53. package/static/v3/js/views/workflows.26c57290.js +128 -0
  54. package/static/v3/js/views/workflows.js +128 -0
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
  [![npm version](https://img.shields.io/npm/v/ltcai?label=npm)](https://www.npmjs.com/package/ltcai)
17
17
  [![VS Code Marketplace](https://vsmarketplacebadges.dev/version-short/parktaesoo.ltcai.svg)](https://marketplace.visualstudio.com/items?itemName=parktaesoo.ltcai)
18
18
  [![Open VSX](https://img.shields.io/open-vsx/v/parktaesoo/ltcai?label=Open%20VSX)](https://open-vsx.org/extension/parktaesoo/ltcai)
19
- [![GitHub release](https://img.shields.io/github/v/release/TaeSooPark-PTS/LatticeAI?label=GitHub%20release)](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.1.0)
19
+ [![GitHub release](https://img.shields.io/github/v/release/TaeSooPark-PTS/LatticeAI?label=GitHub%20release)](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.2.0)
20
20
  [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
21
21
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/)
22
22
  [![VS Code extension](https://img.shields.io/badge/VS%20Code-extension-blue?logo=visualstudiocode)](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.1.0](https://github.com/TaeSooPark-PTS/LatticeAI/releases/tag/v3.1.0)
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.1.0 Highlights
126
-
127
- Lattice AI v3.1.0 completes the non-enterprise local-first workspace platform
128
- around `/app`: Classic is retired from normal workflows, retrieval is wired
129
- through a shared service layer, and browser assets are hash-manifested.
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,9 @@ Core areas:
265
290
 
266
291
  | Version | Theme |
267
292
  | --- | --- |
268
- | **3.1.0** | Mainline platform completionnative `/app` workflows, Classic retired from normal paths, production embedding profiles, AgentRuntime/registries, hashed v3 assets |
293
+ | **3.3.0** | Product quality & honesty release evidence-based feature audit (`FEATURE_STATUS.md`), single-source version truth, working manual document upload in Files, fixed document-generation streaming, truthful Home retrieval status, documented design system (`STYLE_SYSTEM.md`) |
294
+ | 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` |
295
+ | 3.1.0 | Mainline platform completion — native `/app` workflows, Classic retired from normal paths, production embedding profiles, AgentRuntime/registries, hashed v3 assets |
269
296
  | 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
297
  | 3.0.0 | v3 local-first AI workspace platform — `/app`, Native Chat, Knowledge Graph, Vector Index, Hybrid Search, workspace modes |
271
298
  | 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.
@@ -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
- Live surfaces wired in v3.1.0:
101
+ Core live surfaces established before v3.2.0:
102
102
 
103
103
  | Adapter | Endpoint | Unavailable state |
104
104
  | --- | --- | --- |
@@ -1,5 +1,11 @@
1
1
  # Lattice AI Architecture
2
2
 
3
+ > v3.3.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,
@@ -1,3 +1,3 @@
1
1
  """Lattice AI - modular server package."""
2
2
 
3
- __version__ = "3.1.0"
3
+ __version__ = "3.3.0"
@@ -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