ltcai 8.1.0 → 8.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.
Files changed (110) hide show
  1. package/README.md +20 -41
  2. package/docs/CHANGELOG.md +38 -874
  3. package/docs/DEVELOPMENT.md +26 -3
  4. package/docs/LEGACY_COMPATIBILITY.md +3 -1
  5. package/docs/TRUST_MODEL.md +26 -26
  6. package/docs/WHY_LATTICE.md +28 -25
  7. package/docs/kg-schema.md +6 -4
  8. package/lattice_brain/__init__.py +1 -1
  9. package/lattice_brain/graph/schema.py +6 -0
  10. package/lattice_brain/runtime/multi_agent.py +1 -1
  11. package/latticeai/__init__.py +1 -1
  12. package/latticeai/api/computer_use.py +2 -0
  13. package/latticeai/api/memory.py +13 -0
  14. package/latticeai/app_factory.py +30 -28
  15. package/latticeai/brain/__init__.py +1 -1
  16. package/latticeai/core/config.py +10 -0
  17. package/latticeai/core/marketplace.py +1 -1
  18. package/latticeai/core/tool_registry.py +10 -0
  19. package/latticeai/core/workspace_graph_trace.py +132 -0
  20. package/latticeai/core/workspace_memory.py +75 -0
  21. package/latticeai/core/workspace_os.py +135 -1283
  22. package/latticeai/core/workspace_os_utils.py +132 -0
  23. package/latticeai/core/workspace_permissions.py +99 -0
  24. package/latticeai/core/workspace_plugins.py +97 -0
  25. package/latticeai/core/workspace_runs.py +612 -0
  26. package/latticeai/core/workspace_skills.py +114 -0
  27. package/latticeai/core/workspace_snapshots.py +195 -0
  28. package/latticeai/core/workspace_timeline.py +107 -0
  29. package/latticeai/runtime/audit_runtime.py +64 -0
  30. package/latticeai/runtime/config_runtime.py +4 -0
  31. package/latticeai/runtime/sso_runtime.py +52 -0
  32. package/latticeai/services/architecture_readiness.py +3 -3
  33. package/latticeai/services/memory_service.py +215 -7
  34. package/latticeai/services/model_capability_registry.py +68 -0
  35. package/latticeai/services/model_engines.py +603 -0
  36. package/latticeai/services/model_loading.py +482 -0
  37. package/latticeai/services/model_recommendation.py +5 -0
  38. package/latticeai/services/model_runtime.py +141 -866
  39. package/latticeai/services/product_readiness.py +19 -18
  40. package/package.json +1 -1
  41. package/src-tauri/Cargo.lock +1 -1
  42. package/src-tauri/Cargo.toml +1 -1
  43. package/src-tauri/tauri.conf.json +1 -1
  44. package/static/app/asset-manifest.json +11 -11
  45. package/static/app/assets/{Act-BOO66G-c.js → Act-D9jIknFd.js} +1 -1
  46. package/static/app/assets/{Brain-C6lEYiD7.js → Brain-CFOtWbPN.js} +1 -1
  47. package/static/app/assets/{Capture-TATXBRDw.js → Capture-Q4WYzwr5.js} +1 -1
  48. package/static/app/assets/{Library-DK4FIp8a.js → Library-C5Q2yWee.js} +1 -1
  49. package/static/app/assets/{System-Bgs6Ql7x.js → System-BLbjdr1_.js} +1 -1
  50. package/static/app/assets/index-BqammyNu.js +16 -0
  51. package/static/app/assets/index-ty1iGgZu.css +2 -0
  52. package/static/app/assets/{primitives-B70WOra0.js → primitives-Br8uSfZ4.js} +1 -1
  53. package/static/app/assets/{textarea-Czrd9gwM.js → textarea-BnhNs1_X.js} +1 -1
  54. package/static/app/index.html +2 -2
  55. package/static/sw.js +1 -1
  56. package/tools/__init__.py +2 -1
  57. package/tools/computer.py +21 -0
  58. package/docs/CARRYOVER_AUDIT_v3.6.0.md +0 -61
  59. package/docs/HANDOVER_v3.6.0.md +0 -46
  60. package/docs/RUNTIME_HOOK_COVERAGE_v3.5.0.md +0 -56
  61. package/docs/RUNTIME_HOOK_COVERAGE_v3.6.0.md +0 -49
  62. package/docs/V2_ARCHITECTURE.md +0 -561
  63. package/docs/V3_2_AUDIT.md +0 -82
  64. package/docs/V3_BACKEND_ARCHITECTURE.md +0 -138
  65. package/docs/V3_FRONTEND.md +0 -146
  66. package/docs/V4_1_FRONTEND_ARCHITECTURE_REVIEW.md +0 -65
  67. package/docs/V4_1_FRONTEND_MIGRATION_REPORT.md +0 -70
  68. package/docs/V4_1_VALIDATION_REPORT.md +0 -47
  69. package/docs/V4_2_BRAIN_CORE_ARCHITECTURE.md +0 -97
  70. package/docs/V4_2_STORAGE_MIGRATION_REPORT.md +0 -91
  71. package/docs/V4_2_VALIDATION_REPORT.md +0 -89
  72. package/docs/V4_3_2_DEADCODE_AUDIT_REPORT.md +0 -174
  73. package/docs/V4_3_2_DOCUMENTATION_CLEANUP_REPORT.md +0 -81
  74. package/docs/V4_3_2_GITHUB_VERCEL_CHECK_REPORT.md +0 -75
  75. package/docs/V4_3_2_GRAPH_UX_REPORT.md +0 -48
  76. package/docs/V4_3_2_INDEPENDENT_AUDIT_PACKAGE.md +0 -209
  77. package/docs/V4_3_2_PRODUCT_POLISH_REPORT.md +0 -57
  78. package/docs/V4_3_2_SELF_AUDIT_REPORT.md +0 -63
  79. package/docs/V4_3_2_VALIDATION_REPORT.md +0 -97
  80. package/docs/V4_3_3_VALIDATION_REPORT.md +0 -46
  81. package/docs/V4_3_PORTABILITY_ARCHITECTURE.md +0 -69
  82. package/docs/V4_3_PRIVACY_AUDIT.md +0 -60
  83. package/docs/V4_3_PRODUCT_HARDENING_REPORT.md +0 -53
  84. package/docs/V4_3_VALIDATION_REPORT.md +0 -58
  85. package/docs/V4_4_0_EXTRACTION_REPORT.md +0 -239
  86. package/docs/V4_5_0_GEMMA_RUNTIME_COMPATIBILITY_REPORT.md +0 -49
  87. package/docs/V4_5_0_GRAPH_UX_REPORT.md +0 -34
  88. package/docs/V4_5_0_MODEL_RUNTIME_UX_REPORT.md +0 -40
  89. package/docs/V4_5_0_ONBOARDING_REPORT.md +0 -31
  90. package/docs/V4_5_0_PRODUCT_EXPERIENCE_RECOVERY_REPORT.md +0 -49
  91. package/docs/V4_5_0_VALIDATION_REPORT.md +0 -60
  92. package/docs/V4_5_1_GRAPH_EXPERIENCE_REPORT.md +0 -33
  93. package/docs/V4_5_1_MODEL_EXPERIENCE_REPORT.md +0 -37
  94. package/docs/V4_5_1_NAVIGATION_REPORT.md +0 -37
  95. package/docs/V4_5_1_ONBOARDING_REPORT.md +0 -29
  96. package/docs/V4_5_1_PRODUCT_REIMAGINING_REPORT.md +0 -61
  97. package/docs/V4_5_1_RC_ARTIFACTS.md +0 -44
  98. package/docs/V4_5_1_UX_REPORT.md +0 -45
  99. package/docs/V4_5_1_VALIDATION_REPORT.md +0 -55
  100. package/docs/V4_5_1_VISUAL_DESIGN_REPORT.md +0 -30
  101. package/docs/V4_6_0_LIVING_BRAIN_EXPERIENCE_REPORT.md +0 -72
  102. package/docs/V4_6_1_RELEASE_REFRESH_REPORT.md +0 -42
  103. package/docs/V4_7_0_ADMIN_SEPARATION_REPORT.md +0 -42
  104. package/docs/V4_7_1_ADMIN_OPERATIONS_REPORT.md +0 -49
  105. package/docs/V4_7_2_INTUITIVE_BRAIN_UX_REPORT.md +0 -62
  106. package/docs/V4_BRAIN_ARCHITECTURE.md +0 -322
  107. package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +0 -555
  108. package/docs/V4_IMPLEMENTATION_PLAN.md +0 -470
  109. package/static/app/assets/index-Bvv79nre.js +0 -16
  110. package/static/app/assets/index-Dslqglia.css +0 -2
