livepilot 1.23.3 → 1.23.4
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/CHANGELOG.md +93 -0
- package/README.md +106 -8
- package/m4l_device/LivePilot_Analyzer.amxd +0 -0
- package/m4l_device/livepilot_bridge.js +1 -1
- package/mcp_server/__init__.py +1 -1
- package/mcp_server/atlas/cross_pack_chain.py +658 -0
- package/mcp_server/atlas/demo_story.py +700 -0
- package/mcp_server/atlas/extract_chain.py +786 -0
- package/mcp_server/atlas/macro_fingerprint.py +554 -0
- package/mcp_server/atlas/overlays.py +95 -3
- package/mcp_server/atlas/pack_aware_compose.py +1255 -0
- package/mcp_server/atlas/preset_resolver.py +238 -0
- package/mcp_server/atlas/tools.py +1001 -31
- package/mcp_server/atlas/transplant.py +1177 -0
- package/mcp_server/mix_engine/state_builder.py +44 -1
- package/mcp_server/runtime/capability_state.py +34 -3
- package/mcp_server/server.py +45 -24
- package/mcp_server/tools/agent_os.py +33 -9
- package/mcp_server/tools/analyzer.py +38 -7
- package/mcp_server/tools/browser.py +20 -1
- package/mcp_server/tools/devices.py +78 -11
- package/mcp_server/tools/perception.py +5 -1
- package/mcp_server/tools/tracks.py +39 -2
- package/mcp_server/user_corpus/__init__.py +48 -0
- package/mcp_server/user_corpus/manifest.py +142 -0
- package/mcp_server/user_corpus/plugin_engine/__init__.py +39 -0
- package/mcp_server/user_corpus/plugin_engine/detector.py +579 -0
- package/mcp_server/user_corpus/plugin_engine/manual.py +347 -0
- package/mcp_server/user_corpus/plugin_engine/research.py +247 -0
- package/mcp_server/user_corpus/runner.py +261 -0
- package/mcp_server/user_corpus/scanner.py +115 -0
- package/mcp_server/user_corpus/scanners/__init__.py +18 -0
- package/mcp_server/user_corpus/scanners/adg.py +79 -0
- package/mcp_server/user_corpus/scanners/als.py +144 -0
- package/mcp_server/user_corpus/scanners/amxd.py +374 -0
- package/mcp_server/user_corpus/scanners/plugin_preset.py +202 -0
- package/mcp_server/user_corpus/tools.py +904 -0
- package/mcp_server/user_corpus/wizard.py +224 -0
- package/package.json +2 -2
- package/remote_script/LivePilot/__init__.py +1 -1
- package/remote_script/LivePilot/browser.py +7 -2
- package/requirements.txt +3 -3
- package/server.json +2 -2
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""User-corpus builder — scan your own .als / .adg / .amxd / plugin presets / samples
|
|
2
|
+
into queryable atlas overlays.
|
|
3
|
+
|
|
4
|
+
See docs/USER_CORPUS_GUIDE.md for the full architecture + user guide.
|
|
5
|
+
|
|
6
|
+
Public API:
|
|
7
|
+
from mcp_server.user_corpus import (
|
|
8
|
+
Scanner, register_scanner, get_scanner, list_scanners,
|
|
9
|
+
Manifest, Source, load_manifest, save_manifest,
|
|
10
|
+
run_scan, ScanResult,
|
|
11
|
+
)
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from .scanner import Scanner, register_scanner, get_scanner, list_scanners
|
|
16
|
+
from .manifest import (
|
|
17
|
+
Manifest,
|
|
18
|
+
Source,
|
|
19
|
+
load_manifest,
|
|
20
|
+
save_manifest,
|
|
21
|
+
init_default_manifest,
|
|
22
|
+
DEFAULT_MANIFEST_PATH,
|
|
23
|
+
DEFAULT_OUTPUT_ROOT,
|
|
24
|
+
)
|
|
25
|
+
from .runner import run_scan, ScanResult, SourceScanResult
|
|
26
|
+
|
|
27
|
+
# Eager-import the built-in scanners so their @register_scanner decorators fire.
|
|
28
|
+
from .scanners import als as _als # noqa: F401
|
|
29
|
+
from .scanners import adg as _adg # noqa: F401
|
|
30
|
+
from .scanners import amxd as _amxd # noqa: F401
|
|
31
|
+
from .scanners import plugin_preset as _pp # noqa: F401
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"Scanner",
|
|
35
|
+
"register_scanner",
|
|
36
|
+
"get_scanner",
|
|
37
|
+
"list_scanners",
|
|
38
|
+
"Manifest",
|
|
39
|
+
"Source",
|
|
40
|
+
"load_manifest",
|
|
41
|
+
"save_manifest",
|
|
42
|
+
"init_default_manifest",
|
|
43
|
+
"DEFAULT_MANIFEST_PATH",
|
|
44
|
+
"DEFAULT_OUTPUT_ROOT",
|
|
45
|
+
"run_scan",
|
|
46
|
+
"ScanResult",
|
|
47
|
+
"SourceScanResult",
|
|
48
|
+
]
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Manifest — declarative source registry for user corpus scans.
|
|
2
|
+
|
|
3
|
+
Schema lives in the YAML; this module is just (de)serialization + dataclasses.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from dataclasses import dataclass, field, asdict
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
import yaml
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# ─── Default paths ───────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
DEFAULT_OUTPUT_ROOT = Path.home() / ".livepilot" / "atlas-overlays" / "user"
|
|
20
|
+
DEFAULT_MANIFEST_PATH = DEFAULT_OUTPUT_ROOT / "manifest.yaml"
|
|
21
|
+
|
|
22
|
+
CURRENT_SCHEMA_VERSION = 1
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# ─── Data classes ────────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class Source:
|
|
30
|
+
"""One declared scan source."""
|
|
31
|
+
id: str
|
|
32
|
+
type: str # scanner type_id
|
|
33
|
+
path: str # filesystem path (may contain ~)
|
|
34
|
+
recursive: bool = True
|
|
35
|
+
exclude_globs: list[str] = field(default_factory=list)
|
|
36
|
+
last_scanned: str | None = None # ISO 8601 UTC, set by the runner
|
|
37
|
+
file_count: int | None = None # set by the runner after scan
|
|
38
|
+
options: dict[str, Any] = field(default_factory=dict)
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def resolved_path(self) -> Path:
|
|
42
|
+
return Path(os.path.expanduser(self.path)).resolve()
|
|
43
|
+
|
|
44
|
+
def mark_scanned(self, file_count: int) -> None:
|
|
45
|
+
self.last_scanned = datetime.now(timezone.utc).isoformat(timespec="seconds")
|
|
46
|
+
self.file_count = file_count
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class Manifest:
|
|
51
|
+
"""Top-level manifest — all scan sources + global options."""
|
|
52
|
+
schema_version: int = CURRENT_SCHEMA_VERSION
|
|
53
|
+
sources: list[Source] = field(default_factory=list)
|
|
54
|
+
output: dict[str, Any] = field(default_factory=lambda: {
|
|
55
|
+
"root": str(DEFAULT_OUTPUT_ROOT),
|
|
56
|
+
"schema_version": CURRENT_SCHEMA_VERSION,
|
|
57
|
+
})
|
|
58
|
+
options: dict[str, Any] = field(default_factory=lambda: {
|
|
59
|
+
"parallel_workers": 4,
|
|
60
|
+
"skip_unchanged": True,
|
|
61
|
+
"log_level": "info",
|
|
62
|
+
"on_error": "continue",
|
|
63
|
+
})
|
|
64
|
+
ai_annotation: dict[str, Any] = field(default_factory=lambda: {
|
|
65
|
+
"enabled": False,
|
|
66
|
+
"model": "sonnet",
|
|
67
|
+
"fields": [
|
|
68
|
+
"sonic_fingerprint",
|
|
69
|
+
"tags",
|
|
70
|
+
"reach_for",
|
|
71
|
+
"avoid",
|
|
72
|
+
"cross_references",
|
|
73
|
+
],
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def output_root(self) -> Path:
|
|
78
|
+
return Path(os.path.expanduser(self.output.get("root", str(DEFAULT_OUTPUT_ROOT))))
|
|
79
|
+
|
|
80
|
+
def find_source(self, source_id: str) -> Source | None:
|
|
81
|
+
for s in self.sources:
|
|
82
|
+
if s.id == source_id:
|
|
83
|
+
return s
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def add_source(self, source: Source) -> None:
|
|
87
|
+
if self.find_source(source.id):
|
|
88
|
+
raise ValueError(f"Source id '{source.id}' already exists; remove or rename first")
|
|
89
|
+
self.sources.append(source)
|
|
90
|
+
|
|
91
|
+
def remove_source(self, source_id: str) -> Source | None:
|
|
92
|
+
match = self.find_source(source_id)
|
|
93
|
+
if match:
|
|
94
|
+
self.sources.remove(match)
|
|
95
|
+
return match
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# ─── (De)serialization ───────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def load_manifest(path: Path = DEFAULT_MANIFEST_PATH) -> Manifest:
|
|
102
|
+
"""Load a manifest YAML. Returns a default Manifest if the file is missing."""
|
|
103
|
+
if not path.exists():
|
|
104
|
+
return Manifest()
|
|
105
|
+
raw = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
|
|
106
|
+
sources = [Source(**s) for s in (raw.get("sources") or [])]
|
|
107
|
+
return Manifest(
|
|
108
|
+
schema_version=raw.get("schema_version", CURRENT_SCHEMA_VERSION),
|
|
109
|
+
sources=sources,
|
|
110
|
+
output=raw.get("output") or Manifest().output,
|
|
111
|
+
options=raw.get("options") or Manifest().options,
|
|
112
|
+
ai_annotation=raw.get("ai_annotation") or Manifest().ai_annotation,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def save_manifest(manifest: Manifest, path: Path = DEFAULT_MANIFEST_PATH) -> None:
|
|
117
|
+
"""Persist a manifest as YAML. Creates parent dirs if needed."""
|
|
118
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
119
|
+
data = {
|
|
120
|
+
"schema_version": manifest.schema_version,
|
|
121
|
+
"sources": [
|
|
122
|
+
{k: v for k, v in asdict(s).items() if v is not None and v != [] and v != {}}
|
|
123
|
+
for s in manifest.sources
|
|
124
|
+
],
|
|
125
|
+
"output": manifest.output,
|
|
126
|
+
"options": manifest.options,
|
|
127
|
+
"ai_annotation": manifest.ai_annotation,
|
|
128
|
+
}
|
|
129
|
+
path.write_text(
|
|
130
|
+
yaml.dump(data, sort_keys=False, default_flow_style=False, width=200, allow_unicode=True),
|
|
131
|
+
encoding="utf-8",
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def init_default_manifest(path: Path = DEFAULT_MANIFEST_PATH) -> Manifest:
|
|
136
|
+
"""Create a fresh manifest at the default path, ensuring directory exists."""
|
|
137
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
138
|
+
if path.exists():
|
|
139
|
+
return load_manifest(path)
|
|
140
|
+
m = Manifest()
|
|
141
|
+
save_manifest(m, path)
|
|
142
|
+
return m
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Plugin Knowledge Engine — detects installed plugins, extracts identity from
|
|
2
|
+
their bundles, finds + extracts manuals, and emits research / synthesis briefs
|
|
3
|
+
for the agent to fulfill via WebSearch + sonnet subagents.
|
|
4
|
+
|
|
5
|
+
See docs/PLUGIN_KNOWLEDGE_ENGINE.md for the full architecture.
|
|
6
|
+
|
|
7
|
+
Public API:
|
|
8
|
+
from mcp_server.user_corpus.plugin_engine import (
|
|
9
|
+
detect_installed_plugins, discover_manuals_for_plugin,
|
|
10
|
+
extract_manual_text, build_research_targets,
|
|
11
|
+
build_synthesis_brief, default_plugin_dir,
|
|
12
|
+
)
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from .detector import (
|
|
17
|
+
detect_installed_plugins,
|
|
18
|
+
default_plugin_dir,
|
|
19
|
+
DetectedPlugin,
|
|
20
|
+
)
|
|
21
|
+
from .manual import (
|
|
22
|
+
discover_manuals_for_plugin,
|
|
23
|
+
extract_manual_text,
|
|
24
|
+
ManualCandidate,
|
|
25
|
+
ManualExtraction,
|
|
26
|
+
)
|
|
27
|
+
from .research import build_research_targets, build_synthesis_brief
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"detect_installed_plugins",
|
|
31
|
+
"default_plugin_dir",
|
|
32
|
+
"DetectedPlugin",
|
|
33
|
+
"discover_manuals_for_plugin",
|
|
34
|
+
"extract_manual_text",
|
|
35
|
+
"ManualCandidate",
|
|
36
|
+
"ManualExtraction",
|
|
37
|
+
"build_research_targets",
|
|
38
|
+
"build_synthesis_brief",
|
|
39
|
+
]
|