loki-mode 6.36.3 → 6.36.5
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/LICENSE +123 -21
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/dashboard/__init__.py +1 -1
- package/dashboard/auth.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/mcp/__init__.py +1 -1
- package/mcp/server.py +21 -0
- package/memory/consolidation.py +1 -1
- package/memory/engine.py +10 -0
- package/memory/retrieval.py +7 -0
- package/package.json +1 -1
- package/web-app/server.py +28 -4
package/LICENSE
CHANGED
|
@@ -1,21 +1,123 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Parameters
|
|
4
|
+
|
|
5
|
+
Licensor: Autonomi, Inc. (autonomi.dev)
|
|
6
|
+
Licensed Work: Loki Mode and all associated components, including but not
|
|
7
|
+
limited to its multi-agent orchestration engine, agent
|
|
8
|
+
coordination protocols, review and verification systems,
|
|
9
|
+
documentation, research, architectural patterns, and any
|
|
10
|
+
rebranded or successor versions of this software.
|
|
11
|
+
The Licensed Work is (c) 2024-2026 Autonomi, Inc.
|
|
12
|
+
All rights reserved.
|
|
13
|
+
Additional Use Grant: You may make production use of the Licensed Work, provided
|
|
14
|
+
that such use does not include offering the Licensed Work,
|
|
15
|
+
or any derivative work or adaptation of it, to third parties
|
|
16
|
+
as a commercial product, hosted service, managed service, or
|
|
17
|
+
embedded component of a commercial offering that competes
|
|
18
|
+
with any product or service provided by the Licensor.
|
|
19
|
+
|
|
20
|
+
For purposes of this license, "compete" means offering a
|
|
21
|
+
product or service that provides substantially the same or
|
|
22
|
+
similar functionality as the Licensed Work to third parties,
|
|
23
|
+
whether for a fee or free of charge, including but not
|
|
24
|
+
limited to:
|
|
25
|
+
(a) multi-agent AI development orchestration platforms or
|
|
26
|
+
frameworks;
|
|
27
|
+
(b) autonomous software development products or services;
|
|
28
|
+
(c) AI-powered code generation, review, or deployment
|
|
29
|
+
services that incorporate or replicate the Licensed
|
|
30
|
+
Work's orchestration, review, verification, or agent
|
|
31
|
+
coordination systems; or
|
|
32
|
+
(d) products or services that substantially replicate the
|
|
33
|
+
Licensed Work's core architectural patterns, including
|
|
34
|
+
the RARV (Reason-Act-Reflect-Verify) cycle, Completion
|
|
35
|
+
Council peer review system, or multi-agent swarm
|
|
36
|
+
coordination model.
|
|
37
|
+
|
|
38
|
+
The following uses are permitted without a commercial license:
|
|
39
|
+
(i) individual and non-commercial use;
|
|
40
|
+
(ii) internal business use where the Licensed Work is used
|
|
41
|
+
as a tool and is not itself the product or service
|
|
42
|
+
being offered to third parties;
|
|
43
|
+
(iii) academic, educational, and research use;
|
|
44
|
+
(iv) evaluation and testing in non-production environments;
|
|
45
|
+
(v) contributions back to the Licensed Work under a signed
|
|
46
|
+
Contributor License Agreement.
|
|
47
|
+
|
|
48
|
+
Change Date: March 19, 2030
|
|
49
|
+
Change License: Apache License, Version 2.0
|
|
50
|
+
|
|
51
|
+
For information about alternative licensing arrangements for the Licensed Work,
|
|
52
|
+
please contact: founder@autonomi.dev
|
|
53
|
+
|
|
54
|
+
Intellectual Property Notice
|
|
55
|
+
|
|
56
|
+
The Licensed Work embodies proprietary methodologies, architectural patterns,
|
|
57
|
+
and research developed by the Licensor. These include, without limitation, the
|
|
58
|
+
RARV execution cycle, the Completion Council consensus-based review system,
|
|
59
|
+
context persistence mechanisms for long-running autonomous sessions, multi-
|
|
60
|
+
provider orchestration protocols, and swarm-based agent coordination models.
|
|
61
|
+
Use of these methodologies, whether through the Licensed Work's code or through
|
|
62
|
+
independent reimplementation based on the Licensed Work's documentation or
|
|
63
|
+
published research, is subject to the terms of this License.
|
|
64
|
+
|
|
65
|
+
Contributions
|
|
66
|
+
|
|
67
|
+
External contributions to the Licensed Work are accepted only under a signed
|
|
68
|
+
Contributor License Agreement (CLA) that assigns sufficient rights to the
|
|
69
|
+
Licensor to sublicense, relicense, and commercially distribute the contribution
|
|
70
|
+
as part of the Licensed Work. Contributing code to the Licensed Work without a
|
|
71
|
+
signed CLA does not grant the Licensor any rights to the contribution, and such
|
|
72
|
+
contributions may be removed.
|
|
73
|
+
|
|
74
|
+
Notice
|
|
75
|
+
|
|
76
|
+
The Business Source License (this document, or the "License") is not an Open
|
|
77
|
+
Source license. However, the Licensed Work will eventually be made available
|
|
78
|
+
under an Open Source License, as stated in this License.
|
|
79
|
+
|
|
80
|
+
License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
|
|
81
|
+
"Business Source License" is a trademark of MariaDB Corporation Ab.
|
|
82
|
+
|
|
83
|
+
Terms
|
|
84
|
+
|
|
85
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
86
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
87
|
+
Licensor may make an Additional Use Grant, above, permitting limited production
|
|
88
|
+
use.
|
|
89
|
+
|
|
90
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
91
|
+
available distribution of a specific version of the Licensed Work under this
|
|
92
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
93
|
+
the terms of the Change License, and the rights granted in the paragraph above
|
|
94
|
+
terminate.
|
|
95
|
+
|
|
96
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
97
|
+
currently in effect as described in this License, you must purchase a
|
|
98
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
99
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
100
|
+
|
|
101
|
+
All copies of the original and modified Licensed Work, and derivative works of
|
|
102
|
+
the Licensed Work, are subject to this License. This License applies separately
|
|
103
|
+
for each version of the Licensed Work and the Change Date may vary for each
|
|
104
|
+
version of the Licensed Work released by Licensor.
|
|
105
|
+
|
|
106
|
+
You must conspicuously display this License on each original or modified copy
|
|
107
|
+
of the Licensed Work. If you receive the Licensed Work in original or modified
|
|
108
|
+
form from a third party, the terms and conditions set forth in this License
|
|
109
|
+
apply to your use of that work.
|
|
110
|
+
|
|
111
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
112
|
+
terminate your rights under this License for the current and all other
|
|
113
|
+
versions of the Licensed Work.
|
|
114
|
+
|
|
115
|
+
This License does not grant you any right in any trademark or logo of Licensor
|
|
116
|
+
or its affiliates (provided that you may use a trademark or logo of Licensor
|
|
117
|
+
as expressly required by this License).
|
|
118
|
+
|
|
119
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
120
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
121
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
122
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
123
|
+
TITLE.
|
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v6.36.
|
|
6
|
+
# Loki Mode v6.36.5
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -267,4 +267,4 @@ The following features are documented in skill modules but not yet fully automat
|
|
|
267
267
|
| Quality gates 3-reviewer system | Implemented (v5.35.0) | 5 specialist reviewers in `skills/quality-gates.md`; execution in run.sh |
|
|
268
268
|
| Benchmarks (HumanEval, SWE-bench) | Infrastructure only | Runner scripts and datasets exist in `benchmarks/`; no published results |
|
|
269
269
|
|
|
270
|
-
**v6.36.
|
|
270
|
+
**v6.36.5 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
6.36.
|
|
1
|
+
6.36.5
|
package/dashboard/__init__.py
CHANGED
package/dashboard/auth.py
CHANGED
|
@@ -595,7 +595,7 @@ def require_scope(scope: str):
|
|
|
595
595
|
"""
|
|
596
596
|
async def check_scope(token_info: Optional[dict] = Security(get_current_token)):
|
|
597
597
|
if not ENTERPRISE_AUTH_ENABLED and not OIDC_ENABLED:
|
|
598
|
-
return #
|
|
598
|
+
return True # Auth disabled - allow access with explicit truthy value
|
|
599
599
|
|
|
600
600
|
if not token_info:
|
|
601
601
|
raise HTTPException(status_code=401, detail="Authentication required")
|
package/docs/INSTALLATION.md
CHANGED
package/mcp/__init__.py
CHANGED
package/mcp/server.py
CHANGED
|
@@ -88,6 +88,23 @@ def _get_mcp_state_manager():
|
|
|
88
88
|
return _state_manager
|
|
89
89
|
|
|
90
90
|
|
|
91
|
+
def cleanup_mcp_singletons():
|
|
92
|
+
"""Clean up module-level singletons to prevent resource leaks on restart.
|
|
93
|
+
|
|
94
|
+
Call this before restarting the MCP server to release file handles
|
|
95
|
+
held by the StateManager and LearningCollector instances.
|
|
96
|
+
"""
|
|
97
|
+
global _state_manager, _learning_collector
|
|
98
|
+
if _state_manager is not None:
|
|
99
|
+
if hasattr(_state_manager, 'close'):
|
|
100
|
+
_state_manager.close()
|
|
101
|
+
_state_manager = None
|
|
102
|
+
if _learning_collector is not None:
|
|
103
|
+
if hasattr(_learning_collector, 'close'):
|
|
104
|
+
_learning_collector.close()
|
|
105
|
+
_learning_collector = None
|
|
106
|
+
|
|
107
|
+
|
|
91
108
|
# ============================================================
|
|
92
109
|
# PATH SECURITY - Prevent path traversal attacks
|
|
93
110
|
# ============================================================
|
|
@@ -1679,6 +1696,7 @@ Use loki_state_get and loki_task_queue_list to gather data."""
|
|
|
1679
1696
|
|
|
1680
1697
|
def main():
|
|
1681
1698
|
import argparse
|
|
1699
|
+
import atexit
|
|
1682
1700
|
parser = argparse.ArgumentParser(description='Loki Mode MCP Server')
|
|
1683
1701
|
parser.add_argument('--transport', choices=['stdio', 'http'], default='stdio',
|
|
1684
1702
|
help='Transport mechanism (default: stdio)')
|
|
@@ -1686,6 +1704,9 @@ def main():
|
|
|
1686
1704
|
help='Port for HTTP transport (default: 8421)')
|
|
1687
1705
|
args = parser.parse_args()
|
|
1688
1706
|
|
|
1707
|
+
# Register cleanup to prevent file handle leaks on shutdown/restart
|
|
1708
|
+
atexit.register(cleanup_mcp_singletons)
|
|
1709
|
+
|
|
1689
1710
|
logger.info(f"Starting Loki Mode MCP server (transport: {args.transport})")
|
|
1690
1711
|
|
|
1691
1712
|
if args.transport == 'http':
|
package/memory/consolidation.py
CHANGED
|
@@ -81,7 +81,7 @@ class Cluster:
|
|
|
81
81
|
def to_dict(self) -> Dict[str, Any]:
|
|
82
82
|
"""Convert to dictionary for JSON serialization."""
|
|
83
83
|
return {
|
|
84
|
-
"episode_ids": [ep
|
|
84
|
+
"episode_ids": [getattr(ep, 'id', '') if not isinstance(ep, dict) else ep.get('id', '') for ep in self.episodes],
|
|
85
85
|
"label": self.label,
|
|
86
86
|
"size": len(self.episodes),
|
|
87
87
|
}
|
package/memory/engine.py
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
|
+
import logging
|
|
8
9
|
import os
|
|
9
10
|
from datetime import datetime, timedelta, timezone
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
from typing import Any, Callable, Dict, List, Optional, Union
|
|
12
13
|
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
13
16
|
# Import schemas - these are expected to be created in parallel
|
|
14
17
|
from .schemas import (
|
|
15
18
|
ActionEntry,
|
|
@@ -598,6 +601,13 @@ class MemoryEngine:
|
|
|
598
601
|
"""
|
|
599
602
|
if self._embedding_func is None:
|
|
600
603
|
# Fall back to keyword matching if no embeddings
|
|
604
|
+
if not getattr(self, '_embedding_warning_logged', False):
|
|
605
|
+
logger.warning(
|
|
606
|
+
"Vector search unavailable: numpy or sentence-transformers "
|
|
607
|
+
"not installed. Falling back to keyword matching. "
|
|
608
|
+
"Install with: pip install numpy sentence-transformers"
|
|
609
|
+
)
|
|
610
|
+
self._embedding_warning_logged = True
|
|
601
611
|
return self._keyword_search(query, collection, top_k)
|
|
602
612
|
|
|
603
613
|
# Use embeddings for similarity search
|
package/memory/retrieval.py
CHANGED
|
@@ -18,11 +18,14 @@ See references/memory-system.md for full documentation.
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import json
|
|
21
|
+
import logging
|
|
21
22
|
import re
|
|
22
23
|
from datetime import datetime, timezone
|
|
23
24
|
from pathlib import Path
|
|
24
25
|
from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union, TYPE_CHECKING
|
|
25
26
|
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
26
29
|
# numpy is optional - only required for vector operations
|
|
27
30
|
try:
|
|
28
31
|
import numpy as np
|
|
@@ -30,6 +33,10 @@ try:
|
|
|
30
33
|
except ImportError:
|
|
31
34
|
np = None # type: ignore
|
|
32
35
|
NUMPY_AVAILABLE = False
|
|
36
|
+
logger.warning(
|
|
37
|
+
"numpy not installed. Vector operations in memory retrieval will be "
|
|
38
|
+
"degraded. Install with: pip install numpy"
|
|
39
|
+
)
|
|
33
40
|
|
|
34
41
|
# Import from sibling modules
|
|
35
42
|
from .schemas import EpisodeTrace, SemanticPattern, ProceduralSkill
|
package/package.json
CHANGED
package/web-app/server.py
CHANGED
|
@@ -44,9 +44,20 @@ DIST_DIR = SCRIPT_DIR / "dist"
|
|
|
44
44
|
|
|
45
45
|
app = FastAPI(title="Purple Lab", docs_url=None, redoc_url=None)
|
|
46
46
|
|
|
47
|
+
_default_cors_origins = [
|
|
48
|
+
f"http://127.0.0.1:{PORT}",
|
|
49
|
+
f"http://localhost:{PORT}",
|
|
50
|
+
]
|
|
51
|
+
_cors_env = os.environ.get("PURPLE_LAB_CORS_ORIGINS", "")
|
|
52
|
+
_cors_origins = (
|
|
53
|
+
[o.strip() for o in _cors_env.split(",") if o.strip()]
|
|
54
|
+
if _cors_env
|
|
55
|
+
else _default_cors_origins
|
|
56
|
+
)
|
|
57
|
+
|
|
47
58
|
app.add_middleware(
|
|
48
59
|
CORSMiddleware,
|
|
49
|
-
allow_origins=
|
|
60
|
+
allow_origins=_cors_origins,
|
|
50
61
|
allow_methods=["*"],
|
|
51
62
|
allow_headers=["*"],
|
|
52
63
|
)
|
|
@@ -149,12 +160,25 @@ def _loki_dir() -> Path:
|
|
|
149
160
|
|
|
150
161
|
|
|
151
162
|
def _safe_resolve(base: Path, requested: str) -> Optional[Path]:
|
|
152
|
-
"""Resolve a path ensuring it stays within base (path traversal protection).
|
|
163
|
+
"""Resolve a path ensuring it stays within base (path traversal protection).
|
|
164
|
+
|
|
165
|
+
Uses os.path.commonpath to avoid the startswith prefix collision where
|
|
166
|
+
/tmp/proj would incorrectly pass a check against /tmp/projother.
|
|
167
|
+
Also rejects symlinks that escape the base directory.
|
|
168
|
+
"""
|
|
153
169
|
try:
|
|
154
170
|
resolved = (base / requested).resolve()
|
|
155
171
|
base_resolved = base.resolve()
|
|
156
|
-
|
|
157
|
-
|
|
172
|
+
# Ensure resolved is strictly inside base_resolved
|
|
173
|
+
resolved.relative_to(base_resolved)
|
|
174
|
+
# Reject if any component is a symlink pointing outside base
|
|
175
|
+
check = base_resolved
|
|
176
|
+
for part in resolved.relative_to(base_resolved).parts:
|
|
177
|
+
check = check / part
|
|
178
|
+
if check.is_symlink():
|
|
179
|
+
link_target = check.resolve()
|
|
180
|
+
link_target.relative_to(base_resolved) # raises ValueError if outside
|
|
181
|
+
return resolved
|
|
158
182
|
except (ValueError, OSError):
|
|
159
183
|
pass
|
|
160
184
|
return None
|