agentlas 0.7.0 → 0.9.2
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 +199 -0
- package/README.md +161 -18
- package/bin/agentlas.cjs +8 -8
- package/engine/agentlas-core-harness.cjs +212 -0
- package/engine/agentlas-desktop-loadout.cjs +527 -0
- package/engine/agentlas-doctor.cjs +1 -1
- package/engine/agentlas-experience-exchange.cjs +835 -85
- package/engine/agentlas-experience-intake.cjs +444 -0
- package/engine/agentlas-experience-mcp.cjs +580 -18
- package/engine/agentlas-i18n.cjs +10 -10
- package/engine/agentlas-input.cjs +5 -4
- package/engine/agentlas-mcp-env.cjs +219 -0
- package/engine/agentlas-mcp-wrapper.cjs +51 -0
- package/engine/agentlas-memory-governance.cjs +1029 -0
- package/engine/agentlas-native-host.cjs +129 -39
- package/engine/agentlas-parity.cjs +339 -154
- package/engine/agentlas-repl.cjs +306 -31
- package/engine/agentlas-workforce.cjs +2991 -0
- package/engine/agentlas-workload-routing.cjs +523 -0
- package/engine/agentlas.cjs +1619 -234
- package/engine/bootstrap-schema.sql +1 -1
- package/engine/experience-taxonomy-v1.json +49 -0
- package/package.json +8 -4
- package/scripts/gen-bootstrap-schema.sh +0 -23
- package/test/bootstrap-race.cjs +0 -47
- package/test/capture-runtime-guard.cjs +0 -122
- package/test/cloud-asset-restore.cjs +0 -423
- package/test/cloud-cas-client.cjs +0 -333
- package/test/cloud-owner-restore.cjs +0 -183
- package/test/cloud-runtime-paths.cjs +0 -40
- package/test/cloud-save-publish.cjs +0 -487
- package/test/credential-env-regression.cjs +0 -52
- package/test/engine-hardening-regression.cjs +0 -74
- package/test/experience-exchange-contract.cjs +0 -569
- package/test/experience-mcp-contract.cjs +0 -391
- package/test/fixtures/portable-experience-bundle-v1-golden.json +0 -124
- package/test/login-loopback-security.cjs +0 -115
- package/test/mcp-config-isolation.cjs +0 -36
- package/test/permission-mapping.cjs +0 -180
- package/test/route-regression.cjs +0 -357
- package/test/run-api-regression.cjs +0 -322
- package/test/runtime-env-protection.cjs +0 -89
- package/test/semver-precedence.cjs +0 -39
- package/test/smoke.sh +0 -93
- package/test/sqlite-driver-probe.cjs +0 -22
- package/test/terminal-ui-regression.cjs +0 -477
- package/test/timeout-regression.cjs +0 -218
- package/test/tool-workspace-boundary.cjs +0 -165
- package/test/update-safety.cjs +0 -376
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("node:crypto");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const os = require("node:os");
|
|
6
|
+
const path = require("node:path");
|
|
7
|
+
const { spawn, spawnSync } = require("node:child_process");
|
|
8
|
+
|
|
9
|
+
const HARNESS_SCHEMA_VERSION = "agentlas.stormbreaker.goal-ultracode-harness.v1";
|
|
10
|
+
const HARNESS_ID = "agentlas-core/stormbreaker-goal-ultracode";
|
|
11
|
+
const HARNESS_MODE = "stormbreaker-goal-ultracode";
|
|
12
|
+
const CORE_RUNTIME_MARKERS = [
|
|
13
|
+
["agentlas_cloud", "__main__.py"],
|
|
14
|
+
["schemas", "workforce-work-order.schema.json"],
|
|
15
|
+
["schemas", "workforce-selection.schema.json"],
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const PY_BOOTSTRAP =
|
|
19
|
+
"import os, runpy, sys; " +
|
|
20
|
+
'cwd=os.getcwd(); root=os.environ["HEPHAESTUS_RUNTIME_ROOT"]; ' +
|
|
21
|
+
'sys.path=[p for p in sys.path if p not in ("", cwd, root)]; ' +
|
|
22
|
+
"sys.path.insert(0, root); " +
|
|
23
|
+
"sys.argv=sys.argv[1:]; " +
|
|
24
|
+
'runpy.run_module(sys.argv[0], run_name="__main__", alter_sys=True)';
|
|
25
|
+
|
|
26
|
+
function unique(values) {
|
|
27
|
+
return [...new Set(values.filter(Boolean).map((value) => path.resolve(String(value))))];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function runtimeRoots(explicitRoot) {
|
|
31
|
+
if (explicitRoot) return unique([explicitRoot]);
|
|
32
|
+
const binRoot = process.env.HEPHAESTUS_BIN
|
|
33
|
+
? path.dirname(path.dirname(path.resolve(process.env.HEPHAESTUS_BIN)))
|
|
34
|
+
: null;
|
|
35
|
+
const roots = [
|
|
36
|
+
process.env.HEPHAESTUS_RUNTIME_ROOT,
|
|
37
|
+
binRoot,
|
|
38
|
+
path.join(os.homedir(), ".agentlas", "runtime", "current"),
|
|
39
|
+
];
|
|
40
|
+
if (process.resourcesPath) roots.push(path.join(process.resourcesPath, "Hephaestus"));
|
|
41
|
+
if (process.platform === "darwin") roots.push("/Applications/Agentlas.app/Contents/Resources/Hephaestus");
|
|
42
|
+
return unique(roots);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resolveCoreRuntimeRoot(explicitRoot) {
|
|
46
|
+
for (const root of runtimeRoots(explicitRoot)) {
|
|
47
|
+
try {
|
|
48
|
+
if (CORE_RUNTIME_MARKERS.every((segments) => fs.existsSync(path.join(root, ...segments)))) {
|
|
49
|
+
return root;
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
// Continue to the next installed/bundled root.
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function pythonCandidates() {
|
|
59
|
+
return [...new Set([
|
|
60
|
+
process.env.HEPHAESTUS_PYTHON,
|
|
61
|
+
process.env.PYTHON,
|
|
62
|
+
...(process.platform === "win32" ? ["python", "py", "python3"] : ["python3", "python", "py"]),
|
|
63
|
+
].filter(Boolean))];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function pythonInvocation(executable) {
|
|
67
|
+
const basename = path.basename(String(executable)).toLowerCase();
|
|
68
|
+
return {
|
|
69
|
+
executable,
|
|
70
|
+
prefix: basename === "py" || basename === "py.exe" ? ["-3"] : [],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function resolvePython() {
|
|
75
|
+
for (const candidate of pythonCandidates()) {
|
|
76
|
+
const invocation = pythonInvocation(candidate);
|
|
77
|
+
try {
|
|
78
|
+
const probe = spawnSync(
|
|
79
|
+
invocation.executable,
|
|
80
|
+
[...invocation.prefix, "-c", "import sys; raise SystemExit(0 if sys.version_info >= (3, 9) else 1)"],
|
|
81
|
+
{ stdio: "ignore", windowsHide: true },
|
|
82
|
+
);
|
|
83
|
+
if (probe.status === 0) return invocation;
|
|
84
|
+
} catch {
|
|
85
|
+
// Continue to the next candidate.
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function spawnCoreModule(moduleName, args, opts = {}, explicitRoot) {
|
|
92
|
+
const root = resolveCoreRuntimeRoot(explicitRoot);
|
|
93
|
+
const python = resolvePython();
|
|
94
|
+
if (!root || !python) return null;
|
|
95
|
+
return spawn(
|
|
96
|
+
python.executable,
|
|
97
|
+
[...python.prefix, "-c", PY_BOOTSTRAP, moduleName, ...args],
|
|
98
|
+
{
|
|
99
|
+
...opts,
|
|
100
|
+
windowsHide: true,
|
|
101
|
+
env: {
|
|
102
|
+
...(opts.env || process.env),
|
|
103
|
+
HEPHAESTUS_RUNTIME_ROOT: root,
|
|
104
|
+
PYTHONUTF8: "1",
|
|
105
|
+
PYTHONIOENCODING: "utf-8",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function parseJsonOutput(stdout) {
|
|
112
|
+
const text = String(stdout || "");
|
|
113
|
+
const start = text.indexOf("{");
|
|
114
|
+
const end = text.lastIndexOf("}");
|
|
115
|
+
if (start < 0 || end <= start) return null;
|
|
116
|
+
try { return JSON.parse(text.slice(start, end + 1)); } catch { return null; }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function validateCoreStormbreakerHarness(harness) {
|
|
120
|
+
if (
|
|
121
|
+
!harness ||
|
|
122
|
+
harness.schema_version !== HARNESS_SCHEMA_VERSION ||
|
|
123
|
+
harness.harness_id !== HARNESS_ID ||
|
|
124
|
+
harness.mode !== HARNESS_MODE ||
|
|
125
|
+
typeof harness.system_prompt !== "string" ||
|
|
126
|
+
!harness.system_prompt.trim() ||
|
|
127
|
+
typeof harness.prompt_sha256 !== "string"
|
|
128
|
+
) {
|
|
129
|
+
throw new Error("Agentlas Core returned an invalid Stormbreaker harness contract.");
|
|
130
|
+
}
|
|
131
|
+
const digest = crypto.createHash("sha256").update(harness.system_prompt, "utf8").digest("hex");
|
|
132
|
+
if (digest !== harness.prompt_sha256) {
|
|
133
|
+
throw new Error("Agentlas Core Stormbreaker harness failed its SHA-256 integrity check.");
|
|
134
|
+
}
|
|
135
|
+
if (
|
|
136
|
+
harness.system_prompt.split("GOAL MODE:").length - 1 !== 1 ||
|
|
137
|
+
harness.system_prompt.split("ULTRACODE MODE:").length - 1 !== 1
|
|
138
|
+
) {
|
|
139
|
+
throw new Error("Agentlas Core Stormbreaker harness must contain exactly one Goal mode and one UltraCode mode.");
|
|
140
|
+
}
|
|
141
|
+
return harness;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function captureCoreJson(moduleName, args, opts = {}, explicitRoot) {
|
|
145
|
+
const child = spawnCoreModule(moduleName, args, { ...opts, stdio: ["ignore", "pipe", "pipe"] }, explicitRoot);
|
|
146
|
+
if (!child) throw new Error("Agentlas Core runtime or Python 3.9+ is unavailable.");
|
|
147
|
+
const result = await new Promise((resolve) => {
|
|
148
|
+
let stdout = "";
|
|
149
|
+
let stderr = "";
|
|
150
|
+
child.stdout.on("data", (chunk) => { stdout += chunk.toString(); });
|
|
151
|
+
child.stderr.on("data", (chunk) => { stderr = (stderr + chunk.toString()).slice(-4000); });
|
|
152
|
+
child.on("error", (error) => resolve({ code: 1, stdout, stderr: String(error.message) }));
|
|
153
|
+
child.on("close", (code) => resolve({ code: code ?? 0, stdout, stderr }));
|
|
154
|
+
});
|
|
155
|
+
const json = parseJsonOutput(result.stdout);
|
|
156
|
+
if (result.code !== 0 || !json) {
|
|
157
|
+
throw new Error(result.stderr.trim() || `Agentlas Core ${moduleName} did not return JSON.`);
|
|
158
|
+
}
|
|
159
|
+
return json;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function captureCoreJsonSync(moduleName, args, opts = {}, explicitRoot) {
|
|
163
|
+
const root = resolveCoreRuntimeRoot(explicitRoot);
|
|
164
|
+
const python = resolvePython();
|
|
165
|
+
if (!root || !python) throw new Error("Agentlas Core runtime or Python 3.9+ is unavailable.");
|
|
166
|
+
const result = spawnSync(
|
|
167
|
+
python.executable,
|
|
168
|
+
[...python.prefix, "-c", PY_BOOTSTRAP, moduleName, ...args],
|
|
169
|
+
{
|
|
170
|
+
...opts,
|
|
171
|
+
encoding: "utf8",
|
|
172
|
+
windowsHide: true,
|
|
173
|
+
timeout: opts.timeout || 120_000,
|
|
174
|
+
env: {
|
|
175
|
+
...(opts.env || process.env),
|
|
176
|
+
HEPHAESTUS_RUNTIME_ROOT: root,
|
|
177
|
+
PYTHONUTF8: "1",
|
|
178
|
+
PYTHONIOENCODING: "utf-8",
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
);
|
|
182
|
+
const json = parseJsonOutput(result.stdout);
|
|
183
|
+
if (result.status !== 0 || !json) {
|
|
184
|
+
throw new Error(String(result.stderr || result.error?.message || `Agentlas Core ${moduleName} did not return JSON.`).trim());
|
|
185
|
+
}
|
|
186
|
+
return json;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function loadCoreStormbreakerHarness(cwd, explicitRoot) {
|
|
190
|
+
const harness = await captureCoreJson(
|
|
191
|
+
"agentlas_cloud",
|
|
192
|
+
["stormbreaker", "harness"],
|
|
193
|
+
{ cwd },
|
|
194
|
+
explicitRoot,
|
|
195
|
+
);
|
|
196
|
+
return validateCoreStormbreakerHarness(harness);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.exports = {
|
|
200
|
+
HARNESS_SCHEMA_VERSION,
|
|
201
|
+
HARNESS_ID,
|
|
202
|
+
HARNESS_MODE,
|
|
203
|
+
PY_BOOTSTRAP,
|
|
204
|
+
resolveCoreRuntimeRoot,
|
|
205
|
+
resolvePython,
|
|
206
|
+
spawnCoreModule,
|
|
207
|
+
parseJsonOutput,
|
|
208
|
+
validateCoreStormbreakerHarness,
|
|
209
|
+
captureCoreJson,
|
|
210
|
+
captureCoreJsonSync,
|
|
211
|
+
loadCoreStormbreakerHarness,
|
|
212
|
+
};
|