@crvouga/mockingbird-service-hermes 0.1.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/API_EVIDENCE.md +418 -0
- package/CHANGELOG.md +5 -0
- package/DISCOVERY.md +54 -0
- package/README.md +290 -0
- package/SUPPORT.md +16 -0
- package/dist/chunk-E3W77NV6.js +821 -0
- package/dist/chunk-E3W77NV6.js.map +7 -0
- package/dist/chunk-RLLHIXKE.js +3618 -0
- package/dist/chunk-RLLHIXKE.js.map +7 -0
- package/dist/cli.js +19 -0
- package/dist/cli.js.map +7 -0
- package/dist/index.d.ts +1285 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +7 -0
- package/dist/server.d.ts +1742 -0
- package/dist/server.js +12 -0
- package/dist/server.js.map +7 -0
- package/evidence/fingerprint-python.json +156 -0
- package/evidence/pinned-oracle.json +616 -0
- package/openapi.yaml +342 -0
- package/oracle/README.md +99 -0
- package/oracle/compare.mjs +274 -0
- package/oracle/comparison.mjs +16 -0
- package/oracle/comparison.test.mjs +41 -0
- package/oracle/fetch.py +29 -0
- package/oracle/requirements.lock +11 -0
- package/oracle/server.py +227 -0
- package/oracle/source-lock.json +52 -0
- package/oracle/sources.py +71 -0
- package/oracle/test_sources.py +50 -0
- package/package.json +117 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Exact-source loading without importing gateway startup or inference."""
|
|
2
|
+
import ast
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
import types
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
LOCK = json.loads(Path(__file__).with_name("source-lock.json").read_text())
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def verify(directory):
|
|
13
|
+
directory = Path(directory)
|
|
14
|
+
for name, expected in LOCK["sources"].items():
|
|
15
|
+
data = (directory / name).read_bytes()
|
|
16
|
+
if hashlib.sha256(data).hexdigest() != expected["sha256"]:
|
|
17
|
+
raise ValueError(f"Pinned source hash mismatch: {name}")
|
|
18
|
+
return LOCK
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def definitions(path, roots, namespace):
|
|
22
|
+
"""Compile original AST nodes and their local definition dependencies.
|
|
23
|
+
|
|
24
|
+
Imports are explicitly supplied by the harness. No function body is rewritten;
|
|
25
|
+
future annotations avoid loading unrelated annotation-only dependencies.
|
|
26
|
+
Return selected names so provenance can disclose the exact loading boundary.
|
|
27
|
+
"""
|
|
28
|
+
tree = ast.parse(Path(path).read_text(), filename=str(path))
|
|
29
|
+
definitions_by_name = {}
|
|
30
|
+
for node in tree.body:
|
|
31
|
+
candidates = node.body if isinstance(node, ast.ClassDef) and node.name == "APIServerAdapter" else [node]
|
|
32
|
+
for candidate in candidates:
|
|
33
|
+
if isinstance(candidate, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
|
|
34
|
+
definitions_by_name[candidate.name] = candidate
|
|
35
|
+
elif isinstance(candidate, (ast.Assign, ast.AnnAssign)):
|
|
36
|
+
targets = candidate.targets if isinstance(candidate, ast.Assign) else [candidate.target]
|
|
37
|
+
for target in targets:
|
|
38
|
+
if isinstance(target, ast.Name):
|
|
39
|
+
definitions_by_name[target.id] = candidate
|
|
40
|
+
selected = set()
|
|
41
|
+
pending = list(roots)
|
|
42
|
+
while pending:
|
|
43
|
+
name = pending.pop()
|
|
44
|
+
if name in selected or name in namespace:
|
|
45
|
+
continue
|
|
46
|
+
node = definitions_by_name.get(name)
|
|
47
|
+
if node is None:
|
|
48
|
+
if name in roots:
|
|
49
|
+
raise ValueError(f"Missing pinned definition: {name}")
|
|
50
|
+
continue
|
|
51
|
+
selected.add(name)
|
|
52
|
+
pending.extend(n.id for n in ast.walk(node) if isinstance(n, ast.Name) and isinstance(n.ctx, ast.Load))
|
|
53
|
+
nodes = {id(definitions_by_name[name]): definitions_by_name[name] for name in selected}
|
|
54
|
+
module = ast.Module(body=[ast.ImportFrom(module="__future__", names=[ast.alias(name="annotations")], level=0), *sorted(nodes.values(), key=lambda node: node.lineno)], type_ignores=[])
|
|
55
|
+
ast.fix_missing_locations(module)
|
|
56
|
+
exec(compile(module, str(path), "exec"), namespace)
|
|
57
|
+
return sorted(selected)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def load_module(path, name):
|
|
61
|
+
module = types.ModuleType(name)
|
|
62
|
+
module.__file__ = str(path)
|
|
63
|
+
sys.modules[name] = module
|
|
64
|
+
exec(compile(Path(path).read_text(), str(path), "exec"), module.__dict__)
|
|
65
|
+
return module
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
import sys
|
|
70
|
+
manifest = verify(sys.argv[1])
|
|
71
|
+
print(json.dumps({"commit": manifest["commit"], "verified_files": len(manifest["sources"])}))
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Dependency-free checks: never start upstream code, services or databases."""
|
|
2
|
+
import unittest
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
from sources import definitions, verify
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SourceLoadingTests(unittest.TestCase):
|
|
9
|
+
def test_transitive_definitions_preserve_behavior_without_running_startup(self):
|
|
10
|
+
fixture = '''
|
|
11
|
+
LIMIT = 3
|
|
12
|
+
raise RuntimeError("unrelated gateway startup must not execute")
|
|
13
|
+
def helper(value):
|
|
14
|
+
return value + LIMIT
|
|
15
|
+
def handler(value):
|
|
16
|
+
return helper(value) if value else "invalid"
|
|
17
|
+
'''
|
|
18
|
+
namespace = {}
|
|
19
|
+
with patch.object(Path, "read_text", return_value=fixture):
|
|
20
|
+
names = definitions("fixture.py", ["handler"], namespace)
|
|
21
|
+
self.assertEqual(names, ["LIMIT", "handler", "helper"])
|
|
22
|
+
self.assertEqual(namespace["handler"](4), 7)
|
|
23
|
+
self.assertEqual(namespace["handler"](0), "invalid")
|
|
24
|
+
|
|
25
|
+
def test_missing_required_definition_fails_closed(self):
|
|
26
|
+
with patch.object(Path, "read_text", return_value="def different(): pass"):
|
|
27
|
+
with self.assertRaisesRegex(ValueError, "Missing pinned definition: handler"):
|
|
28
|
+
definitions("fixture.py", ["handler"], {})
|
|
29
|
+
|
|
30
|
+
def test_source_tampering_fails_before_execution(self):
|
|
31
|
+
with patch.object(Path, "read_bytes", return_value=b"changed source"):
|
|
32
|
+
with self.assertRaisesRegex(ValueError, "Pinned source hash mismatch"):
|
|
33
|
+
verify("unread-fixture")
|
|
34
|
+
|
|
35
|
+
def test_selected_adapter_method_keeps_staticmethod_binding(self):
|
|
36
|
+
fixture = '''
|
|
37
|
+
class APIServerAdapter:
|
|
38
|
+
@staticmethod
|
|
39
|
+
def header(request):
|
|
40
|
+
return request["value"]
|
|
41
|
+
'''
|
|
42
|
+
namespace = {}
|
|
43
|
+
with patch.object(Path, "read_text", return_value=fixture):
|
|
44
|
+
definitions("fixture.py", ["header"], namespace)
|
|
45
|
+
adapter = type("Adapter", (), {"header": namespace["header"]})
|
|
46
|
+
self.assertEqual(adapter().header({"value": "synthetic"}), "synthetic")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == "__main__":
|
|
50
|
+
unittest.main()
|
package/package.json
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@crvouga/mockingbird-service-hermes",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Hermes peer-run API mock with portable scripted lifecycle controls.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"CHANGELOG.md",
|
|
12
|
+
"API_EVIDENCE.md",
|
|
13
|
+
"SUPPORT.md",
|
|
14
|
+
"oracle",
|
|
15
|
+
"evidence",
|
|
16
|
+
"DISCOVERY.md",
|
|
17
|
+
"openapi.yaml"
|
|
18
|
+
],
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"default": "./dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./server": {
|
|
27
|
+
"types": "./dist/server.d.ts",
|
|
28
|
+
"default": "./dist/server.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"bin": {
|
|
32
|
+
"mockingbird-hermes": "./dist/cli.js"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public",
|
|
36
|
+
"provenance": true
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/crvouga/mockingbird.git",
|
|
41
|
+
"directory": "packages/service/hermes"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/crvouga/mockingbird/tree/main/packages/service/hermes#readme",
|
|
44
|
+
"keywords": [
|
|
45
|
+
"mockingbird",
|
|
46
|
+
"service",
|
|
47
|
+
"hermes",
|
|
48
|
+
"peer-runs"
|
|
49
|
+
],
|
|
50
|
+
"mockingbird": {
|
|
51
|
+
"runtime": "portable",
|
|
52
|
+
"entries": {
|
|
53
|
+
"server": "node",
|
|
54
|
+
"cli": "node"
|
|
55
|
+
},
|
|
56
|
+
"layer": "service",
|
|
57
|
+
"category": "infrastructure",
|
|
58
|
+
"displayName": "Hermes Agent",
|
|
59
|
+
"vendor": {
|
|
60
|
+
"website": "https://hermes-agent.nousresearch.com",
|
|
61
|
+
"docs": "https://hermes-agent.nousresearch.com/docs/user-guide/features/api-server/",
|
|
62
|
+
"description": "Hermes Agent exposes asynchronous public peer-run APIs."
|
|
63
|
+
},
|
|
64
|
+
"status": "wip",
|
|
65
|
+
"playground": {
|
|
66
|
+
"operation": "RunCreate"
|
|
67
|
+
},
|
|
68
|
+
"parity": "Pinned Hermes run lifecycle and recovery",
|
|
69
|
+
"discovery": {
|
|
70
|
+
"guide": "DISCOVERY.md",
|
|
71
|
+
"behavior": "README.md",
|
|
72
|
+
"capabilities": "SUPPORT.md",
|
|
73
|
+
"contract": "openapi.yaml",
|
|
74
|
+
"types": "dist/index.d.ts",
|
|
75
|
+
"oracle": {
|
|
76
|
+
"kind": "Live vendor API or sandbox",
|
|
77
|
+
"command": "bun run parity:service -- hermes",
|
|
78
|
+
"note": "Run from a Mockingbird checkout; credentials come only from .env.local or GitHub Actions secrets. Missing credentials exit 2."
|
|
79
|
+
},
|
|
80
|
+
"introspection": [
|
|
81
|
+
"GET /__admin/health",
|
|
82
|
+
"GET /__admin",
|
|
83
|
+
"GET /__admin/state",
|
|
84
|
+
"GET /__admin/requests",
|
|
85
|
+
"GET /__admin/metrics",
|
|
86
|
+
"GET /__admin/faults/presets",
|
|
87
|
+
"GET /__admin/ui"
|
|
88
|
+
],
|
|
89
|
+
"reporting": "https://github.com/crvouga/mockingbird/blob/main/docs/REPORTING_ISSUES.md"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"scripts": {
|
|
93
|
+
"generate": "bun ../../openapi/codegen/dist/cli.js",
|
|
94
|
+
"generate:check": "bun ../../openapi/codegen/dist/cli.js --check",
|
|
95
|
+
"openapi:check": "bun ../../openapi/codegen/dist/cli.js --validate",
|
|
96
|
+
"build": "bun ../../../scripts/bundle-service.ts",
|
|
97
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
98
|
+
"lint": "biome check .",
|
|
99
|
+
"test": "bun test",
|
|
100
|
+
"portability": "bun ../../../scripts/portability.ts",
|
|
101
|
+
"pack:check": "bun ../../../scripts/pack-check.ts"
|
|
102
|
+
},
|
|
103
|
+
"dependencies": {
|
|
104
|
+
"@crvouga/mockingbird-service-sqlite": "2.1.1",
|
|
105
|
+
"hono": "4.11.9"
|
|
106
|
+
},
|
|
107
|
+
"devDependencies": {
|
|
108
|
+
"@crvouga/mockingbird-parity": "0.0.0-development",
|
|
109
|
+
"@crvouga/mockingbird-testing": "0.1.0",
|
|
110
|
+
"@crvouga/mockingbird-openapi-codegen": "0.1.0",
|
|
111
|
+
"@crvouga/mockingbird-core": "0.0.0-development",
|
|
112
|
+
"@crvouga/mockingbird-sqlite": "0.0.0-development",
|
|
113
|
+
"@crvouga/mockingbird-openapi": "0.0.0-development",
|
|
114
|
+
"@crvouga/mockingbird-service": "0.0.0-development",
|
|
115
|
+
"@crvouga/mockingbird-adapter-node": "0.0.0-development"
|
|
116
|
+
}
|
|
117
|
+
}
|