nucleus-mcp 1.0.7 → 1.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/package.json +2 -4
- package/.github/workflows/ci.yml +0 -72
- package/.smithery/shttp/module.js +0 -3
- package/.smithery/shttp/module.js.map +0 -7
- package/.smithery/stdio/index.cjs +0 -74
- package/.smithery/stdio/index.cjs.map +0 -7
- package/CHANGELOG.md +0 -65
- package/CODE_OF_CONDUCT.md +0 -34
- package/COMPARISON.md +0 -20
- package/CONTRIBUTING.md +0 -137
- package/DEVELOPMENT.md +0 -109
- package/LICENSE +0 -21
- package/README.md +0 -319
- package/ROADMAP.md +0 -24
- package/SECURITY.md +0 -88
- package/docs/COMMUNITY_FAQ.md +0 -48
- package/docs/COMPETITIVE_ANALYSIS.md +0 -90
- package/docs/DEMO_SCRIPT.md +0 -86
- package/docs/ENTERPRISE.md +0 -169
- package/docs/FAQ.md +0 -228
- package/docs/QUICK_START.md +0 -155
- package/docs/README.md +0 -67
- package/docs/RECURSIVE_SNAP_DEMO.gif +0 -0
- package/docs/social-preview-hq.png +0 -0
- package/docs/social-preview.png +0 -0
- package/examples/basic_usage.py +0 -84
- package/package.json.real +0 -24
- package/pyproject.toml +0 -50
- package/registry-server.json +0 -20
- package/scripts/demo_governance.py +0 -109
- package/scripts/sse_bridge.py +0 -87
- package/scripts/verify_windows_paths.py +0 -48
- package/server.json +0 -20
- package/src/mcp_server_nucleus/__init__.py +0 -8583
- package/src/mcp_server_nucleus/__main__.py +0 -9
- package/src/mcp_server_nucleus/cli.py +0 -1225
- package/src/mcp_server_nucleus/commitment_core.py +0 -146
- package/src/mcp_server_nucleus/commitment_ledger.py +0 -841
- package/src/mcp_server_nucleus/core/__init__.py +0 -6
- package/src/mcp_server_nucleus/core/orchestrator.py +0 -9
- package/src/mcp_server_nucleus/core/tool_registration_impl.py +0 -99
- package/src/mcp_server_nucleus/daemon/safety/lock.py +0 -121
- package/src/mcp_server_nucleus/deployment/render_integration.py +0 -4
- package/src/mcp_server_nucleus/hypervisor/__init__.py +0 -0
- package/src/mcp_server_nucleus/hypervisor/injector.py +0 -83
- package/src/mcp_server_nucleus/hypervisor/locker.py +0 -130
- package/src/mcp_server_nucleus/hypervisor/watchdog.py +0 -71
- package/src/mcp_server_nucleus/runtime/__init__.py +0 -58
- package/src/mcp_server_nucleus/runtime/agent.py +0 -517
- package/src/mcp_server_nucleus/runtime/agent_pool.py +0 -797
- package/src/mcp_server_nucleus/runtime/agents/base.py +0 -34
- package/src/mcp_server_nucleus/runtime/agents/oracle/manifest.json +0 -28
- package/src/mcp_server_nucleus/runtime/auth.py +0 -98
- package/src/mcp_server_nucleus/runtime/autopilot.py +0 -1057
- package/src/mcp_server_nucleus/runtime/broker.py +0 -126
- package/src/mcp_server_nucleus/runtime/budget.py +0 -153
- package/src/mcp_server_nucleus/runtime/capabilities/base.py +0 -20
- package/src/mcp_server_nucleus/runtime/capabilities/brain_ops.py +0 -253
- package/src/mcp_server_nucleus/runtime/capabilities/code_ops.py +0 -192
- package/src/mcp_server_nucleus/runtime/capabilities/depth_tracker.py +0 -81
- package/src/mcp_server_nucleus/runtime/capabilities/feature_map.py +0 -274
- package/src/mcp_server_nucleus/runtime/capabilities/marketing_engine.py +0 -205
- package/src/mcp_server_nucleus/runtime/capabilities/memory_ops.py +0 -79
- package/src/mcp_server_nucleus/runtime/capabilities/proof_system.py +0 -127
- package/src/mcp_server_nucleus/runtime/capabilities/render_ops.py +0 -80
- package/src/mcp_server_nucleus/runtime/capabilities/render_poller_cap.py +0 -266
- package/src/mcp_server_nucleus/runtime/capabilities/self_healing.py +0 -110
- package/src/mcp_server_nucleus/runtime/capabilities/strategy.py +0 -138
- package/src/mcp_server_nucleus/runtime/capabilities/synthesizer.py +0 -134
- package/src/mcp_server_nucleus/runtime/capabilities/web_ops.py +0 -94
- package/src/mcp_server_nucleus/runtime/common.py +0 -134
- package/src/mcp_server_nucleus/runtime/context_manager.py +0 -342
- package/src/mcp_server_nucleus/runtime/context_rules.json +0 -86
- package/src/mcp_server_nucleus/runtime/crdt_task_store.py +0 -349
- package/src/mcp_server_nucleus/runtime/critic.py +0 -150
- package/src/mcp_server_nucleus/runtime/daemon.py +0 -142
- package/src/mcp_server_nucleus/runtime/dashboard.py +0 -1087
- package/src/mcp_server_nucleus/runtime/depth_ops.py +0 -339
- package/src/mcp_server_nucleus/runtime/event_ops.py +0 -103
- package/src/mcp_server_nucleus/runtime/event_stream.py +0 -213
- package/src/mcp_server_nucleus/runtime/export.py +0 -64
- package/src/mcp_server_nucleus/runtime/factory.py +0 -594
- package/src/mcp_server_nucleus/runtime/federation.py +0 -1040
- package/src/mcp_server_nucleus/runtime/fetcher.py +0 -92
- package/src/mcp_server_nucleus/runtime/file_monitor.py +0 -208
- package/src/mcp_server_nucleus/runtime/firestore_bridge.py +0 -91
- package/src/mcp_server_nucleus/runtime/gcloud_ops.py +0 -186
- package/src/mcp_server_nucleus/runtime/hooks.py +0 -246
- package/src/mcp_server_nucleus/runtime/identity/gatekeeper.py +0 -106
- package/src/mcp_server_nucleus/runtime/identity/keygen.py +0 -147
- package/src/mcp_server_nucleus/runtime/identity/manifest.py +0 -62
- package/src/mcp_server_nucleus/runtime/identity/trust.py +0 -27
- package/src/mcp_server_nucleus/runtime/inspector.py +0 -74
- package/src/mcp_server_nucleus/runtime/installer.py +0 -81
- package/src/mcp_server_nucleus/runtime/ipc_auth.py +0 -377
- package/src/mcp_server_nucleus/runtime/lifecycle.py +0 -129
- package/src/mcp_server_nucleus/runtime/llm_client.py +0 -408
- package/src/mcp_server_nucleus/runtime/llm_tiers.json +0 -88
- package/src/mcp_server_nucleus/runtime/locking.py +0 -228
- package/src/mcp_server_nucleus/runtime/loops/fixer.py +0 -110
- package/src/mcp_server_nucleus/runtime/memory.py +0 -158
- package/src/mcp_server_nucleus/runtime/mounter.py +0 -210
- package/src/mcp_server_nucleus/runtime/mounter_ops.py +0 -250
- package/src/mcp_server_nucleus/runtime/nuke_protocol.py +0 -147
- package/src/mcp_server_nucleus/runtime/orchestrator.py +0 -370
- package/src/mcp_server_nucleus/runtime/orchestrator_unified.py +0 -263
- package/src/mcp_server_nucleus/runtime/orchestrator_v3.py +0 -617
- package/src/mcp_server_nucleus/runtime/plugin_loader.py +0 -84
- package/src/mcp_server_nucleus/runtime/policy.py +0 -117
- package/src/mcp_server_nucleus/runtime/profiling.py +0 -219
- package/src/mcp_server_nucleus/runtime/prometheus.py +0 -286
- package/src/mcp_server_nucleus/runtime/proposals.py +0 -101
- package/src/mcp_server_nucleus/runtime/publisher.py +0 -109
- package/src/mcp_server_nucleus/runtime/pulse.py +0 -516
- package/src/mcp_server_nucleus/runtime/registry.py +0 -82
- package/src/mcp_server_nucleus/runtime/render_ops.py +0 -83
- package/src/mcp_server_nucleus/runtime/schema_gen.py +0 -140
- package/src/mcp_server_nucleus/runtime/session_ops.py +0 -224
- package/src/mcp_server_nucleus/runtime/stdio_server.py +0 -633
- package/src/mcp_server_nucleus/runtime/storage.py +0 -83
- package/src/mcp_server_nucleus/runtime/strategy.py +0 -91
- package/src/mcp_server_nucleus/runtime/swarm.py +0 -170
- package/src/mcp_server_nucleus/runtime/sync_ops.py +0 -878
- package/src/mcp_server_nucleus/runtime/task_ingestion.py +0 -1020
- package/src/mcp_server_nucleus/runtime/task_ops.py +0 -449
- package/src/mcp_server_nucleus/runtime/task_scheduler.py +0 -488
- package/src/mcp_server_nucleus/runtime/team.py +0 -59
- package/src/mcp_server_nucleus/runtime/triggers.py +0 -237
- package/src/mcp_server_nucleus/runtime/vector_store.py +0 -125
- package/src/mcp_server_nucleus/runtime/watcher.py +0 -112
- package/src/mcp_server_nucleus/tool_tiers.py +0 -243
- package/tests/__init__.py +0 -1
- package/tests/conftest.py +0 -42
- package/tests/test_core.py +0 -235
- package/tests/test_search.py +0 -69
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import json
|
|
3
|
-
from typing import Dict, Any
|
|
4
|
-
import logging
|
|
5
|
-
|
|
6
|
-
logger = logging.getLogger("nucleus.schema")
|
|
7
|
-
|
|
8
|
-
def _to_json_serializable(obj):
|
|
9
|
-
"""Helper to convert Pydantic models/objects to serializable dicts."""
|
|
10
|
-
if hasattr(obj, "model_dump"):
|
|
11
|
-
return obj.model_dump()
|
|
12
|
-
if hasattr(obj, "dict"):
|
|
13
|
-
return obj.dict()
|
|
14
|
-
if isinstance(obj, list):
|
|
15
|
-
return [_to_json_serializable(item) for item in obj]
|
|
16
|
-
if isinstance(obj, dict):
|
|
17
|
-
return {k: _to_json_serializable(v) for k, v in obj.items()}
|
|
18
|
-
# Handle specific MCP objects if needed
|
|
19
|
-
return str(obj)
|
|
20
|
-
|
|
21
|
-
async def generate_tool_schema(mcp) -> Dict[str, Any]:
|
|
22
|
-
"""
|
|
23
|
-
Introspects the MCP server and generates a combined JSON Schema for tools, prompts, and resources.
|
|
24
|
-
"""
|
|
25
|
-
try:
|
|
26
|
-
schema = {
|
|
27
|
-
"openapi": "3.0.0",
|
|
28
|
-
"info": {
|
|
29
|
-
"title": f"{mcp.name} API",
|
|
30
|
-
"version": getattr(mcp, "version", "0.5.0"),
|
|
31
|
-
"description": "Auto-generated schema for Nucleus MCP Tools, Prompts, and Resources"
|
|
32
|
-
},
|
|
33
|
-
"paths": {},
|
|
34
|
-
"components": {
|
|
35
|
-
"schemas": {}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
# 1. Tools
|
|
40
|
-
tool_names = await mcp.get_tools()
|
|
41
|
-
for name in tool_names:
|
|
42
|
-
tool = await mcp.get_tool(name)
|
|
43
|
-
path = f"/tools/{tool.name}"
|
|
44
|
-
schema["paths"][path] = {
|
|
45
|
-
"post": {
|
|
46
|
-
"summary": f"Tool: {tool.name}",
|
|
47
|
-
"description": tool.description,
|
|
48
|
-
"operationId": f"tool_{tool.name}",
|
|
49
|
-
"requestBody": {
|
|
50
|
-
"content": {
|
|
51
|
-
"application/json": {
|
|
52
|
-
"schema": _to_json_serializable(tool.parameters)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
"responses": {
|
|
57
|
-
"200": {
|
|
58
|
-
"description": "Successful tool execution",
|
|
59
|
-
"content": {
|
|
60
|
-
"application/json": {
|
|
61
|
-
"schema": _to_json_serializable(tool.output_schema) if tool.output_schema else {"type": "object"}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
# 2. Prompts
|
|
70
|
-
try:
|
|
71
|
-
prompt_names = await mcp.get_prompts()
|
|
72
|
-
for name in prompt_names:
|
|
73
|
-
prompt = await mcp.get_prompt(name)
|
|
74
|
-
path = f"/prompts/{prompt.name}"
|
|
75
|
-
schema["paths"][path] = {
|
|
76
|
-
"post": {
|
|
77
|
-
"summary": f"Prompt: {prompt.name}",
|
|
78
|
-
"description": prompt.description,
|
|
79
|
-
"operationId": f"prompt_{prompt.name}",
|
|
80
|
-
"requestBody": {
|
|
81
|
-
"content": {
|
|
82
|
-
"application/json": {
|
|
83
|
-
"schema": {
|
|
84
|
-
"type": "object",
|
|
85
|
-
"properties": {
|
|
86
|
-
arg.name: {
|
|
87
|
-
"description": arg.description,
|
|
88
|
-
"type": "string" # MCP prompt args are usually strings
|
|
89
|
-
} for arg in getattr(prompt, "arguments", [])
|
|
90
|
-
},
|
|
91
|
-
"required": [arg.name for arg in getattr(prompt, "arguments", []) if getattr(arg, "required", False)]
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
"responses": {
|
|
97
|
-
"200": {
|
|
98
|
-
"description": "Successful prompt render"
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
except Exception as e:
|
|
104
|
-
logger.warning(f"Failed to introspect prompts: {e}")
|
|
105
|
-
|
|
106
|
-
# 3. Resources
|
|
107
|
-
try:
|
|
108
|
-
resources = await mcp.get_resources()
|
|
109
|
-
for uri in resources:
|
|
110
|
-
resource = await mcp.get_resource(uri)
|
|
111
|
-
path = f"/resources/{resource.name}"
|
|
112
|
-
schema["paths"][path] = {
|
|
113
|
-
"get": {
|
|
114
|
-
"summary": f"Resource: {resource.name}",
|
|
115
|
-
"description": f"{resource.description} (URI: {resource.uri})",
|
|
116
|
-
"operationId": f"resource_{resource.name}",
|
|
117
|
-
"responses": {
|
|
118
|
-
"200": {
|
|
119
|
-
"description": "Successful resource read",
|
|
120
|
-
"content": {
|
|
121
|
-
resource.mime_type or "text/plain": {}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
except Exception as e:
|
|
128
|
-
logger.warning(f"Failed to introspect resources: {e}")
|
|
129
|
-
|
|
130
|
-
return schema
|
|
131
|
-
except Exception as e:
|
|
132
|
-
logger.error(f"Error generating schema: {e}")
|
|
133
|
-
return {"error": str(e)}
|
|
134
|
-
|
|
135
|
-
def export_schema_to_file(schema: Dict[str, Any], output_path: str):
|
|
136
|
-
"""
|
|
137
|
-
Writes the generated schema to a JSON file.
|
|
138
|
-
"""
|
|
139
|
-
with open(output_path, "w") as f:
|
|
140
|
-
json.dump(schema, f, indent=2)
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Nucleus Runtime - Session Operations
|
|
3
|
-
====================================
|
|
4
|
-
Core logic for session management (Save, Resume, Context switching).
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import json
|
|
8
|
-
import time
|
|
9
|
-
from typing import Dict, Any, List, Optional
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
|
|
12
|
-
from .common import get_brain_path
|
|
13
|
-
from .event_ops import _emit_event
|
|
14
|
-
|
|
15
|
-
def _get_sessions_path() -> Path:
|
|
16
|
-
"""Get path to sessions directory."""
|
|
17
|
-
brain = get_brain_path()
|
|
18
|
-
return brain / "sessions"
|
|
19
|
-
|
|
20
|
-
def _get_active_session_path() -> Path:
|
|
21
|
-
"""Get path to active session file."""
|
|
22
|
-
brain = get_brain_path()
|
|
23
|
-
return brain / "sessions" / "active.json"
|
|
24
|
-
|
|
25
|
-
def _get_depth_state_safe() -> Dict:
|
|
26
|
-
"""Get current depth tracking state (helper for session save)."""
|
|
27
|
-
try:
|
|
28
|
-
brain = get_brain_path()
|
|
29
|
-
depth_path = brain / "session" / "depth.json"
|
|
30
|
-
if depth_path.exists():
|
|
31
|
-
with open(depth_path, "r") as f:
|
|
32
|
-
return json.load(f)
|
|
33
|
-
except Exception:
|
|
34
|
-
pass
|
|
35
|
-
return {"current_depth": 0, "levels": []}
|
|
36
|
-
|
|
37
|
-
def _save_session(context: str, active_task: Optional[str] = None,
|
|
38
|
-
pending_decisions: Optional[List[str]] = None,
|
|
39
|
-
breadcrumbs: Optional[List[str]] = None,
|
|
40
|
-
next_steps: Optional[List[str]] = None) -> Dict[str, Any]:
|
|
41
|
-
"""Save current session for later resumption."""
|
|
42
|
-
try:
|
|
43
|
-
sessions_dir = _get_sessions_path()
|
|
44
|
-
sessions_dir.mkdir(parents=True, exist_ok=True)
|
|
45
|
-
|
|
46
|
-
timestamp = time.strftime("%Y%m%d_%H%M%S")
|
|
47
|
-
context_slug = context.lower().replace(" ", "_")[:30]
|
|
48
|
-
session_id = f"{context_slug}_{timestamp}"
|
|
49
|
-
|
|
50
|
-
depth_state = _get_depth_state_safe()
|
|
51
|
-
|
|
52
|
-
session = {
|
|
53
|
-
"schema_version": "1.0",
|
|
54
|
-
"nucleus_version": "0.5.0",
|
|
55
|
-
"id": session_id,
|
|
56
|
-
"context": context,
|
|
57
|
-
"active_task": active_task or "Not specified",
|
|
58
|
-
"pending_decisions": pending_decisions or [],
|
|
59
|
-
"breadcrumbs": breadcrumbs or [],
|
|
60
|
-
"next_steps": next_steps or [],
|
|
61
|
-
"depth_snapshot": {
|
|
62
|
-
"current_depth": depth_state.get("current_depth", 0),
|
|
63
|
-
"levels": depth_state.get("levels", [])
|
|
64
|
-
},
|
|
65
|
-
"created_at": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
|
|
66
|
-
"is_active": True
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
session_path = sessions_dir / f"{session_id}.json"
|
|
70
|
-
with open(session_path, "w") as f:
|
|
71
|
-
json.dump(session, f, indent=2)
|
|
72
|
-
|
|
73
|
-
with open(_get_active_session_path(), "w") as f:
|
|
74
|
-
json.dump({"active_session_id": session_id}, f)
|
|
75
|
-
|
|
76
|
-
_prune_old_sessions(max_sessions=10)
|
|
77
|
-
|
|
78
|
-
_emit_event(
|
|
79
|
-
"session_saved",
|
|
80
|
-
"brain_save_session",
|
|
81
|
-
{
|
|
82
|
-
"session_id": session_id,
|
|
83
|
-
"context": context,
|
|
84
|
-
"active_task": active_task or "Not specified"
|
|
85
|
-
},
|
|
86
|
-
description=f"Session saved: {context}"
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
"success": True,
|
|
91
|
-
"session_id": session_id,
|
|
92
|
-
"context": context,
|
|
93
|
-
"message": "Session saved. Resume later with: nucleus sessions resume"
|
|
94
|
-
}
|
|
95
|
-
except Exception as e:
|
|
96
|
-
return {"error": str(e)}
|
|
97
|
-
|
|
98
|
-
def _prune_old_sessions(max_sessions: int = 10) -> None:
|
|
99
|
-
"""Keep only the most recent N sessions."""
|
|
100
|
-
try:
|
|
101
|
-
sessions_dir = _get_sessions_path()
|
|
102
|
-
if not sessions_dir.exists():
|
|
103
|
-
return
|
|
104
|
-
|
|
105
|
-
session_files = sorted(
|
|
106
|
-
sessions_dir.glob("*.json"),
|
|
107
|
-
key=lambda f: f.stat().st_mtime,
|
|
108
|
-
reverse=True
|
|
109
|
-
)
|
|
110
|
-
session_files = [f for f in session_files if f.name != "active.json"]
|
|
111
|
-
|
|
112
|
-
for old_session in session_files[max_sessions:]:
|
|
113
|
-
try:
|
|
114
|
-
old_session.unlink()
|
|
115
|
-
except Exception:
|
|
116
|
-
pass
|
|
117
|
-
except Exception:
|
|
118
|
-
pass
|
|
119
|
-
|
|
120
|
-
def _get_session(session_id: str) -> Dict[str, Any]:
|
|
121
|
-
"""Get a specific session by ID."""
|
|
122
|
-
try:
|
|
123
|
-
sessions_dir = _get_sessions_path()
|
|
124
|
-
session_path = sessions_dir / f"{session_id}.json"
|
|
125
|
-
|
|
126
|
-
if not session_path.exists():
|
|
127
|
-
return {"error": f"Session '{session_id}' not found"}
|
|
128
|
-
|
|
129
|
-
with open(session_path) as f:
|
|
130
|
-
session = json.load(f)
|
|
131
|
-
|
|
132
|
-
return {"session": session}
|
|
133
|
-
except Exception as e:
|
|
134
|
-
return {"error": str(e)}
|
|
135
|
-
|
|
136
|
-
def _resume_session(session_id: Optional[str] = None) -> Dict[str, Any]:
|
|
137
|
-
"""Resume a saved session."""
|
|
138
|
-
try:
|
|
139
|
-
if not session_id:
|
|
140
|
-
active_path = _get_active_session_path()
|
|
141
|
-
if active_path.exists():
|
|
142
|
-
with open(active_path) as f:
|
|
143
|
-
active_data = json.load(f)
|
|
144
|
-
session_id = active_data.get("active_session_id")
|
|
145
|
-
|
|
146
|
-
if not session_id:
|
|
147
|
-
return {"error": "No active session found"}
|
|
148
|
-
|
|
149
|
-
session_result = _get_session(session_id)
|
|
150
|
-
if "error" in session_result:
|
|
151
|
-
return session_result
|
|
152
|
-
|
|
153
|
-
session = session_result.get("session", {})
|
|
154
|
-
|
|
155
|
-
# Version Checks
|
|
156
|
-
warnings = []
|
|
157
|
-
if session.get("schema_version") != "1.0":
|
|
158
|
-
warnings.append(f"Schema mismatch: Session uses v{session.get('schema_version', 'unknown')}, System uses v1.0")
|
|
159
|
-
if session.get("nucleus_version") != "0.5.0":
|
|
160
|
-
warnings.append(f"Nucleus update: Session from v{session.get('nucleus_version', 'unknown')}, System is v0.5.0")
|
|
161
|
-
|
|
162
|
-
created_str = session.get("created_at", "")
|
|
163
|
-
# Simple recent check
|
|
164
|
-
is_recent = True
|
|
165
|
-
try:
|
|
166
|
-
if created_str:
|
|
167
|
-
# Very basic check
|
|
168
|
-
pass
|
|
169
|
-
except Exception:
|
|
170
|
-
pass
|
|
171
|
-
|
|
172
|
-
return {
|
|
173
|
-
"session_id": session_id,
|
|
174
|
-
"context": session.get("context"),
|
|
175
|
-
"active_task": session.get("active_task"),
|
|
176
|
-
"pending_decisions": session.get("pending_decisions", []),
|
|
177
|
-
"breadcrumbs": session.get("breadcrumbs", []),
|
|
178
|
-
"next_steps": session.get("next_steps", []),
|
|
179
|
-
"depth_snapshot": session.get("depth_snapshot", {}),
|
|
180
|
-
"created_at": created_str,
|
|
181
|
-
"warnings": warnings,
|
|
182
|
-
"is_recent": is_recent
|
|
183
|
-
}
|
|
184
|
-
except Exception as e:
|
|
185
|
-
return {"error": str(e)}
|
|
186
|
-
|
|
187
|
-
def _list_sessions() -> Dict[str, Any]:
|
|
188
|
-
"""List all saved sessions."""
|
|
189
|
-
try:
|
|
190
|
-
sessions_dir = _get_sessions_path()
|
|
191
|
-
if not sessions_dir.exists():
|
|
192
|
-
return {"sessions": [], "total": 0}
|
|
193
|
-
|
|
194
|
-
sessions = []
|
|
195
|
-
for session_file in sorted(sessions_dir.glob("*.json"), reverse=True):
|
|
196
|
-
if session_file.name == "active.json":
|
|
197
|
-
continue
|
|
198
|
-
try:
|
|
199
|
-
with open(session_file) as f:
|
|
200
|
-
session = json.load(f)
|
|
201
|
-
sessions.append({
|
|
202
|
-
"id": session.get("id"),
|
|
203
|
-
"context": session.get("context"),
|
|
204
|
-
"created_at": session.get("created_at")
|
|
205
|
-
})
|
|
206
|
-
except Exception:
|
|
207
|
-
continue
|
|
208
|
-
|
|
209
|
-
return {"sessions": sessions, "total": len(sessions)}
|
|
210
|
-
except Exception as e:
|
|
211
|
-
return {"error": str(e)}
|
|
212
|
-
|
|
213
|
-
def _check_for_recent_session() -> Dict[str, Any]:
|
|
214
|
-
"""Check for recent session."""
|
|
215
|
-
try:
|
|
216
|
-
active_path = _get_active_session_path()
|
|
217
|
-
if active_path.exists():
|
|
218
|
-
with open(active_path) as f:
|
|
219
|
-
sid = json.load(f).get("active_session_id")
|
|
220
|
-
if sid:
|
|
221
|
-
return {"exists": True, "session_id": sid, "message": "Resumable session found."}
|
|
222
|
-
return {"exists": False}
|
|
223
|
-
except Exception:
|
|
224
|
-
return {"exists": False}
|