@@ -26,6 +26,8 @@ from datetime import datetime
26
26
  from pathlib import Path
27
27
  from typing import Any, Dict, List, Optional
28
28
 
29
+ from latticeai.core.workspace_os_utils import _file_size
30
+
29
31
  # Personal workspace memory kinds (from WorkspaceOS.MEMORY_KINDS).
30
32
  WORKSPACE_KINDS = (
31
33
  "short_term",
@@ -44,13 +46,6 @@ def _now() -> str:
44
46
  return datetime.now().isoformat(timespec="seconds")
45
47
 
46
48
 
47
- def _file_size(path: Path) -> int:
48
- try:
49
- return path.stat().st_size if path.exists() else 0
50
- except Exception:
51
- return 0
52
-
53
-
54
49
  class MemoryService:
55
50
  def __init__(
56
51
  self,
@@ -293,6 +288,219 @@ class MemoryService:
293
288
  """Return the backend-owned Brain readiness signal for API consumers."""
294
289
  return self.manager(user_email=user_email, workspace_id=workspace_id)["brain_readiness"]
295
290
 
291
+ def brain_brief(
292
+ self,
293
+ *,
294
+ user_email: Optional[str] = None,
295
+ workspace_id: Optional[str] = None,
296
+ active_model: Optional[str] = None,
297
+ recall_query: str = "",
298
+ limit: int = 3,
299
+ ) -> Dict[str, Any]:
300
+ """Return a compact, evidence-backed Brain briefing for the home screen.
301
+
302
+ The brief intentionally reuses the Memory Manager and Brain Proof data
303
+ instead of inventing UI-only facts. It answers three product questions:
304
+ what should the user notice, why can the Brain prove it, and what is the
305
+ easiest next action.
306
+ """
307
+ manager = self.manager(user_email=user_email, workspace_id=workspace_id)
308
+ proof = self.brain_proof(
309
+ user_email=user_email,
310
+ workspace_id=workspace_id,
311
+ active_model=active_model,
312
+ recall_query=recall_query,
313
+ limit=limit,
314
+ )
315
+ readiness = manager.get("brain_readiness") or {}
316
+ state = str(readiness.get("state") or "quiet")
317
+ proofs = proof.get("proofs") or {}
318
+ recall = proof.get("recall") or {}
319
+ recall_items = [item for item in recall.get("items") or [] if isinstance(item, dict)]
320
+ durable_items = int(proofs.get("durable_items") or 0)
321
+ workspace_memories = int(proofs.get("workspace_memories") or 0)
322
+ conversations = int(proofs.get("conversations") or 0)
323
+ graph_concepts = int(proofs.get("graph_concepts") or 0)
324
+ vector_items = int(proofs.get("vector_items") or 0)
325
+ healthy_sources = int(proofs.get("healthy_sources") or 0)
326
+
327
+ focus = self._brain_brief_focus(
328
+ user_email=user_email,
329
+ workspace_id=workspace_id,
330
+ recall_items=recall_items,
331
+ durable_items=durable_items,
332
+ graph_concepts=graph_concepts,
333
+ query=str(recall.get("query") or recall_query or ""),
334
+ )
335
+ actions = self._brain_brief_actions(
336
+ state=state,
337
+ has_durable_evidence=bool(proofs.get("has_durable_evidence")),
338
+ has_recall=bool(recall_items),
339
+ graph_concepts=graph_concepts,
340
+ )
341
+ return {
342
+ "status": state,
343
+ "score": int(readiness.get("score") or 0),
344
+ "headline_key": f"brain.brief.headline.{state if state in {'quiet', 'forming', 'alive'} else 'quiet'}",
345
+ "body_key": f"brain.brief.body.{state if state in {'quiet', 'forming', 'alive'} else 'quiet'}",
346
+ "focus": focus,
347
+ "next_actions": actions,
348
+ "evidence": [
349
+ {
350
+ "id": "durable",
351
+ "label_key": "brain.brief.evidence.durable",
352
+ "value": durable_items,
353
+ "detail_key": "brain.brief.evidence.durable.detail",
354
+ },
355
+ {
356
+ "id": "graph",
357
+ "label_key": "brain.brief.evidence.graph",
358
+ "value": graph_concepts,
359
+ "detail_key": "brain.brief.evidence.graph.detail",
360
+ },
361
+ {
362
+ "id": "sources",
363
+ "label_key": "brain.brief.evidence.sources",
364
+ "value": healthy_sources,
365
+ "detail_key": "brain.brief.evidence.sources.detail",
366
+ },
367
+ ],
368
+ "signals": {
369
+ "workspace_memories": workspace_memories,
370
+ "conversations": conversations,
371
+ "graph_concepts": graph_concepts,
372
+ "vector_items": vector_items,
373
+ "healthy_sources": healthy_sources,
374
+ },
375
+ "proof": {
376
+ "query": recall.get("query") or "",
377
+ "items": recall_items[: max(1, min(limit, 6))],
378
+ "model_continuity": proof.get("model_continuity") or {},
379
+ },
380
+ "generated_at": _now(),
381
+ }
382
+
383
+ def _brain_brief_focus(
384
+ self,
385
+ *,
386
+ user_email: Optional[str],
387
+ workspace_id: Optional[str],
388
+ recall_items: List[Dict[str, Any]],
389
+ durable_items: int,
390
+ graph_concepts: int,
391
+ query: str,
392
+ ) -> Dict[str, Any]:
393
+ if recall_items:
394
+ first = recall_items[0]
395
+ return {
396
+ "kind": "recall",
397
+ "title": str(first.get("title") or "Memory"),
398
+ "detail": str(first.get("snippet") or query or ""),
399
+ "source": str(first.get("source") or "memory"),
400
+ "score": float(first.get("score") or 0),
401
+ }
402
+
403
+ memories = self._workspace_memories(user_email=user_email, workspace_id=workspace_id or "personal")
404
+ if memories:
405
+ first_memory = memories[0]
406
+ return {
407
+ "kind": "memory",
408
+ "title": str(first_memory.get("kind") or "memory"),
409
+ "detail": str(first_memory.get("content") or "")[:240],
410
+ "source": "workspace",
411
+ "score": 1.0,
412
+ }
413
+
414
+ conversations = self._scoped_conversations(user_email=user_email, workspace_id=workspace_id)
415
+ if conversations:
416
+ latest = conversations[-1]
417
+ messages = latest.get("messages") if isinstance(latest, dict) else []
418
+ last_message = next((m for m in reversed(messages or []) if isinstance(m, dict) and str(m.get("content") or "").strip()), {})
419
+ return {
420
+ "kind": "conversation",
421
+ "title": str(latest.get("title") or latest.get("id") or "conversation"),
422
+ "detail": str(last_message.get("content") or "")[:240],
423
+ "source": "conversation",
424
+ "score": 1.0,
425
+ }
426
+
427
+ if graph_concepts > 0:
428
+ return {
429
+ "kind": "graph",
430
+ "title": "Knowledge Graph",
431
+ "detail": f"{graph_concepts} graph concepts are ready to inspect.",
432
+ "source": "graph",
433
+ "score": 1.0,
434
+ }
435
+
436
+ return {
437
+ "kind": "empty",
438
+ "title": "",
439
+ "detail": "",
440
+ "source": "none",
441
+ "score": 0,
442
+ "empty": durable_items <= 0,
443
+ }
444
+
445
+ @staticmethod
446
+ def _brain_brief_actions(
447
+ *,
448
+ state: str,
449
+ has_durable_evidence: bool,
450
+ has_recall: bool,
451
+ graph_concepts: int,
452
+ ) -> List[Dict[str, Any]]:
453
+ actions: List[Dict[str, Any]] = []
454
+ if not has_durable_evidence:
455
+ actions.extend([
456
+ {
457
+ "id": "add_source",
458
+ "label_key": "brain.brief.action.add",
459
+ "detail_key": "brain.brief.action.add.detail",
460
+ "route": "/capture",
461
+ "priority": 10,
462
+ },
463
+ {
464
+ "id": "ask_brain",
465
+ "label_key": "brain.brief.action.ask",
466
+ "detail_key": "brain.brief.action.ask.detail",
467
+ "route": "",
468
+ "priority": 9,
469
+ },
470
+ ])
471
+ else:
472
+ actions.append({
473
+ "id": "ask_brain",
474
+ "label_key": "brain.brief.action.ask",
475
+ "detail_key": "brain.brief.action.ask.detail",
476
+ "route": "",
477
+ "priority": 10,
478
+ })
479
+ if graph_concepts > 0 or state == "alive":
480
+ actions.append({
481
+ "id": "inspect_topics",
482
+ "label_key": "brain.brief.action.topics",
483
+ "detail_key": "brain.brief.action.topics.detail",
484
+ "route": "/knowledge-graph",
485
+ "priority": 8,
486
+ })
487
+ if has_recall:
488
+ actions.append({
489
+ "id": "verify_model",
490
+ "label_key": "brain.brief.action.verify",
491
+ "detail_key": "brain.brief.action.verify.detail",
492
+ "route": "",
493
+ "priority": 7,
494
+ })
495
+ actions.append({
496
+ "id": "backup_brain",
497
+ "label_key": "brain.brief.action.backup",
498
+ "detail_key": "brain.brief.action.backup.detail",
499
+ "route": "/settings",
500
+ "priority": 6,
501
+ })
502
+ return sorted(actions, key=lambda item: int(item.get("priority") or 0), reverse=True)[:4]
503
+
296
504
  def brain_proof(
297
505
  self,
298
506
  *,
@@ -414,6 +414,74 @@ _REGISTRY: List[ModelCapability] = [
414
414
  ),
415
415
  display_priority=45,
416
416
  ),
417
+
418
+ # Additional recent multimodal (2025-2026 era ports, MLX-first where possible)
419
+ ModelCapability(
420
+ id="mlx-community/Llama-3.2-11B-Vision-Instruct-4bit",
421
+ hf_repo_id="mlx-community/Llama-3.2-11B-Vision-Instruct-4bit",
422
+ name="Llama 3.2 11B Vision Instruct",
423
+ family="Llama 3.2 Vision",
424
+ tag="local-vlm",
425
+ size="6.8GB",
426
+ quantization="4bit",
427
+ provider_hints=["local_mlx", "ollama", "llamacpp"],
428
+ download_strategy="hf_hub",
429
+ load_strategy="mlx_vlm",
430
+ hardware=HardwareProfile(min_ram_gb=10.0, recommended_ram_gb=14.0, apple_silicon_pref=True, notes="Excellent vision for its size. Great all-rounder multimodal."),
431
+ source_country="미국", source_company="Meta",
432
+ verification=VerificationStatus(hf_exists=True, has_config=True, has_tokenizer=True, has_weights_hint=True, pipeline_tag="image-text-to-text", license="llama3.2", verified_by="hf-api-light"),
433
+ recommended_default=True,
434
+ display_priority=25,
435
+ ),
436
+ ModelCapability(
437
+ id="mlx-community/phi-3.5-vision-4bit",
438
+ hf_repo_id="mlx-community/phi-3.5-vision-4bit",
439
+ name="Phi-3.5 Vision 4B",
440
+ family="Phi Vision",
441
+ tag="local-vlm",
442
+ size="3.2GB",
443
+ quantization="4bit",
444
+ provider_hints=["local_mlx"],
445
+ download_strategy="hf_hub",
446
+ load_strategy="mlx_vlm",
447
+ hardware=HardwareProfile(min_ram_gb=6.0, recommended_ram_gb=8.0, apple_silicon_pref=True, notes="Microsoft small VLM, fast and capable for on-device vision tasks."),
448
+ source_country="미국", source_company="Microsoft",
449
+ verification=VerificationStatus(hf_exists=True, has_config=True, has_tokenizer=True, has_weights_hint=True, pipeline_tag="image-text-to-text", license="mit", verified_by="hf-api-light"),
450
+ display_priority=30,
451
+ ),
452
+ ModelCapability(
453
+ id="mlx-community/Qwen2.5-VL-7B-Instruct-4bit",
454
+ hf_repo_id="mlx-community/Qwen2.5-VL-7B-Instruct-4bit",
455
+ name="Qwen2.5-VL 7B",
456
+ family="Qwen2.5-VL",
457
+ tag="local-vlm",
458
+ size="4.5GB",
459
+ quantization="4bit",
460
+ provider_hints=["local_mlx", "ollama"],
461
+ download_strategy="hf_hub",
462
+ load_strategy="mlx_vlm",
463
+ hardware=HardwareProfile(min_ram_gb=8.0, recommended_ram_gb=12.0, apple_silicon_pref=True, notes="Strong Chinese/English vision model, updated from Qwen2-VL."),
464
+ source_country="중국", source_company="Alibaba",
465
+ verification=VerificationStatus(hf_exists=True, has_config=True, has_tokenizer=True, has_weights_hint=True, pipeline_tag="image-text-to-text", license="apache-2.0", verified_by="hf-api-light"),
466
+ recommended_default=True,
467
+ display_priority=18,
468
+ ),
469
+ ModelCapability(
470
+ id="mlx-community/moondream2-4bit",
471
+ hf_repo_id="mlx-community/moondream2-4bit",
472
+ name="Moondream2 (small VLM)",
473
+ family="Moondream",
474
+ tag="local-vlm",
475
+ size="1.8GB",
476
+ quantization="4bit",
477
+ provider_hints=["local_mlx"],
478
+ download_strategy="hf_hub",
479
+ load_strategy="mlx_vlm",
480
+ hardware=HardwareProfile(min_ram_gb=4.0, recommended_ram_gb=6.0, apple_silicon_pref=True, notes="Ultra-light vision model for quick descriptions and simple QA. Ideal for low-resource or frequent use."),
481
+ source_country="미국", source_company="vikhyatk",
482
+ verification=VerificationStatus(hf_exists=True, has_config=True, has_tokenizer=True, has_weights_hint=True, pipeline_tag="image-text-to-text", license="apache-2.0", verified_by="hf-api-light"),
483
+ display_priority=8,
484
+ ),
417
485
  ]
418
486
 
419
487