micro-models-agent 0.30.0 → 0.32.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/dist/main.js +646 -253
- package/dist/modules/browser/bridge-server.mjs +194 -0
- package/package.json +45 -45
package/dist/main.js
CHANGED
|
@@ -2224,6 +2224,9 @@ var init_defaults = __esm(() => {
|
|
|
2224
2224
|
enabled: true,
|
|
2225
2225
|
headless: true,
|
|
2226
2226
|
maxElements: 30,
|
|
2227
|
+
maxContentChars: 2500,
|
|
2228
|
+
maxConsoleEntries: 40,
|
|
2229
|
+
maxConsoleLineChars: 400,
|
|
2227
2230
|
viewportWidth: 1280,
|
|
2228
2231
|
viewportHeight: 720,
|
|
2229
2232
|
navigationTimeout: 15000
|
|
@@ -2784,6 +2787,10 @@ Use this knowledge to answer the user's question.`,
|
|
|
2784
2787
|
"browser.no_page_short": "No page",
|
|
2785
2788
|
"browser.no_elements": "(no interactive elements on page)",
|
|
2786
2789
|
"browser.more_elements": "... and more elements not shown. Use scroll or search to find others.",
|
|
2790
|
+
"browser.content_header": "Content:",
|
|
2791
|
+
"browser.console_header": "Console:",
|
|
2792
|
+
"browser.network_errors_header": "Network errors:",
|
|
2793
|
+
"browser.truncated": "... (truncated)",
|
|
2787
2794
|
"pipeline.invalid": "Invalid pipeline: name and steps required",
|
|
2788
2795
|
"pipeline.step_missing_fields": "Step missing required fields (id, agent, prompt): {step}",
|
|
2789
2796
|
"pipeline.circular": "Circular dependency: {stepId}",
|
|
@@ -3357,6 +3364,10 @@ var init_ru = __esm(() => {
|
|
|
3357
3364
|
"browser.no_page_short": "Нет страницы",
|
|
3358
3365
|
"browser.no_elements": "(нет интерактивных элементов на странице)",
|
|
3359
3366
|
"browser.more_elements": "... и другие элементы не показаны. Используйте прокрутку или поиск.",
|
|
3367
|
+
"browser.content_header": "Содержимое:",
|
|
3368
|
+
"browser.console_header": "Консоль:",
|
|
3369
|
+
"browser.network_errors_header": "Сетевые ошибки:",
|
|
3370
|
+
"browser.truncated": "... (обрезано)",
|
|
3360
3371
|
"pipeline.invalid": "Невалидный пайплайн: требуются name и steps",
|
|
3361
3372
|
"pipeline.step_missing_fields": "Шаг не содержит обязательных полей (id, agent, prompt): {step}",
|
|
3362
3373
|
"pipeline.circular": "Циклическая зависимость: {stepId}",
|
|
@@ -13660,6 +13671,323 @@ var init_recall = __esm(() => {
|
|
|
13660
13671
|
};
|
|
13661
13672
|
});
|
|
13662
13673
|
|
|
13674
|
+
// src/modules/browser/bridge-client.ts
|
|
13675
|
+
var exports_bridge_client = {};
|
|
13676
|
+
__export(exports_bridge_client, {
|
|
13677
|
+
BridgeDriver: () => BridgeDriver
|
|
13678
|
+
});
|
|
13679
|
+
import { spawn as spawn4 } from "child_process";
|
|
13680
|
+
import { createInterface } from "readline";
|
|
13681
|
+
import { dirname as dirname6, join as join17 } from "path";
|
|
13682
|
+
import { fileURLToPath } from "url";
|
|
13683
|
+
function bridgeScriptPath() {
|
|
13684
|
+
return join17(dirname6(fileURLToPath(import.meta.url)), "bridge-server.mjs");
|
|
13685
|
+
}
|
|
13686
|
+
|
|
13687
|
+
class BridgeDriver {
|
|
13688
|
+
proc = null;
|
|
13689
|
+
rl = null;
|
|
13690
|
+
pending = new Map;
|
|
13691
|
+
nextId = 1;
|
|
13692
|
+
lastUrl = "";
|
|
13693
|
+
console = new ConsoleBuffer(500);
|
|
13694
|
+
network = [];
|
|
13695
|
+
maxConsoleLineChars;
|
|
13696
|
+
constructor(opts = {}) {
|
|
13697
|
+
this.maxConsoleLineChars = opts.maxConsoleLineChars ?? 400;
|
|
13698
|
+
}
|
|
13699
|
+
async send(cmd, params = {}) {
|
|
13700
|
+
if (!this.proc || !this.rl)
|
|
13701
|
+
throw new Error("Bridge is not running");
|
|
13702
|
+
const id = this.nextId++;
|
|
13703
|
+
const response = await new Promise((resolve15, reject) => {
|
|
13704
|
+
const timer = setTimeout(() => {
|
|
13705
|
+
this.pending.delete(id);
|
|
13706
|
+
reject(new Error(`Bridge timeout waiting for "${cmd}"`));
|
|
13707
|
+
}, BRIDGE_REQUEST_TIMEOUT_MS);
|
|
13708
|
+
this.pending.set(id, (resp) => {
|
|
13709
|
+
clearTimeout(timer);
|
|
13710
|
+
resolve15(resp);
|
|
13711
|
+
});
|
|
13712
|
+
this.proc.stdin.write(JSON.stringify({ id, cmd, params }) + `
|
|
13713
|
+
`);
|
|
13714
|
+
});
|
|
13715
|
+
this.drainEvents(response);
|
|
13716
|
+
if (!response.ok)
|
|
13717
|
+
throw new Error(response.error || `Bridge command failed: ${cmd}`);
|
|
13718
|
+
return response;
|
|
13719
|
+
}
|
|
13720
|
+
drainEvents(resp) {
|
|
13721
|
+
if (Array.isArray(resp.console)) {
|
|
13722
|
+
for (const entry of resp.console) {
|
|
13723
|
+
this.console.add(entry.type, entry.text);
|
|
13724
|
+
}
|
|
13725
|
+
}
|
|
13726
|
+
if (Array.isArray(resp.network)) {
|
|
13727
|
+
for (const err of resp.network)
|
|
13728
|
+
this.network.push(err);
|
|
13729
|
+
}
|
|
13730
|
+
if (resp.data && typeof resp.data.url === "string") {
|
|
13731
|
+
this.lastUrl = resp.data.url;
|
|
13732
|
+
}
|
|
13733
|
+
}
|
|
13734
|
+
async launch(cfg) {
|
|
13735
|
+
this.spawnBridge();
|
|
13736
|
+
await this.send("launch", {
|
|
13737
|
+
headless: cfg.headless,
|
|
13738
|
+
viewport: cfg.viewport,
|
|
13739
|
+
timeoutMs: cfg.timeoutMs,
|
|
13740
|
+
maxConsoleLineChars: this.maxConsoleLineChars
|
|
13741
|
+
});
|
|
13742
|
+
}
|
|
13743
|
+
spawnBridge() {
|
|
13744
|
+
const script = bridgeScriptPath();
|
|
13745
|
+
const proc = spawn4("node", [script], { stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
|
|
13746
|
+
this.proc = proc;
|
|
13747
|
+
proc.stderr.on("data", () => {});
|
|
13748
|
+
const rl = createInterface({ input: proc.stdout });
|
|
13749
|
+
this.rl = rl;
|
|
13750
|
+
rl.on("line", (line) => {
|
|
13751
|
+
let resp;
|
|
13752
|
+
try {
|
|
13753
|
+
resp = JSON.parse(line);
|
|
13754
|
+
} catch {
|
|
13755
|
+
return;
|
|
13756
|
+
}
|
|
13757
|
+
const resolver = this.pending.get(resp.id);
|
|
13758
|
+
if (resolver) {
|
|
13759
|
+
this.pending.delete(resp.id);
|
|
13760
|
+
resolver(resp);
|
|
13761
|
+
}
|
|
13762
|
+
});
|
|
13763
|
+
proc.on("exit", () => {
|
|
13764
|
+
for (const [, resolver] of this.pending) {
|
|
13765
|
+
resolver({ id: -1, ok: false, error: "Bridge process exited" });
|
|
13766
|
+
}
|
|
13767
|
+
this.pending.clear();
|
|
13768
|
+
this.proc = null;
|
|
13769
|
+
this.rl = null;
|
|
13770
|
+
});
|
|
13771
|
+
}
|
|
13772
|
+
async goto(url, timeoutMs) {
|
|
13773
|
+
await this.send("goto", { url, timeoutMs });
|
|
13774
|
+
}
|
|
13775
|
+
async evaluate(js) {
|
|
13776
|
+
const resp = await this.send("evaluate", { js });
|
|
13777
|
+
return resp.data?.result;
|
|
13778
|
+
}
|
|
13779
|
+
async content() {
|
|
13780
|
+
const resp = await this.send("content");
|
|
13781
|
+
return String(resp.data?.html ?? "");
|
|
13782
|
+
}
|
|
13783
|
+
async title() {
|
|
13784
|
+
const resp = await this.send("title");
|
|
13785
|
+
return String(resp.data?.title ?? "");
|
|
13786
|
+
}
|
|
13787
|
+
url() {
|
|
13788
|
+
return this.lastUrl;
|
|
13789
|
+
}
|
|
13790
|
+
async waitForLoad(timeoutMs) {
|
|
13791
|
+
await this.send("waitLoad", { timeoutMs });
|
|
13792
|
+
}
|
|
13793
|
+
async screenshot() {
|
|
13794
|
+
const resp = await this.send("screenshot");
|
|
13795
|
+
return Buffer.from(String(resp.data?.base64 ?? ""), "base64");
|
|
13796
|
+
}
|
|
13797
|
+
async cookies() {
|
|
13798
|
+
const resp = await this.send("cookies");
|
|
13799
|
+
return resp.data?.cookies ?? [];
|
|
13800
|
+
}
|
|
13801
|
+
async addCookies(cookies) {
|
|
13802
|
+
await this.send("setCookies", { cookies });
|
|
13803
|
+
}
|
|
13804
|
+
async goBack(timeoutMs) {
|
|
13805
|
+
await this.send("back", { timeoutMs });
|
|
13806
|
+
}
|
|
13807
|
+
async goForward(timeoutMs) {
|
|
13808
|
+
await this.send("forward", { timeoutMs });
|
|
13809
|
+
}
|
|
13810
|
+
resetEventLog() {
|
|
13811
|
+
this.console.clear();
|
|
13812
|
+
this.network = [];
|
|
13813
|
+
}
|
|
13814
|
+
getConsole() {
|
|
13815
|
+
return this.console.getAll();
|
|
13816
|
+
}
|
|
13817
|
+
getNetworkErrors() {
|
|
13818
|
+
return this.network.slice(-15);
|
|
13819
|
+
}
|
|
13820
|
+
async close() {
|
|
13821
|
+
try {
|
|
13822
|
+
if (this.proc)
|
|
13823
|
+
await this.send("close");
|
|
13824
|
+
} catch {}
|
|
13825
|
+
this.dispose();
|
|
13826
|
+
}
|
|
13827
|
+
dispose() {
|
|
13828
|
+
if (this.proc) {
|
|
13829
|
+
this.proc.kill();
|
|
13830
|
+
this.proc = null;
|
|
13831
|
+
}
|
|
13832
|
+
if (this.rl) {
|
|
13833
|
+
this.rl.close();
|
|
13834
|
+
this.rl = null;
|
|
13835
|
+
}
|
|
13836
|
+
}
|
|
13837
|
+
}
|
|
13838
|
+
var BRIDGE_REQUEST_TIMEOUT_MS = 30000;
|
|
13839
|
+
var init_bridge_client = __esm(() => {
|
|
13840
|
+
init_session();
|
|
13841
|
+
});
|
|
13842
|
+
|
|
13843
|
+
// src/modules/browser/driver.ts
|
|
13844
|
+
import { chromium } from "playwright";
|
|
13845
|
+
|
|
13846
|
+
class PlaywrightDriver {
|
|
13847
|
+
browser = null;
|
|
13848
|
+
context = null;
|
|
13849
|
+
page = null;
|
|
13850
|
+
console = new ConsoleBuffer;
|
|
13851
|
+
network = [];
|
|
13852
|
+
async launch(cfg) {
|
|
13853
|
+
if (this.browser)
|
|
13854
|
+
return;
|
|
13855
|
+
this.browser = await chromium.launch({
|
|
13856
|
+
headless: cfg.headless,
|
|
13857
|
+
timeout: cfg.timeoutMs
|
|
13858
|
+
});
|
|
13859
|
+
this.context = await this.browser.newContext({ viewport: cfg.viewport });
|
|
13860
|
+
this.page = await this.context.newPage();
|
|
13861
|
+
this.page.setDefaultTimeout(cfg.timeoutMs);
|
|
13862
|
+
this.page.on("console", (msg) => this.console.add(msg.type(), msg.text()));
|
|
13863
|
+
this.page.on("pageerror", (err) => this.console.add("pageerror", `Page error: ${err.message}`));
|
|
13864
|
+
this.page.on("requestfailed", (req) => {
|
|
13865
|
+
const failure = req.failure();
|
|
13866
|
+
this.network.push({
|
|
13867
|
+
method: req.method(),
|
|
13868
|
+
url: req.url(),
|
|
13869
|
+
error: failure?.errorText || "unknown"
|
|
13870
|
+
});
|
|
13871
|
+
});
|
|
13872
|
+
}
|
|
13873
|
+
async goto(url, timeoutMs) {
|
|
13874
|
+
this.requirePage();
|
|
13875
|
+
this.console.clear();
|
|
13876
|
+
this.network = [];
|
|
13877
|
+
await this.page.goto(url, { waitUntil: "domcontentloaded", timeout: timeoutMs });
|
|
13878
|
+
}
|
|
13879
|
+
async evaluate(js) {
|
|
13880
|
+
return this.requirePage().evaluate(js);
|
|
13881
|
+
}
|
|
13882
|
+
async content() {
|
|
13883
|
+
return this.requirePage().content();
|
|
13884
|
+
}
|
|
13885
|
+
async title() {
|
|
13886
|
+
return this.requirePage().title();
|
|
13887
|
+
}
|
|
13888
|
+
url() {
|
|
13889
|
+
return this.page?.url() || "";
|
|
13890
|
+
}
|
|
13891
|
+
async waitForLoad(timeoutMs) {
|
|
13892
|
+
await this.requirePage().waitForLoadState("domcontentloaded", { timeout: timeoutMs }).catch(() => {});
|
|
13893
|
+
}
|
|
13894
|
+
async screenshot() {
|
|
13895
|
+
return this.requirePage().screenshot({ type: "png", fullPage: false });
|
|
13896
|
+
}
|
|
13897
|
+
async cookies() {
|
|
13898
|
+
if (!this.context)
|
|
13899
|
+
return [];
|
|
13900
|
+
return this.context.cookies();
|
|
13901
|
+
}
|
|
13902
|
+
async addCookies(cookies) {
|
|
13903
|
+
if (!this.context || cookies.length === 0)
|
|
13904
|
+
return;
|
|
13905
|
+
await this.context.addCookies(cookies);
|
|
13906
|
+
}
|
|
13907
|
+
async goBack(timeoutMs) {
|
|
13908
|
+
await this.requirePage().goBack({ waitUntil: "domcontentloaded", timeout: timeoutMs }).catch(() => {});
|
|
13909
|
+
}
|
|
13910
|
+
async goForward(timeoutMs) {
|
|
13911
|
+
await this.requirePage().goForward({ waitUntil: "domcontentloaded", timeout: timeoutMs }).catch(() => {});
|
|
13912
|
+
}
|
|
13913
|
+
resetEventLog() {
|
|
13914
|
+
this.console.clear();
|
|
13915
|
+
this.network = [];
|
|
13916
|
+
}
|
|
13917
|
+
getConsole() {
|
|
13918
|
+
return this.console.getAll();
|
|
13919
|
+
}
|
|
13920
|
+
getNetworkErrors() {
|
|
13921
|
+
return this.network.slice(-15);
|
|
13922
|
+
}
|
|
13923
|
+
async close() {
|
|
13924
|
+
if (this.page)
|
|
13925
|
+
await this.page.close().catch(() => {});
|
|
13926
|
+
if (this.context)
|
|
13927
|
+
await this.context.close().catch(() => {});
|
|
13928
|
+
if (this.browser)
|
|
13929
|
+
await this.browser.close().catch(() => {});
|
|
13930
|
+
this.page = null;
|
|
13931
|
+
this.context = null;
|
|
13932
|
+
this.browser = null;
|
|
13933
|
+
}
|
|
13934
|
+
dispose() {
|
|
13935
|
+
this.close().catch(() => {});
|
|
13936
|
+
}
|
|
13937
|
+
requirePage() {
|
|
13938
|
+
if (!this.page)
|
|
13939
|
+
throw new Error("No page open");
|
|
13940
|
+
return this.page;
|
|
13941
|
+
}
|
|
13942
|
+
}
|
|
13943
|
+
function createBrowserDriver(config) {
|
|
13944
|
+
const common = {
|
|
13945
|
+
headless: config.headless,
|
|
13946
|
+
viewport: { width: config.viewportWidth, height: config.viewportHeight },
|
|
13947
|
+
timeoutMs: config.navigationTimeout
|
|
13948
|
+
};
|
|
13949
|
+
return (async () => {
|
|
13950
|
+
if (process.versions.bun) {
|
|
13951
|
+
return launchBridge(config, common);
|
|
13952
|
+
}
|
|
13953
|
+
const direct = new PlaywrightDriver;
|
|
13954
|
+
try {
|
|
13955
|
+
await direct.launch({ ...common, timeoutMs: DIRECT_LAUNCH_TIMEOUT_MS });
|
|
13956
|
+
return direct;
|
|
13957
|
+
} catch {
|
|
13958
|
+
direct.dispose();
|
|
13959
|
+
}
|
|
13960
|
+
return launchBridge(config, common);
|
|
13961
|
+
})();
|
|
13962
|
+
}
|
|
13963
|
+
async function launchBridge(config, common) {
|
|
13964
|
+
const { BridgeDriver: BridgeDriver2 } = await Promise.resolve().then(() => (init_bridge_client(), exports_bridge_client));
|
|
13965
|
+
const bridge = new BridgeDriver2({ maxConsoleLineChars: config.maxConsoleLineChars });
|
|
13966
|
+
await bridge.launch(common);
|
|
13967
|
+
return bridge;
|
|
13968
|
+
}
|
|
13969
|
+
var DIRECT_LAUNCH_TIMEOUT_MS = 8000;
|
|
13970
|
+
var init_driver = __esm(() => {
|
|
13971
|
+
init_session();
|
|
13972
|
+
});
|
|
13973
|
+
|
|
13974
|
+
// src/modules/browser/types.ts
|
|
13975
|
+
var DEFAULT_BROWSER_CONFIG;
|
|
13976
|
+
var init_types = __esm(() => {
|
|
13977
|
+
DEFAULT_BROWSER_CONFIG = {
|
|
13978
|
+
headless: true,
|
|
13979
|
+
maxElements: 30,
|
|
13980
|
+
maxContentChars: 2500,
|
|
13981
|
+
maxConsoleEntries: 40,
|
|
13982
|
+
maxConsoleLineChars: 400,
|
|
13983
|
+
screenshotMaxWidth: 1280,
|
|
13984
|
+
cookieDir: "",
|
|
13985
|
+
viewportWidth: 1280,
|
|
13986
|
+
viewportHeight: 720,
|
|
13987
|
+
navigationTimeout: 15000
|
|
13988
|
+
};
|
|
13989
|
+
});
|
|
13990
|
+
|
|
13663
13991
|
// src/modules/browser/snapshot.ts
|
|
13664
13992
|
function inferRole(tag, type) {
|
|
13665
13993
|
const t2 = tag.toLowerCase();
|
|
@@ -13747,35 +14075,69 @@ function extractInteractiveElements(html, maxElements = 30) {
|
|
|
13747
14075
|
}
|
|
13748
14076
|
return elements;
|
|
13749
14077
|
}
|
|
13750
|
-
function
|
|
14078
|
+
function truncateText(text, maxChars) {
|
|
14079
|
+
if (maxChars <= 0)
|
|
14080
|
+
return "";
|
|
14081
|
+
if (text.length <= maxChars)
|
|
14082
|
+
return text;
|
|
14083
|
+
const cut = text.slice(0, maxChars);
|
|
14084
|
+
const lastNewline = cut.lastIndexOf(`
|
|
14085
|
+
`);
|
|
14086
|
+
const safe = lastNewline > maxChars * 0.6 ? cut.slice(0, lastNewline) : cut;
|
|
14087
|
+
return `${safe}
|
|
14088
|
+
${t("browser.truncated")}`;
|
|
14089
|
+
}
|
|
14090
|
+
function formatSnapshot(snapshot, maxContentChars = DEFAULT_BROWSER_CONFIG.maxContentChars) {
|
|
13751
14091
|
const lines = [];
|
|
13752
14092
|
lines.push(`Page: "${snapshot.title}"`);
|
|
13753
14093
|
lines.push(`URL: ${snapshot.url}`);
|
|
13754
14094
|
lines.push("");
|
|
13755
14095
|
if (snapshot.elements.length === 0 && !snapshot.truncated) {
|
|
13756
14096
|
lines.push(t("browser.no_elements"));
|
|
13757
|
-
|
|
13758
|
-
|
|
14097
|
+
} else {
|
|
14098
|
+
for (const el of snapshot.elements) {
|
|
14099
|
+
let line = `[${el.index}] ${el.role}`;
|
|
14100
|
+
if (el.name)
|
|
14101
|
+
line += ` "${el.name}"`;
|
|
14102
|
+
if (el.href)
|
|
14103
|
+
line += ` → ${el.href}`;
|
|
14104
|
+
if (el.value)
|
|
14105
|
+
line += ` = "${el.value}"`;
|
|
14106
|
+
lines.push(line);
|
|
14107
|
+
}
|
|
14108
|
+
if (snapshot.truncated) {
|
|
14109
|
+
lines.push("");
|
|
14110
|
+
lines.push(t("browser.more_elements"));
|
|
14111
|
+
}
|
|
14112
|
+
}
|
|
14113
|
+
if (snapshot.content) {
|
|
14114
|
+
lines.push("");
|
|
14115
|
+
lines.push(t("browser.content_header"));
|
|
14116
|
+
for (const line of truncateText(snapshot.content, maxContentChars).split(`
|
|
14117
|
+
`)) {
|
|
14118
|
+
lines.push(`- ${line}`);
|
|
14119
|
+
}
|
|
14120
|
+
}
|
|
14121
|
+
if (snapshot.console.length > 0) {
|
|
14122
|
+
lines.push("");
|
|
14123
|
+
lines.push(t("browser.console_header"));
|
|
14124
|
+
for (const entry of snapshot.console) {
|
|
14125
|
+
lines.push(`[${entry.type}] ${entry.text}`);
|
|
14126
|
+
}
|
|
13759
14127
|
}
|
|
13760
|
-
|
|
13761
|
-
let line = `[${el.index}] ${el.role}`;
|
|
13762
|
-
if (el.name)
|
|
13763
|
-
line += ` "${el.name}"`;
|
|
13764
|
-
if (el.href)
|
|
13765
|
-
line += ` → ${el.href}`;
|
|
13766
|
-
if (el.value)
|
|
13767
|
-
line += ` = "${el.value}"`;
|
|
13768
|
-
lines.push(line);
|
|
13769
|
-
}
|
|
13770
|
-
if (snapshot.truncated) {
|
|
14128
|
+
if (snapshot.networkErrors.length > 0) {
|
|
13771
14129
|
lines.push("");
|
|
13772
|
-
lines.push(t("browser.
|
|
14130
|
+
lines.push(t("browser.network_errors_header"));
|
|
14131
|
+
for (const err of snapshot.networkErrors) {
|
|
14132
|
+
lines.push(`${err.method} ${err.url} → ${err.error}`);
|
|
14133
|
+
}
|
|
13773
14134
|
}
|
|
13774
14135
|
return lines.join(`
|
|
13775
14136
|
`);
|
|
13776
14137
|
}
|
|
13777
14138
|
var init_snapshot = __esm(() => {
|
|
13778
14139
|
init_i18n();
|
|
14140
|
+
init_types();
|
|
13779
14141
|
});
|
|
13780
14142
|
|
|
13781
14143
|
// src/modules/browser/actions.ts
|
|
@@ -13822,18 +14184,48 @@ function buildIndexInjectionScript() {
|
|
|
13822
14184
|
});
|
|
13823
14185
|
`;
|
|
13824
14186
|
}
|
|
14187
|
+
function buildTextExtractionScript() {
|
|
14188
|
+
return `
|
|
14189
|
+
const contentTags = new Set(['h1','h2','h3','h4','h5','h6','p','li','article','main','section','blockquote','pre','td','th','dt','dd','figcaption']);
|
|
14190
|
+
const out = [];
|
|
14191
|
+
const seen = new Set();
|
|
14192
|
+
const isHidden = (el) => {
|
|
14193
|
+
const st = window.getComputedStyle(el);
|
|
14194
|
+
return st.display === 'none' || st.visibility === 'hidden';
|
|
14195
|
+
};
|
|
14196
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
|
|
14197
|
+
acceptNode: (node) => {
|
|
14198
|
+
const tag = node.tagName ? node.tagName.toLowerCase() : '';
|
|
14199
|
+
if (!contentTags.has(tag)) return NodeFilter.FILTER_SKIP;
|
|
14200
|
+
if (isHidden(node)) return NodeFilter.FILTER_REJECT;
|
|
14201
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
14202
|
+
}
|
|
14203
|
+
});
|
|
14204
|
+
let node;
|
|
14205
|
+
while ((node = walker.nextNode())) {
|
|
14206
|
+
const tag = node.tagName.toLowerCase();
|
|
14207
|
+
const text = (node.textContent || '').replace(/\\s+/g, ' ').trim();
|
|
14208
|
+
if (!text) continue;
|
|
14209
|
+
if (seen.has(text)) continue;
|
|
14210
|
+
seen.add(text);
|
|
14211
|
+
const line = text.length > 200 ? text.slice(0, 200) + '…' : text;
|
|
14212
|
+
out.push('[' + tag + '] ' + line);
|
|
14213
|
+
}
|
|
14214
|
+
return out.join('\\n');
|
|
14215
|
+
`;
|
|
14216
|
+
}
|
|
13825
14217
|
|
|
13826
14218
|
// src/modules/browser/cookie-store.ts
|
|
13827
14219
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
13828
|
-
import { join as
|
|
14220
|
+
import { join as join18 } from "path";
|
|
13829
14221
|
|
|
13830
14222
|
class CookieStore {
|
|
13831
14223
|
filePath;
|
|
13832
14224
|
constructor(cookieDir) {
|
|
13833
|
-
this.filePath =
|
|
14225
|
+
this.filePath = join18(cookieDir, "cookies.json");
|
|
13834
14226
|
}
|
|
13835
14227
|
async save(cookies) {
|
|
13836
|
-
await mkdir(
|
|
14228
|
+
await mkdir(join18(this.filePath, ".."), { recursive: true });
|
|
13837
14229
|
await writeFile(this.filePath, JSON.stringify(cookies, null, 2), "utf-8");
|
|
13838
14230
|
}
|
|
13839
14231
|
async load() {
|
|
@@ -13851,9 +14243,32 @@ class CookieStore {
|
|
|
13851
14243
|
var init_cookie_store = () => {};
|
|
13852
14244
|
|
|
13853
14245
|
// src/modules/browser/session.ts
|
|
13854
|
-
|
|
13855
|
-
|
|
13856
|
-
|
|
14246
|
+
class ConsoleBuffer {
|
|
14247
|
+
entries = [];
|
|
14248
|
+
maxEntries;
|
|
14249
|
+
constructor(maxEntries = 20) {
|
|
14250
|
+
this.maxEntries = maxEntries;
|
|
14251
|
+
}
|
|
14252
|
+
add(type, text) {
|
|
14253
|
+
const clean = String(text).replace(/\s+/g, " ").trim();
|
|
14254
|
+
if (!clean)
|
|
14255
|
+
return;
|
|
14256
|
+
const line = clean.length > CONSOLE_MAX_LINE ? clean.slice(0, CONSOLE_MAX_LINE) + "…" : clean;
|
|
14257
|
+
this.entries.push({ type, text: line });
|
|
14258
|
+
if (this.entries.length > this.maxEntries) {
|
|
14259
|
+
this.entries.splice(0, this.entries.length - this.maxEntries);
|
|
14260
|
+
}
|
|
14261
|
+
}
|
|
14262
|
+
clear() {
|
|
14263
|
+
this.entries = [];
|
|
14264
|
+
}
|
|
14265
|
+
getAll() {
|
|
14266
|
+
return [...this.entries];
|
|
14267
|
+
}
|
|
14268
|
+
get size() {
|
|
14269
|
+
return this.entries.length;
|
|
14270
|
+
}
|
|
14271
|
+
}
|
|
13857
14272
|
|
|
13858
14273
|
class BrowserActionTracker {
|
|
13859
14274
|
history = [];
|
|
@@ -13881,9 +14296,7 @@ class BrowserActionTracker {
|
|
|
13881
14296
|
}
|
|
13882
14297
|
|
|
13883
14298
|
class BrowserSession {
|
|
13884
|
-
|
|
13885
|
-
context = null;
|
|
13886
|
-
page = null;
|
|
14299
|
+
driver = null;
|
|
13887
14300
|
config;
|
|
13888
14301
|
cookieStore;
|
|
13889
14302
|
state = {
|
|
@@ -13941,7 +14354,7 @@ class BrowserSession {
|
|
|
13941
14354
|
};
|
|
13942
14355
|
}
|
|
13943
14356
|
if (action !== "open") {
|
|
13944
|
-
const warning = this.actionTracker.record(action, args, this.
|
|
14357
|
+
const warning = this.actionTracker.record(action, args, this.driver?.url() || "");
|
|
13945
14358
|
if (warning && result.success) {
|
|
13946
14359
|
result.output = result.output + `
|
|
13947
14360
|
|
|
@@ -13956,45 +14369,40 @@ class BrowserSession {
|
|
|
13956
14369
|
};
|
|
13957
14370
|
}
|
|
13958
14371
|
}
|
|
13959
|
-
async
|
|
13960
|
-
if (!this.
|
|
14372
|
+
async ensureDriver() {
|
|
14373
|
+
if (!this.driver) {
|
|
13961
14374
|
return { success: false, output: t("browser.no_page") };
|
|
13962
14375
|
}
|
|
13963
14376
|
return null;
|
|
13964
14377
|
}
|
|
13965
14378
|
async launch() {
|
|
13966
|
-
if (this.
|
|
14379
|
+
if (this.driver)
|
|
13967
14380
|
return;
|
|
13968
|
-
this.
|
|
13969
|
-
this.context = await this.browser.newContext({
|
|
13970
|
-
viewport: {
|
|
13971
|
-
width: this.config.viewportWidth,
|
|
13972
|
-
height: this.config.viewportHeight
|
|
13973
|
-
}
|
|
13974
|
-
});
|
|
14381
|
+
this.driver = await createBrowserDriver(this.config);
|
|
13975
14382
|
const savedCookies = await this.cookieStore.load();
|
|
13976
14383
|
if (savedCookies.length > 0) {
|
|
13977
|
-
await this.
|
|
13978
|
-
...c,
|
|
13979
|
-
sameSite: c.sameSite
|
|
13980
|
-
})));
|
|
14384
|
+
await this.driver.addCookies(savedCookies);
|
|
13981
14385
|
}
|
|
13982
|
-
this.page = await this.context.newPage();
|
|
13983
|
-
this.page.setDefaultTimeout(this.config.navigationTimeout);
|
|
13984
14386
|
}
|
|
13985
14387
|
async saveCookies() {
|
|
13986
|
-
if (!this.
|
|
14388
|
+
if (!this.driver)
|
|
13987
14389
|
return;
|
|
13988
|
-
const cookies = await this.
|
|
14390
|
+
const cookies = await this.driver.cookies();
|
|
13989
14391
|
await this.cookieStore.save(cookies);
|
|
13990
14392
|
}
|
|
13991
14393
|
async takeSnapshot() {
|
|
13992
|
-
if (!this.
|
|
14394
|
+
if (!this.driver)
|
|
13993
14395
|
return "No page open.";
|
|
13994
|
-
await this.
|
|
13995
|
-
const html = await this.
|
|
13996
|
-
const url = this.
|
|
13997
|
-
const title = await this.
|
|
14396
|
+
await this.driver.evaluate(buildIndexInjectionScript());
|
|
14397
|
+
const html = await this.driver.content();
|
|
14398
|
+
const url = this.driver.url();
|
|
14399
|
+
const title = await this.driver.title();
|
|
14400
|
+
let content = "";
|
|
14401
|
+
try {
|
|
14402
|
+
content = String(await this.driver.evaluate(buildTextExtractionScript()));
|
|
14403
|
+
} catch {
|
|
14404
|
+
content = "";
|
|
14405
|
+
}
|
|
13998
14406
|
const allElements = extractInteractiveElements(html, this.config.maxElements + 5);
|
|
13999
14407
|
const truncated = allElements.length > this.config.maxElements;
|
|
14000
14408
|
const elements = allElements.slice(0, this.config.maxElements);
|
|
@@ -14004,7 +14412,15 @@ class BrowserSession {
|
|
|
14004
14412
|
title,
|
|
14005
14413
|
elementCount: elements.length
|
|
14006
14414
|
};
|
|
14007
|
-
return formatSnapshot({
|
|
14415
|
+
return formatSnapshot({
|
|
14416
|
+
url,
|
|
14417
|
+
title,
|
|
14418
|
+
elements,
|
|
14419
|
+
content,
|
|
14420
|
+
console: this.driver.getConsole(),
|
|
14421
|
+
networkErrors: this.driver.getNetworkErrors(),
|
|
14422
|
+
truncated
|
|
14423
|
+
});
|
|
14008
14424
|
}
|
|
14009
14425
|
async open(url) {
|
|
14010
14426
|
if (!url)
|
|
@@ -14014,14 +14430,12 @@ class BrowserSession {
|
|
|
14014
14430
|
url = isLocalhost ? "http://" + url : "https://" + url;
|
|
14015
14431
|
}
|
|
14016
14432
|
await this.launch();
|
|
14017
|
-
if (!this.
|
|
14433
|
+
if (!this.driver)
|
|
14018
14434
|
return { success: false, output: t("browser.create_page_failed") };
|
|
14019
14435
|
this.actionTracker.reset();
|
|
14436
|
+
this.driver.resetEventLog();
|
|
14020
14437
|
try {
|
|
14021
|
-
await this.
|
|
14022
|
-
waitUntil: "domcontentloaded",
|
|
14023
|
-
timeout: this.config.navigationTimeout
|
|
14024
|
-
});
|
|
14438
|
+
await this.driver.goto(url, this.config.navigationTimeout);
|
|
14025
14439
|
} catch (err) {
|
|
14026
14440
|
return {
|
|
14027
14441
|
success: false,
|
|
@@ -14033,18 +14447,17 @@ class BrowserSession {
|
|
|
14033
14447
|
return { success: true, output: snapshot };
|
|
14034
14448
|
}
|
|
14035
14449
|
async click(target) {
|
|
14036
|
-
const err = await this.
|
|
14450
|
+
const err = await this.ensureDriver();
|
|
14037
14451
|
if (err)
|
|
14038
14452
|
return err;
|
|
14039
|
-
if (!this.
|
|
14453
|
+
if (!this.driver)
|
|
14040
14454
|
return { success: false, output: "No page" };
|
|
14041
14455
|
if (!target || target < 1) {
|
|
14042
14456
|
return { success: false, output: t("browser.invalid_target") };
|
|
14043
14457
|
}
|
|
14044
14458
|
try {
|
|
14045
|
-
|
|
14046
|
-
await this.
|
|
14047
|
-
await this.page.waitForLoadState("domcontentloaded", { timeout: 5000 }).catch(() => {});
|
|
14459
|
+
await this.driver.evaluate(buildClickScript(target));
|
|
14460
|
+
await this.driver.waitForLoad(5000);
|
|
14048
14461
|
await new Promise((r) => setTimeout(r, 500));
|
|
14049
14462
|
const snapshot = await this.takeSnapshot();
|
|
14050
14463
|
await this.saveCookies();
|
|
@@ -14057,10 +14470,10 @@ class BrowserSession {
|
|
|
14057
14470
|
}
|
|
14058
14471
|
}
|
|
14059
14472
|
async type(target, text) {
|
|
14060
|
-
const err = await this.
|
|
14473
|
+
const err = await this.ensureDriver();
|
|
14061
14474
|
if (err)
|
|
14062
14475
|
return err;
|
|
14063
|
-
if (!this.
|
|
14476
|
+
if (!this.driver)
|
|
14064
14477
|
return { success: false, output: "No page" };
|
|
14065
14478
|
if (!target || target < 1) {
|
|
14066
14479
|
return { success: false, output: t("browser.invalid_target_short") };
|
|
@@ -14069,8 +14482,7 @@ class BrowserSession {
|
|
|
14069
14482
|
return { success: false, output: t("browser.text_required") };
|
|
14070
14483
|
}
|
|
14071
14484
|
try {
|
|
14072
|
-
|
|
14073
|
-
await this.page.evaluate(script);
|
|
14485
|
+
await this.driver.evaluate(buildTypeScript(target, text));
|
|
14074
14486
|
const snapshot = await this.takeSnapshot();
|
|
14075
14487
|
return { success: true, output: snapshot };
|
|
14076
14488
|
} catch (err2) {
|
|
@@ -14081,17 +14493,17 @@ class BrowserSession {
|
|
|
14081
14493
|
}
|
|
14082
14494
|
}
|
|
14083
14495
|
async scroll(direction) {
|
|
14084
|
-
const err = await this.
|
|
14496
|
+
const err = await this.ensureDriver();
|
|
14085
14497
|
if (err)
|
|
14086
14498
|
return err;
|
|
14087
|
-
if (!this.
|
|
14499
|
+
if (!this.driver)
|
|
14088
14500
|
return { success: false, output: "No page" };
|
|
14089
14501
|
const dir = direction;
|
|
14090
14502
|
if (!["up", "down", "top", "bottom"].includes(dir)) {
|
|
14091
14503
|
return { success: false, output: t("browser.direction_invalid") };
|
|
14092
14504
|
}
|
|
14093
14505
|
try {
|
|
14094
|
-
await this.
|
|
14506
|
+
await this.driver.evaluate(buildScrollScript(dir));
|
|
14095
14507
|
await new Promise((r) => setTimeout(r, 300));
|
|
14096
14508
|
const snapshot = await this.takeSnapshot();
|
|
14097
14509
|
return { success: true, output: snapshot };
|
|
@@ -14103,52 +14515,46 @@ class BrowserSession {
|
|
|
14103
14515
|
}
|
|
14104
14516
|
}
|
|
14105
14517
|
async back() {
|
|
14106
|
-
const err = await this.
|
|
14518
|
+
const err = await this.ensureDriver();
|
|
14107
14519
|
if (err)
|
|
14108
14520
|
return err;
|
|
14109
|
-
if (!this.
|
|
14521
|
+
if (!this.driver)
|
|
14110
14522
|
return { success: false, output: "No page" };
|
|
14111
|
-
await this.
|
|
14112
|
-
waitUntil: "domcontentloaded",
|
|
14113
|
-
timeout: this.config.navigationTimeout
|
|
14114
|
-
}).catch(() => {});
|
|
14523
|
+
await this.driver.goBack(this.config.navigationTimeout);
|
|
14115
14524
|
await new Promise((r) => setTimeout(r, 300));
|
|
14116
14525
|
const snapshot = await this.takeSnapshot();
|
|
14117
14526
|
return { success: true, output: snapshot };
|
|
14118
14527
|
}
|
|
14119
14528
|
async forward() {
|
|
14120
|
-
const err = await this.
|
|
14529
|
+
const err = await this.ensureDriver();
|
|
14121
14530
|
if (err)
|
|
14122
14531
|
return err;
|
|
14123
|
-
if (!this.
|
|
14532
|
+
if (!this.driver)
|
|
14124
14533
|
return { success: false, output: "No page" };
|
|
14125
|
-
await this.
|
|
14126
|
-
waitUntil: "domcontentloaded",
|
|
14127
|
-
timeout: this.config.navigationTimeout
|
|
14128
|
-
}).catch(() => {});
|
|
14534
|
+
await this.driver.goForward(this.config.navigationTimeout);
|
|
14129
14535
|
await new Promise((r) => setTimeout(r, 300));
|
|
14130
14536
|
const snapshot = await this.takeSnapshot();
|
|
14131
14537
|
return { success: true, output: snapshot };
|
|
14132
14538
|
}
|
|
14133
14539
|
async screenshot() {
|
|
14134
|
-
const err = await this.
|
|
14540
|
+
const err = await this.ensureDriver();
|
|
14135
14541
|
if (err)
|
|
14136
14542
|
return err;
|
|
14137
|
-
if (!this.
|
|
14543
|
+
if (!this.driver)
|
|
14138
14544
|
return { success: false, output: "No page" };
|
|
14139
|
-
const buffer = await this.
|
|
14545
|
+
const buffer = await this.driver.screenshot();
|
|
14140
14546
|
const snapshot = await this.takeSnapshot();
|
|
14141
14547
|
return { success: true, output: snapshot, screenshot: buffer };
|
|
14142
14548
|
}
|
|
14143
14549
|
async snapshot() {
|
|
14144
|
-
const err = await this.
|
|
14550
|
+
const err = await this.ensureDriver();
|
|
14145
14551
|
if (err)
|
|
14146
14552
|
return err;
|
|
14147
14553
|
const snap = await this.takeSnapshot();
|
|
14148
14554
|
return { success: true, output: snap };
|
|
14149
14555
|
}
|
|
14150
14556
|
async wait(ms) {
|
|
14151
|
-
const err = await this.
|
|
14557
|
+
const err = await this.ensureDriver();
|
|
14152
14558
|
if (err)
|
|
14153
14559
|
return err;
|
|
14154
14560
|
await new Promise((r) => setTimeout(r, Math.min(ms, 1e4)));
|
|
@@ -14157,51 +14563,34 @@ class BrowserSession {
|
|
|
14157
14563
|
}
|
|
14158
14564
|
async close() {
|
|
14159
14565
|
await this.saveCookies();
|
|
14160
|
-
if (this.
|
|
14161
|
-
await this.
|
|
14162
|
-
this.
|
|
14163
|
-
}
|
|
14164
|
-
if (this.context) {
|
|
14165
|
-
await this.context.close().catch(() => {});
|
|
14166
|
-
this.context = null;
|
|
14167
|
-
}
|
|
14168
|
-
if (this.browser) {
|
|
14169
|
-
await this.browser.close().catch(() => {});
|
|
14170
|
-
this.browser = null;
|
|
14566
|
+
if (this.driver) {
|
|
14567
|
+
await this.driver.close();
|
|
14568
|
+
this.driver = null;
|
|
14171
14569
|
}
|
|
14172
14570
|
this.state = { isOpen: false, url: null, title: null, elementCount: 0 };
|
|
14173
14571
|
return { success: true, output: t("browser.closed") };
|
|
14174
14572
|
}
|
|
14175
14573
|
}
|
|
14574
|
+
var CONSOLE_MAX_LINE = 400;
|
|
14176
14575
|
var init_session = __esm(() => {
|
|
14576
|
+
init_driver();
|
|
14177
14577
|
init_snapshot();
|
|
14178
14578
|
init_cookie_store();
|
|
14179
14579
|
init_i18n();
|
|
14180
14580
|
});
|
|
14181
14581
|
|
|
14182
|
-
// src/modules/browser/types.ts
|
|
14183
|
-
var DEFAULT_BROWSER_CONFIG;
|
|
14184
|
-
var init_types = __esm(() => {
|
|
14185
|
-
DEFAULT_BROWSER_CONFIG = {
|
|
14186
|
-
headless: true,
|
|
14187
|
-
maxElements: 30,
|
|
14188
|
-
screenshotMaxWidth: 1280,
|
|
14189
|
-
cookieDir: "",
|
|
14190
|
-
viewportWidth: 1280,
|
|
14191
|
-
viewportHeight: 720,
|
|
14192
|
-
navigationTimeout: 15000
|
|
14193
|
-
};
|
|
14194
|
-
});
|
|
14195
|
-
|
|
14196
14582
|
// src/tools/browser.ts
|
|
14197
|
-
import { join as
|
|
14583
|
+
import { join as join19 } from "path";
|
|
14198
14584
|
function getSession(ctx) {
|
|
14199
14585
|
if (!session) {
|
|
14200
|
-
const cookieDir =
|
|
14586
|
+
const cookieDir = join19(ctx.baseDir, ".mma", "browser");
|
|
14201
14587
|
session = new BrowserSession({
|
|
14202
14588
|
...DEFAULT_BROWSER_CONFIG,
|
|
14203
14589
|
headless: ctx.config.browser?.headless ?? true,
|
|
14204
14590
|
maxElements: ctx.config.browser?.maxElements ?? 30,
|
|
14591
|
+
maxContentChars: ctx.config.browser?.maxContentChars ?? 2500,
|
|
14592
|
+
maxConsoleEntries: ctx.config.browser?.maxConsoleEntries ?? 40,
|
|
14593
|
+
maxConsoleLineChars: ctx.config.browser?.maxConsoleLineChars ?? 400,
|
|
14205
14594
|
navigationTimeout: ctx.config.browser?.navigationTimeout ?? 15000,
|
|
14206
14595
|
viewportWidth: ctx.config.browser?.viewportWidth ?? 1280,
|
|
14207
14596
|
viewportHeight: ctx.config.browser?.viewportHeight ?? 720,
|
|
@@ -14230,7 +14619,8 @@ function createBrowserTool() {
|
|
|
14230
14619
|
tags: ["browser", "vision"],
|
|
14231
14620
|
description: [
|
|
14232
14621
|
"Control a headless browser. Navigate pages, click elements, type text, scroll, take screenshots.",
|
|
14233
|
-
"
|
|
14622
|
+
"Each snapshot returns: a numbered list of interactive elements, the visible page text (Content section), browser console messages, and network errors.",
|
|
14623
|
+
"Use the Content section to understand what the page says; use element numbers as targets for click/type.",
|
|
14234
14624
|
"Actions: open (url), click (target), type (target, text), scroll (direction), back, forward, screenshot, snapshot, close, wait (ms)."
|
|
14235
14625
|
].join(" "),
|
|
14236
14626
|
parameters: {
|
|
@@ -14327,8 +14717,8 @@ async function readClipboardFallback() {
|
|
|
14327
14717
|
const { platform: platform3 } = await import("os");
|
|
14328
14718
|
const { execSync } = await import("child_process");
|
|
14329
14719
|
const { readFileSync: readFileSync15, unlinkSync: unlinkSync4 } = await import("fs");
|
|
14330
|
-
const { join:
|
|
14331
|
-
const tmpPath =
|
|
14720
|
+
const { join: join20 } = await import("path");
|
|
14721
|
+
const tmpPath = join20(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
|
|
14332
14722
|
try {
|
|
14333
14723
|
if (platform3() === "linux") {
|
|
14334
14724
|
execSync(`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`, { timeout: 5000 });
|
|
@@ -14608,7 +14998,7 @@ class ModuleRegistry {
|
|
|
14608
14998
|
|
|
14609
14999
|
// src/modules/plugins/loader.ts
|
|
14610
15000
|
import { readdirSync as readdirSync7, existsSync as existsSync25, statSync as statSync5 } from "fs";
|
|
14611
|
-
import { join as
|
|
15001
|
+
import { join as join20 } from "path";
|
|
14612
15002
|
|
|
14613
15003
|
class PluginLoader {
|
|
14614
15004
|
loadFromDir(dirPath, pluginManager, logger) {
|
|
@@ -14616,7 +15006,7 @@ class PluginLoader {
|
|
|
14616
15006
|
return;
|
|
14617
15007
|
const entries = readdirSync7(dirPath);
|
|
14618
15008
|
for (const entry of entries) {
|
|
14619
|
-
const fullPath =
|
|
15009
|
+
const fullPath = join20(dirPath, entry);
|
|
14620
15010
|
if (!statSync5(fullPath).isFile())
|
|
14621
15011
|
continue;
|
|
14622
15012
|
if (!entry.endsWith(".ts") && !entry.endsWith(".js"))
|
|
@@ -14639,9 +15029,9 @@ var init_loader = __esm(() => {
|
|
|
14639
15029
|
});
|
|
14640
15030
|
|
|
14641
15031
|
// src/modules/plugins/builtin/lint-on-write.ts
|
|
14642
|
-
import { spawn as
|
|
15032
|
+
import { spawn as spawn5, execSync } from "child_process";
|
|
14643
15033
|
import { existsSync as existsSync26, readFileSync as readFileSync15 } from "fs";
|
|
14644
|
-
import { resolve as resolve16, extname as extname4, join as
|
|
15034
|
+
import { resolve as resolve16, extname as extname4, join as join21 } from "path";
|
|
14645
15035
|
import { platform as platform3 } from "os";
|
|
14646
15036
|
function contentHash(content) {
|
|
14647
15037
|
let h = 5381;
|
|
@@ -14743,7 +15133,7 @@ class LintOnWritePlugin {
|
|
|
14743
15133
|
}
|
|
14744
15134
|
async runProjectLint(ctx, result) {
|
|
14745
15135
|
try {
|
|
14746
|
-
const packageJsonPath =
|
|
15136
|
+
const packageJsonPath = join21(ctx.baseDir, "package.json");
|
|
14747
15137
|
if (!existsSync26(packageJsonPath)) {
|
|
14748
15138
|
return;
|
|
14749
15139
|
}
|
|
@@ -14763,7 +15153,7 @@ class LintOnWritePlugin {
|
|
|
14763
15153
|
}
|
|
14764
15154
|
}
|
|
14765
15155
|
async runProjectTypeCheck(ctx, result) {
|
|
14766
|
-
const tsconfigPath =
|
|
15156
|
+
const tsconfigPath = join21(ctx.baseDir, "tsconfig.json");
|
|
14767
15157
|
if (!existsSync26(tsconfigPath)) {
|
|
14768
15158
|
return;
|
|
14769
15159
|
}
|
|
@@ -14806,7 +15196,7 @@ class LintOnWritePlugin {
|
|
|
14806
15196
|
}
|
|
14807
15197
|
function runAsync(command, cwd, timeoutMs) {
|
|
14808
15198
|
return new Promise((resolve17, reject) => {
|
|
14809
|
-
const child =
|
|
15199
|
+
const child = spawn5(command, {
|
|
14810
15200
|
cwd,
|
|
14811
15201
|
shell: true,
|
|
14812
15202
|
windowsHide: true,
|
|
@@ -15007,7 +15397,7 @@ var init_tracker = () => {};
|
|
|
15007
15397
|
|
|
15008
15398
|
// src/modules/execution/auditor.ts
|
|
15009
15399
|
import { existsSync as existsSync27, readdirSync as readdirSync8 } from "fs";
|
|
15010
|
-
import { resolve as resolve17, join as
|
|
15400
|
+
import { resolve as resolve17, join as join22 } from "path";
|
|
15011
15401
|
function findTestFile(dir, depth = 0) {
|
|
15012
15402
|
if (depth > 5)
|
|
15013
15403
|
return null;
|
|
@@ -15018,7 +15408,7 @@ function findTestFile(dir, depth = 0) {
|
|
|
15018
15408
|
return null;
|
|
15019
15409
|
}
|
|
15020
15410
|
for (const e of entries) {
|
|
15021
|
-
const full =
|
|
15411
|
+
const full = join22(dir, e.name);
|
|
15022
15412
|
if (e.isDirectory()) {
|
|
15023
15413
|
if (SKIP_DIRS.has(e.name))
|
|
15024
15414
|
continue;
|
|
@@ -15178,7 +15568,7 @@ var init_auditor = __esm(() => {
|
|
|
15178
15568
|
|
|
15179
15569
|
// src/modules/execution/plan-store.ts
|
|
15180
15570
|
import { readFileSync as readFileSync16, writeFileSync as writeFileSync9, mkdirSync as mkdirSync13, existsSync as existsSync28, readdirSync as readdirSync9, rmSync } from "fs";
|
|
15181
|
-
import { join as
|
|
15571
|
+
import { join as join23 } from "path";
|
|
15182
15572
|
function readPlanFile(path, fallbackBaseDir) {
|
|
15183
15573
|
try {
|
|
15184
15574
|
const raw = readFileSync16(path, "utf-8");
|
|
@@ -15206,7 +15596,7 @@ function listDir(dir, baseDir) {
|
|
|
15206
15596
|
if (!existsSync28(dir))
|
|
15207
15597
|
return [];
|
|
15208
15598
|
const files = readdirSync9(dir).filter((f) => f.endsWith(".json"));
|
|
15209
|
-
return files.map((f) => readPlanFile(
|
|
15599
|
+
return files.map((f) => readPlanFile(join23(dir, f), baseDir)).filter((p) => p !== null);
|
|
15210
15600
|
}
|
|
15211
15601
|
function toMeta(plan, status) {
|
|
15212
15602
|
return {
|
|
@@ -15227,21 +15617,21 @@ class PlanStore {
|
|
|
15227
15617
|
archiveDir;
|
|
15228
15618
|
legacyPath;
|
|
15229
15619
|
constructor(baseDir) {
|
|
15230
|
-
const mmaDir =
|
|
15620
|
+
const mmaDir = join23(baseDir, ".mma");
|
|
15231
15621
|
if (!existsSync28(mmaDir))
|
|
15232
15622
|
mkdirSync13(mmaDir, { recursive: true });
|
|
15233
15623
|
this.baseDir = baseDir;
|
|
15234
|
-
this.plansDir =
|
|
15235
|
-
this.draftsDir =
|
|
15236
|
-
this.archiveDir =
|
|
15237
|
-
this.legacyPath =
|
|
15624
|
+
this.plansDir = join23(mmaDir, "plans");
|
|
15625
|
+
this.draftsDir = join23(this.plansDir, "drafts");
|
|
15626
|
+
this.archiveDir = join23(this.plansDir, "archive");
|
|
15627
|
+
this.legacyPath = join23(mmaDir, LEGACY_FILE);
|
|
15238
15628
|
for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
|
|
15239
15629
|
if (!existsSync28(dir))
|
|
15240
15630
|
mkdirSync13(dir, { recursive: true });
|
|
15241
15631
|
}
|
|
15242
15632
|
}
|
|
15243
15633
|
activePath() {
|
|
15244
|
-
return
|
|
15634
|
+
return join23(this.plansDir, "active.json");
|
|
15245
15635
|
}
|
|
15246
15636
|
saveActive(plan) {
|
|
15247
15637
|
writePlanFile(this.activePath(), plan);
|
|
@@ -15271,14 +15661,14 @@ class PlanStore {
|
|
|
15271
15661
|
rmSync(p, { force: true });
|
|
15272
15662
|
}
|
|
15273
15663
|
saveDraft(plan) {
|
|
15274
|
-
writePlanFile(
|
|
15664
|
+
writePlanFile(join23(this.draftsDir, `${plan.id}.json`), plan);
|
|
15275
15665
|
}
|
|
15276
15666
|
loadDraft(id) {
|
|
15277
|
-
const p =
|
|
15667
|
+
const p = join23(this.draftsDir, `${id}.json`);
|
|
15278
15668
|
return existsSync28(p) ? readPlanFile(p, this.baseDir) : null;
|
|
15279
15669
|
}
|
|
15280
15670
|
removeDraft(id) {
|
|
15281
|
-
const p =
|
|
15671
|
+
const p = join23(this.draftsDir, `${id}.json`);
|
|
15282
15672
|
if (existsSync28(p))
|
|
15283
15673
|
rmSync(p, { force: true });
|
|
15284
15674
|
}
|
|
@@ -15286,7 +15676,7 @@ class PlanStore {
|
|
|
15286
15676
|
return listDir(this.draftsDir, this.baseDir);
|
|
15287
15677
|
}
|
|
15288
15678
|
archivePlan(plan) {
|
|
15289
|
-
writePlanFile(
|
|
15679
|
+
writePlanFile(join23(this.archiveDir, `${plan.id}.json`), plan);
|
|
15290
15680
|
this.removeDraft(plan.id);
|
|
15291
15681
|
const active = this.loadActive();
|
|
15292
15682
|
if (active && active.id === plan.id) {
|
|
@@ -15297,7 +15687,7 @@ class PlanStore {
|
|
|
15297
15687
|
return listDir(this.archiveDir, this.baseDir);
|
|
15298
15688
|
}
|
|
15299
15689
|
removeArchived(id) {
|
|
15300
|
-
const p =
|
|
15690
|
+
const p = join23(this.archiveDir, `${id}.json`);
|
|
15301
15691
|
if (existsSync28(p))
|
|
15302
15692
|
rmSync(p, { force: true });
|
|
15303
15693
|
}
|
|
@@ -16164,7 +16554,7 @@ import {
|
|
|
16164
16554
|
readdirSync as readdirSync10,
|
|
16165
16555
|
unlinkSync as unlinkSync4
|
|
16166
16556
|
} from "fs";
|
|
16167
|
-
import { join as
|
|
16557
|
+
import { join as join24 } from "path";
|
|
16168
16558
|
import { homedir as homedir8 } from "os";
|
|
16169
16559
|
|
|
16170
16560
|
class SessionFileEncryptor {
|
|
@@ -16173,7 +16563,7 @@ class SessionFileEncryptor {
|
|
|
16173
16563
|
constructor(config) {
|
|
16174
16564
|
this.config = { ...DEFAULT_SESSION_ENCRYPTION, ...config };
|
|
16175
16565
|
this.encryptor = new ConfigEncryptor({
|
|
16176
|
-
keyPath: config?.keyPath ||
|
|
16566
|
+
keyPath: config?.keyPath || join24(homedir8(), ".mma", ".session-encryption-key")
|
|
16177
16567
|
});
|
|
16178
16568
|
}
|
|
16179
16569
|
isEnabled() {
|
|
@@ -16259,7 +16649,7 @@ class SessionFileEncryptor {
|
|
|
16259
16649
|
return;
|
|
16260
16650
|
const files = readdirSync10(sessionDir);
|
|
16261
16651
|
for (const file of files) {
|
|
16262
|
-
const filePath =
|
|
16652
|
+
const filePath = join24(sessionDir, file);
|
|
16263
16653
|
if (existsSync30(filePath) && !file.endsWith(".enc")) {
|
|
16264
16654
|
try {
|
|
16265
16655
|
const content = readFileSync18(filePath, "utf8");
|
|
@@ -16276,7 +16666,7 @@ class SessionFileEncryptor {
|
|
|
16276
16666
|
const files = readdirSync10(sessionDir);
|
|
16277
16667
|
for (const file of files) {
|
|
16278
16668
|
if (file.endsWith(".enc")) {
|
|
16279
|
-
const encFilePath =
|
|
16669
|
+
const encFilePath = join24(sessionDir, file);
|
|
16280
16670
|
const decFilePath = encFilePath.slice(0, -4);
|
|
16281
16671
|
try {
|
|
16282
16672
|
const content = readFileSync18(encFilePath, "utf8");
|
|
@@ -16309,7 +16699,7 @@ import {
|
|
|
16309
16699
|
writeFileSync as writeFileSync11,
|
|
16310
16700
|
appendFileSync as appendFileSync6
|
|
16311
16701
|
} from "fs";
|
|
16312
|
-
import { join as
|
|
16702
|
+
import { join as join25 } from "path";
|
|
16313
16703
|
import { gzipSync } from "zlib";
|
|
16314
16704
|
|
|
16315
16705
|
class SessionStore {
|
|
@@ -16323,7 +16713,7 @@ class SessionStore {
|
|
|
16323
16713
|
}
|
|
16324
16714
|
}
|
|
16325
16715
|
getSessionDir(id) {
|
|
16326
|
-
return
|
|
16716
|
+
return join25(this.baseDir, id);
|
|
16327
16717
|
}
|
|
16328
16718
|
updateEncryption(config) {
|
|
16329
16719
|
if (config?.enabled) {
|
|
@@ -16339,16 +16729,16 @@ class SessionStore {
|
|
|
16339
16729
|
mkdirSync14(this.baseDir, { recursive: true });
|
|
16340
16730
|
}
|
|
16341
16731
|
sessionDir(id) {
|
|
16342
|
-
return
|
|
16732
|
+
return join25(this.baseDir, id);
|
|
16343
16733
|
}
|
|
16344
16734
|
metaPath(id) {
|
|
16345
|
-
return
|
|
16735
|
+
return join25(this.sessionDir(id), "meta.json");
|
|
16346
16736
|
}
|
|
16347
16737
|
historyPath(id) {
|
|
16348
|
-
return
|
|
16738
|
+
return join25(this.sessionDir(id), "history.jsonl");
|
|
16349
16739
|
}
|
|
16350
16740
|
sessionLogPath(id) {
|
|
16351
|
-
return
|
|
16741
|
+
return join25(this.sessionDir(id), "session.jsonl");
|
|
16352
16742
|
}
|
|
16353
16743
|
sessionExists(id) {
|
|
16354
16744
|
return existsSync31(this.metaPath(id));
|
|
@@ -16502,7 +16892,7 @@ class SessionStore {
|
|
|
16502
16892
|
if (existsSync31(historyPath)) {
|
|
16503
16893
|
const content = readFileSync19(historyPath, "utf-8");
|
|
16504
16894
|
const compressed = gzipSync(content);
|
|
16505
|
-
const gzPath =
|
|
16895
|
+
const gzPath = join25(this.baseDir, `${session2.id}.jsonl.gz`);
|
|
16506
16896
|
writeFileSync11(gzPath, compressed);
|
|
16507
16897
|
rmSync2(historyPath);
|
|
16508
16898
|
}
|
|
@@ -16713,7 +17103,7 @@ class ProfileCompressor {
|
|
|
16713
17103
|
|
|
16714
17104
|
// src/modules/user-profile/profile.ts
|
|
16715
17105
|
import { readFileSync as readFileSync20, writeFileSync as writeFileSync12, existsSync as existsSync32, mkdirSync as mkdirSync15 } from "fs";
|
|
16716
|
-
import { join as
|
|
17106
|
+
import { join as join26 } from "path";
|
|
16717
17107
|
import { homedir as homedir9, hostname, platform as platform4, type } from "os";
|
|
16718
17108
|
import { env } from "process";
|
|
16719
17109
|
|
|
@@ -16740,10 +17130,10 @@ class UserProfile {
|
|
|
16740
17130
|
if (!existsSync32(this.profileDir)) {
|
|
16741
17131
|
mkdirSync15(this.profileDir, { recursive: true });
|
|
16742
17132
|
}
|
|
16743
|
-
writeFileSync12(
|
|
17133
|
+
writeFileSync12(join26(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
|
|
16744
17134
|
}
|
|
16745
17135
|
load() {
|
|
16746
|
-
const path =
|
|
17136
|
+
const path = join26(this.profileDir, "profile.json");
|
|
16747
17137
|
if (!existsSync32(path))
|
|
16748
17138
|
return null;
|
|
16749
17139
|
try {
|
|
@@ -16783,7 +17173,7 @@ var init_profile = () => {};
|
|
|
16783
17173
|
|
|
16784
17174
|
// src/modules/skills/loader.ts
|
|
16785
17175
|
import { readdirSync as readdirSync12, readFileSync as readFileSync21, existsSync as existsSync33, statSync as statSync6 } from "fs";
|
|
16786
|
-
import { join as
|
|
17176
|
+
import { join as join27 } from "path";
|
|
16787
17177
|
|
|
16788
17178
|
class SkillsLoader {
|
|
16789
17179
|
loadFromDir(dirPath) {
|
|
@@ -16796,7 +17186,7 @@ class SkillsLoader {
|
|
|
16796
17186
|
scanDir(dirPath, skills) {
|
|
16797
17187
|
const entries = readdirSync12(dirPath);
|
|
16798
17188
|
for (const entry of entries) {
|
|
16799
|
-
const fullPath =
|
|
17189
|
+
const fullPath = join27(dirPath, entry);
|
|
16800
17190
|
const stat = statSync6(fullPath);
|
|
16801
17191
|
if (stat.isDirectory()) {
|
|
16802
17192
|
this.scanDir(fullPath, skills);
|
|
@@ -17002,6 +17392,7 @@ class BrowserModule {
|
|
|
17002
17392
|
content: [
|
|
17003
17393
|
"You have a headless browser tool. Use it to navigate websites, click links, fill forms, and read page content.",
|
|
17004
17394
|
"Workflow: open(url) → read snapshot → click/type on element numbers → read updated snapshot.",
|
|
17395
|
+
'Each snapshot includes a "Content" section with the visible page text, a "Console" section with browser messages, and network errors. Use these to understand the page, detect JS errors, and verify the result of your actions.',
|
|
17005
17396
|
'Always start with "open" action. Use element numbers from snapshot for click/type targets.',
|
|
17006
17397
|
'Use "screenshot" action only if the model supports vision. Otherwise rely on the text snapshot.'
|
|
17007
17398
|
].join(`
|
|
@@ -17032,12 +17423,14 @@ var init_browser2 = __esm(() => {
|
|
|
17032
17423
|
init_module4();
|
|
17033
17424
|
init_session();
|
|
17034
17425
|
init_cookie_store();
|
|
17426
|
+
init_driver();
|
|
17427
|
+
init_bridge_client();
|
|
17035
17428
|
init_snapshot();
|
|
17036
17429
|
init_types();
|
|
17037
17430
|
});
|
|
17038
17431
|
|
|
17039
17432
|
// src/modules/lsp/client.ts
|
|
17040
|
-
import { spawn as
|
|
17433
|
+
import { spawn as spawn6, execSync as execSync2 } from "child_process";
|
|
17041
17434
|
import { resolve as resolve19 } from "path";
|
|
17042
17435
|
|
|
17043
17436
|
class LspClient {
|
|
@@ -17101,7 +17494,7 @@ class LspClient {
|
|
|
17101
17494
|
}
|
|
17102
17495
|
return new Promise((resolve20, reject) => {
|
|
17103
17496
|
const args = config.args ?? [];
|
|
17104
|
-
const proc =
|
|
17497
|
+
const proc = spawn6(config.command, args, {
|
|
17105
17498
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17106
17499
|
env: { ...process.env, ...config.env },
|
|
17107
17500
|
cwd: baseDir
|
|
@@ -17362,7 +17755,7 @@ var init_lsp = __esm(() => {
|
|
|
17362
17755
|
|
|
17363
17756
|
// src/modules/indexer/walker.ts
|
|
17364
17757
|
import { readdirSync as readdirSync13, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync35, watch } from "fs";
|
|
17365
|
-
import { join as
|
|
17758
|
+
import { join as join28, relative as relative2, extname as extname5 } from "path";
|
|
17366
17759
|
|
|
17367
17760
|
class Indexer {
|
|
17368
17761
|
baseDir;
|
|
@@ -17400,7 +17793,7 @@ class Indexer {
|
|
|
17400
17793
|
for (const entry of entries) {
|
|
17401
17794
|
if (count >= this.MAX_FILES)
|
|
17402
17795
|
return;
|
|
17403
|
-
const fullPath =
|
|
17796
|
+
const fullPath = join28(dir, entry);
|
|
17404
17797
|
const relPath = relative2(this.baseDir, fullPath);
|
|
17405
17798
|
const stat = statSync7(fullPath);
|
|
17406
17799
|
if (stat.isDirectory()) {
|
|
@@ -17464,13 +17857,13 @@ var init_walker = __esm(() => {
|
|
|
17464
17857
|
|
|
17465
17858
|
// src/modules/indexer/cache.ts
|
|
17466
17859
|
import { readFileSync as readFileSync23, writeFileSync as writeFileSync13, existsSync as existsSync36, mkdirSync as mkdirSync16, rmSync as rmSync3 } from "fs";
|
|
17467
|
-
import { join as
|
|
17860
|
+
import { join as join29 } from "path";
|
|
17468
17861
|
|
|
17469
17862
|
class IndexCache {
|
|
17470
17863
|
cachePath;
|
|
17471
17864
|
cache = null;
|
|
17472
17865
|
constructor(cacheDir) {
|
|
17473
|
-
this.cachePath =
|
|
17866
|
+
this.cachePath = join29(cacheDir, "index-cache.json");
|
|
17474
17867
|
}
|
|
17475
17868
|
load() {
|
|
17476
17869
|
if (this.cache)
|
|
@@ -17486,7 +17879,7 @@ class IndexCache {
|
|
|
17486
17879
|
}
|
|
17487
17880
|
save(result) {
|
|
17488
17881
|
this.cache = result;
|
|
17489
|
-
const dir =
|
|
17882
|
+
const dir = join29(this.cachePath, "..");
|
|
17490
17883
|
if (!existsSync36(dir))
|
|
17491
17884
|
mkdirSync16(dir, { recursive: true });
|
|
17492
17885
|
writeFileSync13(this.cachePath, JSON.stringify(result), "utf-8");
|
|
@@ -17503,7 +17896,7 @@ class IndexCache {
|
|
|
17503
17896
|
var init_cache = () => {};
|
|
17504
17897
|
|
|
17505
17898
|
// src/modules/indexer/module.ts
|
|
17506
|
-
import { dirname as
|
|
17899
|
+
import { dirname as dirname8 } from "path";
|
|
17507
17900
|
|
|
17508
17901
|
class IndexerModule {
|
|
17509
17902
|
name = "indexer";
|
|
@@ -17620,7 +18013,7 @@ ${t("indexer.and_more", { count: result.files.length - 100 })}` : "";
|
|
|
17620
18013
|
const counts = {};
|
|
17621
18014
|
for (const f of result.files) {
|
|
17622
18015
|
const normalized = f.path.replace(/\\/g, "/");
|
|
17623
|
-
const dir =
|
|
18016
|
+
const dir = dirname8(normalized);
|
|
17624
18017
|
const key = dir === "." ? "(root)" : dir;
|
|
17625
18018
|
counts[key] = (counts[key] || 0) + 1;
|
|
17626
18019
|
}
|
|
@@ -17851,13 +18244,13 @@ var init_mcp = __esm(() => {
|
|
|
17851
18244
|
|
|
17852
18245
|
// src/modules/memory/module.ts
|
|
17853
18246
|
import { homedir as homedir10 } from "os";
|
|
17854
|
-
import { join as
|
|
18247
|
+
import { join as join30 } from "path";
|
|
17855
18248
|
|
|
17856
18249
|
class MemoryModule {
|
|
17857
18250
|
name = "memory";
|
|
17858
18251
|
store;
|
|
17859
18252
|
constructor(memoryDir) {
|
|
17860
|
-
const dir = memoryDir ||
|
|
18253
|
+
const dir = memoryDir || join30(homedir10(), ".mma", "memory");
|
|
17861
18254
|
this.store = new MemoryStore(dir);
|
|
17862
18255
|
}
|
|
17863
18256
|
getSystemPromptBlock() {
|
|
@@ -17905,7 +18298,7 @@ __export(exports_bootstrap, {
|
|
|
17905
18298
|
bootstrap: () => bootstrap
|
|
17906
18299
|
});
|
|
17907
18300
|
import { homedir as homedir11 } from "os";
|
|
17908
|
-
import { join as
|
|
18301
|
+
import { join as join31, resolve as resolve21 } from "path";
|
|
17909
18302
|
import { existsSync as existsSync37, readFileSync as readFileSync24, writeFileSync as writeFileSync14 } from "fs";
|
|
17910
18303
|
function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
17911
18304
|
const now = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
@@ -17931,8 +18324,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
17931
18324
|
`);
|
|
17932
18325
|
}
|
|
17933
18326
|
async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
17934
|
-
const dir = configDir ||
|
|
17935
|
-
const projectConfigPath = projectDir ?
|
|
18327
|
+
const dir = configDir || join31(homedir11(), ".mma");
|
|
18328
|
+
const projectConfigPath = projectDir ? join31(projectDir, ".mmrc") : join31(process.cwd(), ".mmrc");
|
|
17936
18329
|
const config = loadConfig({ configDir: dir, projectConfigPath });
|
|
17937
18330
|
setLocale(config.locale);
|
|
17938
18331
|
try {
|
|
@@ -17942,7 +18335,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
17942
18335
|
}
|
|
17943
18336
|
} catch {}
|
|
17944
18337
|
const logger = new Logger(config.logLevel);
|
|
17945
|
-
logger.setLogDir(
|
|
18338
|
+
logger.setLogDir(join31(dir, "logs"));
|
|
17946
18339
|
logger.debug("MMA bootstrap", {
|
|
17947
18340
|
version: config.version,
|
|
17948
18341
|
model: config.model
|
|
@@ -17964,7 +18357,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
17964
18357
|
logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
|
|
17965
18358
|
}
|
|
17966
18359
|
}
|
|
17967
|
-
const profile = new UserProfile(
|
|
18360
|
+
const profile = new UserProfile(join31(dir));
|
|
17968
18361
|
profile.load() || profile.collect();
|
|
17969
18362
|
profile.save();
|
|
17970
18363
|
const llmProvider = new OpenAICompatProvider({
|
|
@@ -17976,7 +18369,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
17976
18369
|
rateLimits: config.security?.rateLimits
|
|
17977
18370
|
});
|
|
17978
18371
|
const baseDir = projectDir ? resolve21(projectDir) : process.cwd();
|
|
17979
|
-
const projectMapCacheDir =
|
|
18372
|
+
const projectMapCacheDir = join31(baseDir, ".mma");
|
|
17980
18373
|
const indexerModule = new IndexerModule({
|
|
17981
18374
|
baseDir,
|
|
17982
18375
|
cacheDir: projectMapCacheDir
|
|
@@ -17987,9 +18380,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
17987
18380
|
logger.warn(`Project indexing failed: ${err.message}`);
|
|
17988
18381
|
}
|
|
17989
18382
|
const skillsLoader = new SkillsLoader;
|
|
17990
|
-
const builtinDir =
|
|
17991
|
-
const globalDir =
|
|
17992
|
-
const projectSkillsDir =
|
|
18383
|
+
const builtinDir = join31(import.meta.dirname, "skills", "builtin");
|
|
18384
|
+
const globalDir = join31(homedir11(), ".agents", "skills");
|
|
18385
|
+
const projectSkillsDir = join31(baseDir, ".mma", "skills");
|
|
17993
18386
|
const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
|
|
17994
18387
|
const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
|
|
17995
18388
|
const skillsModule = new SkillsModule(availableSkills, skillsBudget);
|
|
@@ -18003,11 +18396,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18003
18396
|
essential: true,
|
|
18004
18397
|
estimatedTokens: Math.ceil(systemInfoContent.length / 4)
|
|
18005
18398
|
};
|
|
18006
|
-
const agentsMdGlobal =
|
|
18399
|
+
const agentsMdGlobal = join31(dir, "AGENTS.md");
|
|
18007
18400
|
if (!existsSync37(agentsMdGlobal)) {
|
|
18008
18401
|
writeFileSync14(agentsMdGlobal, "", "utf-8");
|
|
18009
18402
|
}
|
|
18010
|
-
const sessionDir =
|
|
18403
|
+
const sessionDir = join31(dir, "sessions");
|
|
18011
18404
|
const sessionStore = new SessionStore(sessionDir);
|
|
18012
18405
|
sessionStore.init();
|
|
18013
18406
|
const sessionManager = new SessionManager(sessionStore, {
|
|
@@ -18074,7 +18467,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18074
18467
|
const mcpModule = new MCPModule(config);
|
|
18075
18468
|
await mcpModule.initialize();
|
|
18076
18469
|
moduleRegistry.register(mcpModule);
|
|
18077
|
-
const memoryModule = new MemoryModule(
|
|
18470
|
+
const memoryModule = new MemoryModule(join31(dir, "memory"));
|
|
18078
18471
|
moduleRegistry.register(memoryModule);
|
|
18079
18472
|
if (config.browser.enabled) {
|
|
18080
18473
|
const browserModule = new BrowserModule;
|
|
@@ -18124,8 +18517,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18124
18517
|
pluginManager.register(plugin);
|
|
18125
18518
|
pluginManager.register(plugin2);
|
|
18126
18519
|
const pluginLoader = new PluginLoader;
|
|
18127
|
-
const globalPluginsDir =
|
|
18128
|
-
const projectPluginsDir =
|
|
18520
|
+
const globalPluginsDir = join31(homedir11(), ".mma", "plugins");
|
|
18521
|
+
const projectPluginsDir = join31(baseDir, ".mma", "plugins");
|
|
18129
18522
|
pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger);
|
|
18130
18523
|
pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger);
|
|
18131
18524
|
contextManager.onCompact = (summary) => {
|
|
@@ -18143,9 +18536,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18143
18536
|
const skipAgentsMd = noAgentsMd === true;
|
|
18144
18537
|
if (!skipAgentsMd) {
|
|
18145
18538
|
const agentsMdCandidates = [
|
|
18146
|
-
|
|
18147
|
-
|
|
18148
|
-
|
|
18539
|
+
join31(baseDir, "AGENTS.md"),
|
|
18540
|
+
join31(baseDir, ".mma", "AGENTS.md"),
|
|
18541
|
+
join31(dir, "AGENTS.md")
|
|
18149
18542
|
];
|
|
18150
18543
|
for (const p of agentsMdCandidates) {
|
|
18151
18544
|
if (existsSync37(p)) {
|
|
@@ -19000,7 +19393,7 @@ __export(exports_manifest, {
|
|
|
19000
19393
|
});
|
|
19001
19394
|
import { existsSync as existsSync38, readFileSync as readFileSync25, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
19002
19395
|
import { homedir as homedir13 } from "os";
|
|
19003
|
-
import { join as
|
|
19396
|
+
import { join as join33 } from "path";
|
|
19004
19397
|
function readManifest(path = MANIFEST_PATH) {
|
|
19005
19398
|
try {
|
|
19006
19399
|
if (existsSync38(path)) {
|
|
@@ -19011,7 +19404,7 @@ function readManifest(path = MANIFEST_PATH) {
|
|
|
19011
19404
|
return { version: 1, certifications: [] };
|
|
19012
19405
|
}
|
|
19013
19406
|
function saveManifest(m, path = MANIFEST_PATH) {
|
|
19014
|
-
mkdirSync17(
|
|
19407
|
+
mkdirSync17(join33(homedir13(), ".mma"), { recursive: true });
|
|
19015
19408
|
writeFileSync15(path, JSON.stringify(m, null, 2), "utf-8");
|
|
19016
19409
|
}
|
|
19017
19410
|
function upsertCertification(entry, path = MANIFEST_PATH) {
|
|
@@ -19046,7 +19439,7 @@ function getCertMark(model, providerUrl, currentVersion, path = MANIFEST_PATH) {
|
|
|
19046
19439
|
}
|
|
19047
19440
|
var MANIFEST_PATH;
|
|
19048
19441
|
var init_manifest = __esm(() => {
|
|
19049
|
-
MANIFEST_PATH =
|
|
19442
|
+
MANIFEST_PATH = join33(homedir13(), ".mma", "certifications.json");
|
|
19050
19443
|
});
|
|
19051
19444
|
|
|
19052
19445
|
// node_modules/yaml/dist/nodes/identity.js
|
|
@@ -26170,7 +26563,7 @@ var init_scenarios = __esm(() => {
|
|
|
26170
26563
|
|
|
26171
26564
|
// src/modules/certification/loader.ts
|
|
26172
26565
|
import { existsSync as existsSync39, readdirSync as readdirSync14, readFileSync as readFileSync26 } from "fs";
|
|
26173
|
-
import { join as
|
|
26566
|
+
import { join as join34 } from "path";
|
|
26174
26567
|
function validateScenario(s) {
|
|
26175
26568
|
const errors2 = [];
|
|
26176
26569
|
const isSkip = s.mode === "skip";
|
|
@@ -26224,7 +26617,7 @@ function loadScenarios(userDir) {
|
|
|
26224
26617
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
|
|
26225
26618
|
continue;
|
|
26226
26619
|
try {
|
|
26227
|
-
const raw = readFileSync26(
|
|
26620
|
+
const raw = readFileSync26(join34(userDir, file), "utf-8");
|
|
26228
26621
|
const data = $parse(raw);
|
|
26229
26622
|
const parsed = normalizeScenario(data, file);
|
|
26230
26623
|
const errs = validateScenario(parsed);
|
|
@@ -26278,7 +26671,7 @@ var init_loader3 = __esm(() => {
|
|
|
26278
26671
|
|
|
26279
26672
|
// src/modules/certification/fact-checker.ts
|
|
26280
26673
|
import { existsSync as existsSync40, readFileSync as readFileSync27, statSync as statSync8 } from "fs";
|
|
26281
|
-
import { join as
|
|
26674
|
+
import { join as join35 } from "path";
|
|
26282
26675
|
function checkSandbox(sandboxDir, checks, exitCode, output) {
|
|
26283
26676
|
const failures = [];
|
|
26284
26677
|
for (const check of checks) {
|
|
@@ -26295,13 +26688,13 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
26295
26688
|
case "outputContains":
|
|
26296
26689
|
return output.includes(check.text);
|
|
26297
26690
|
case "fileExists":
|
|
26298
|
-
return isFile(
|
|
26691
|
+
return isFile(join35(sandboxDir, check.path));
|
|
26299
26692
|
case "fileNotExists":
|
|
26300
|
-
return !existsSync40(
|
|
26693
|
+
return !existsSync40(join35(sandboxDir, check.path));
|
|
26301
26694
|
case "dirExists":
|
|
26302
|
-
return isDir(
|
|
26695
|
+
return isDir(join35(sandboxDir, check.path));
|
|
26303
26696
|
case "fileContent": {
|
|
26304
|
-
const abs =
|
|
26697
|
+
const abs = join35(sandboxDir, check.path);
|
|
26305
26698
|
if (!isFile(abs))
|
|
26306
26699
|
return false;
|
|
26307
26700
|
const content = readFileSync27(abs, "utf-8");
|
|
@@ -26312,7 +26705,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
26312
26705
|
return false;
|
|
26313
26706
|
}
|
|
26314
26707
|
case "fileRegex": {
|
|
26315
|
-
const abs =
|
|
26708
|
+
const abs = join35(sandboxDir, check.path);
|
|
26316
26709
|
if (!isFile(abs))
|
|
26317
26710
|
return false;
|
|
26318
26711
|
return new RegExp(check.pattern).test(readFileSync27(abs, "utf-8"));
|
|
@@ -26360,10 +26753,10 @@ function describe(check) {
|
|
|
26360
26753
|
var init_fact_checker = () => {};
|
|
26361
26754
|
|
|
26362
26755
|
// src/modules/certification/runner.ts
|
|
26363
|
-
import { spawn as
|
|
26756
|
+
import { spawn as spawn7 } from "child_process";
|
|
26364
26757
|
import { existsSync as existsSync41, mkdirSync as mkdirSync18, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
|
|
26365
26758
|
import { platform as platform5 } from "os";
|
|
26366
|
-
import { join as
|
|
26759
|
+
import { join as join36, resolve as resolve22, dirname as dirname9 } from "path";
|
|
26367
26760
|
async function runScenario(scenario, opts) {
|
|
26368
26761
|
if (scenario.mode === "skip") {
|
|
26369
26762
|
return {
|
|
@@ -26382,7 +26775,7 @@ async function runScenario(scenario, opts) {
|
|
|
26382
26775
|
let passed = 0;
|
|
26383
26776
|
let firstError;
|
|
26384
26777
|
for (let i = 1;i <= reps; i++) {
|
|
26385
|
-
const sandbox =
|
|
26778
|
+
const sandbox = join36(opts.sandboxBase, `run-${scenario.id}-${i}`);
|
|
26386
26779
|
let failures = [];
|
|
26387
26780
|
let exitCode = -1;
|
|
26388
26781
|
let output = "";
|
|
@@ -26443,20 +26836,20 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
|
|
|
26443
26836
|
rmSync4(sandbox, { recursive: true, force: true });
|
|
26444
26837
|
mkdirSync18(sandbox, { recursive: true });
|
|
26445
26838
|
for (const f of scenario.fixtures ?? []) {
|
|
26446
|
-
const src =
|
|
26839
|
+
const src = join36(mmaRoot, f.source);
|
|
26447
26840
|
if (!existsSync41(src)) {
|
|
26448
26841
|
throw new Error(`fixture missing: ${f.source}`);
|
|
26449
26842
|
}
|
|
26450
|
-
const dest =
|
|
26451
|
-
mkdirSync18(
|
|
26843
|
+
const dest = join36(sandbox, f.dest);
|
|
26844
|
+
mkdirSync18(dirname9(dest), { recursive: true });
|
|
26452
26845
|
cpSync2(src, dest);
|
|
26453
26846
|
}
|
|
26454
26847
|
}
|
|
26455
26848
|
function resolveMmaEntry(mmaRoot) {
|
|
26456
|
-
const dev =
|
|
26849
|
+
const dev = join36(mmaRoot, "src", "cli", "main.ts");
|
|
26457
26850
|
if (existsSync41(dev))
|
|
26458
26851
|
return dev;
|
|
26459
|
-
return
|
|
26852
|
+
return join36(mmaRoot, "dist", "main.js");
|
|
26460
26853
|
}
|
|
26461
26854
|
function findMmaRoot(fromDir) {
|
|
26462
26855
|
const candidates = [
|
|
@@ -26464,7 +26857,7 @@ function findMmaRoot(fromDir) {
|
|
|
26464
26857
|
resolve22(fromDir, "..")
|
|
26465
26858
|
];
|
|
26466
26859
|
for (const c of candidates) {
|
|
26467
|
-
if (existsSync41(
|
|
26860
|
+
if (existsSync41(join36(c, "package.json")))
|
|
26468
26861
|
return c;
|
|
26469
26862
|
}
|
|
26470
26863
|
return process.cwd();
|
|
@@ -26474,7 +26867,7 @@ function killTree2(child) {
|
|
|
26474
26867
|
if (!pid)
|
|
26475
26868
|
return;
|
|
26476
26869
|
if (platform5() === "win32") {
|
|
26477
|
-
|
|
26870
|
+
spawn7("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
26478
26871
|
windowsHide: true,
|
|
26479
26872
|
stdio: "ignore"
|
|
26480
26873
|
});
|
|
@@ -26489,7 +26882,7 @@ function killTree2(child) {
|
|
|
26489
26882
|
}
|
|
26490
26883
|
}
|
|
26491
26884
|
var defaultRunner = (env2, cwd, args, timeoutMs) => new Promise((resolvePromise) => {
|
|
26492
|
-
const child =
|
|
26885
|
+
const child = spawn7(process.execPath, args, {
|
|
26493
26886
|
cwd,
|
|
26494
26887
|
env: env2,
|
|
26495
26888
|
windowsHide: true,
|
|
@@ -26532,11 +26925,11 @@ __export(exports_cli, {
|
|
|
26532
26925
|
});
|
|
26533
26926
|
import { rmSync as rmSync5 } from "fs";
|
|
26534
26927
|
import { homedir as homedir14 } from "os";
|
|
26535
|
-
import { join as
|
|
26536
|
-
import { fileURLToPath } from "url";
|
|
26928
|
+
import { join as join37, dirname as dirname10 } from "path";
|
|
26929
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
26537
26930
|
import { existsSync as existsSync42, readFileSync as readFileSync28 } from "fs";
|
|
26538
26931
|
function readVersion() {
|
|
26539
|
-
const candidates = [
|
|
26932
|
+
const candidates = [join37(MMA_ROOT, "package.json")];
|
|
26540
26933
|
for (const p of candidates) {
|
|
26541
26934
|
if (existsSync42(p)) {
|
|
26542
26935
|
try {
|
|
@@ -26576,7 +26969,7 @@ async function certify(opts) {
|
|
|
26576
26969
|
return;
|
|
26577
26970
|
}
|
|
26578
26971
|
console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
|
|
26579
|
-
const sandboxBase =
|
|
26972
|
+
const sandboxBase = join37(process.cwd(), ".mma", "certification");
|
|
26580
26973
|
const results = [];
|
|
26581
26974
|
const total = selected.length;
|
|
26582
26975
|
let idx = 0;
|
|
@@ -26688,9 +27081,9 @@ var init_cli = __esm(() => {
|
|
|
26688
27081
|
init_loader3();
|
|
26689
27082
|
init_runner2();
|
|
26690
27083
|
init_manifest();
|
|
26691
|
-
HERE =
|
|
27084
|
+
HERE = dirname10(fileURLToPath2(import.meta.url));
|
|
26692
27085
|
MMA_ROOT = findMmaRoot(HERE);
|
|
26693
|
-
USER_SCENARIO_DIR =
|
|
27086
|
+
USER_SCENARIO_DIR = join37(homedir14(), ".mma", "certification", "scenarios");
|
|
26694
27087
|
});
|
|
26695
27088
|
|
|
26696
27089
|
// src/cli/repl-commands.ts
|
|
@@ -26699,15 +27092,15 @@ __export(exports_repl_commands, {
|
|
|
26699
27092
|
registerAllCommands: () => registerAllCommands,
|
|
26700
27093
|
COMMAND_GROUPS: () => COMMAND_GROUPS
|
|
26701
27094
|
});
|
|
26702
|
-
import { join as
|
|
27095
|
+
import { join as join39, dirname as dirname12 } from "path";
|
|
26703
27096
|
import { homedir as homedir16 } from "os";
|
|
26704
27097
|
import { existsSync as existsSync44, readFileSync as readFileSync30 } from "fs";
|
|
26705
|
-
import { fileURLToPath as
|
|
27098
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
26706
27099
|
function readVersion3() {
|
|
26707
|
-
const here =
|
|
27100
|
+
const here = dirname12(fileURLToPath4(import.meta.url));
|
|
26708
27101
|
const candidates = [
|
|
26709
|
-
|
|
26710
|
-
|
|
27102
|
+
join39(here, "..", "..", "package.json"),
|
|
27103
|
+
join39(here, "..", "package.json")
|
|
26711
27104
|
];
|
|
26712
27105
|
for (const p of candidates) {
|
|
26713
27106
|
if (existsSync44(p)) {
|
|
@@ -26875,7 +27268,7 @@ function registerMmaCommands(ctx) {
|
|
|
26875
27268
|
console.log(pc2.yellow(t("repl.wizard_running")));
|
|
26876
27269
|
await ctx.withExclusiveInput(async () => {
|
|
26877
27270
|
const answers = await runSetup(ctx.rl);
|
|
26878
|
-
const configPath =
|
|
27271
|
+
const configPath = join39(homedir16(), ".mma", "config.json");
|
|
26879
27272
|
ctx.config.provider.type = answers.provider;
|
|
26880
27273
|
ctx.config.provider.baseUrl = answers.apiBase;
|
|
26881
27274
|
ctx.config.provider.apiKey = answers.apiKey;
|
|
@@ -26929,7 +27322,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
26929
27322
|
return;
|
|
26930
27323
|
}
|
|
26931
27324
|
ctx.config.provider.type = name;
|
|
26932
|
-
const configPath =
|
|
27325
|
+
const configPath = join39(homedir16(), ".mma", "config.json");
|
|
26933
27326
|
saveConfig(ctx.config, configPath);
|
|
26934
27327
|
await ctx.agent.reconfigure(ctx.config);
|
|
26935
27328
|
console.log(pc2.green(t("repl.provider_set", { name })));
|
|
@@ -26985,7 +27378,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
26985
27378
|
return;
|
|
26986
27379
|
}
|
|
26987
27380
|
ctx.config.model = name;
|
|
26988
|
-
const configPath =
|
|
27381
|
+
const configPath = join39(homedir16(), ".mma", "config.json");
|
|
26989
27382
|
saveConfig(ctx.config, configPath);
|
|
26990
27383
|
await ctx.agent.reconfigure(ctx.config);
|
|
26991
27384
|
console.log(pc2.green(t("repl.model_set", { name })));
|
|
@@ -27010,7 +27403,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
27010
27403
|
return;
|
|
27011
27404
|
}
|
|
27012
27405
|
ctx.config.contextWindow = size;
|
|
27013
|
-
const configPath =
|
|
27406
|
+
const configPath = join39(homedir16(), ".mma", "config.json");
|
|
27014
27407
|
saveConfig(ctx.config, configPath);
|
|
27015
27408
|
await ctx.agent.reconfigure(ctx.config);
|
|
27016
27409
|
console.log(pc2.green(t("cli.context_set", { size })));
|
|
@@ -27029,10 +27422,10 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
27029
27422
|
ctx.agent.shutdown();
|
|
27030
27423
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
27031
27424
|
const { homedir: homedir17 } = await import("os");
|
|
27032
|
-
const { join:
|
|
27425
|
+
const { join: join40 } = await import("path");
|
|
27033
27426
|
const configDir = ctx.configDir;
|
|
27034
27427
|
const baseDir = ctx.baseDir;
|
|
27035
|
-
const projectConfigPath =
|
|
27428
|
+
const projectConfigPath = join40(baseDir, ".mmrc");
|
|
27036
27429
|
const freshConfig = loadConfig2({ configDir, projectConfigPath });
|
|
27037
27430
|
Object.assign(ctx.config, freshConfig);
|
|
27038
27431
|
const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
|
|
@@ -27332,14 +27725,14 @@ init_bootstrap();
|
|
|
27332
27725
|
init_config2();
|
|
27333
27726
|
init_setup();
|
|
27334
27727
|
init_i18n();
|
|
27335
|
-
import { join as
|
|
27728
|
+
import { join as join38, dirname as dirname11 } from "path";
|
|
27336
27729
|
import { homedir as homedir15 } from "os";
|
|
27337
27730
|
import { existsSync as existsSync43, readFileSync as readFileSync29 } from "fs";
|
|
27338
27731
|
|
|
27339
27732
|
// src/cli/security-commands.ts
|
|
27340
27733
|
init_bootstrap();
|
|
27341
27734
|
init_config2();
|
|
27342
|
-
import { join as
|
|
27735
|
+
import { join as join32 } from "path";
|
|
27343
27736
|
import { homedir as homedir12 } from "os";
|
|
27344
27737
|
|
|
27345
27738
|
// src/modules/security/security-policies.ts
|
|
@@ -27869,7 +28262,7 @@ function createSecurityCommand(program2) {
|
|
|
27869
28262
|
}
|
|
27870
28263
|
});
|
|
27871
28264
|
securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
|
|
27872
|
-
const configPath =
|
|
28265
|
+
const configPath = join32(homedir12(), ".mma", "config.json");
|
|
27873
28266
|
const { config: appConfig } = await bootstrap();
|
|
27874
28267
|
const validPresets = ["strict", "balanced", "permissive"];
|
|
27875
28268
|
if (!validPresets.includes(preset)) {
|
|
@@ -27884,7 +28277,7 @@ function createSecurityCommand(program2) {
|
|
|
27884
28277
|
console.log(t("cli.security.policy_description", { description: policy.description }));
|
|
27885
28278
|
});
|
|
27886
28279
|
securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
|
|
27887
|
-
const configPath =
|
|
28280
|
+
const configPath = join32(homedir12(), ".mma", "config.json");
|
|
27888
28281
|
const { config: appConfig } = await bootstrap();
|
|
27889
28282
|
appConfig.security = appConfig.security || {};
|
|
27890
28283
|
appConfig.security.sessionEncryption = {
|
|
@@ -27896,7 +28289,7 @@ function createSecurityCommand(program2) {
|
|
|
27896
28289
|
console.log(t("cli.security.encryption_enabled"));
|
|
27897
28290
|
});
|
|
27898
28291
|
securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
|
|
27899
|
-
const configPath =
|
|
28292
|
+
const configPath = join32(homedir12(), ".mma", "config.json");
|
|
27900
28293
|
const { config: appConfig } = await bootstrap();
|
|
27901
28294
|
appConfig.security = appConfig.security || {};
|
|
27902
28295
|
appConfig.security.sessionEncryption = {
|
|
@@ -27908,7 +28301,7 @@ function createSecurityCommand(program2) {
|
|
|
27908
28301
|
console.log(t("cli.security.encryption_disabled"));
|
|
27909
28302
|
});
|
|
27910
28303
|
securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
|
|
27911
|
-
const configPath =
|
|
28304
|
+
const configPath = join32(homedir12(), ".mma", "config.json");
|
|
27912
28305
|
const { config: appConfig } = await bootstrap();
|
|
27913
28306
|
appConfig.security = appConfig.security || {};
|
|
27914
28307
|
appConfig.security.auditNotifier = {
|
|
@@ -27922,7 +28315,7 @@ function createSecurityCommand(program2) {
|
|
|
27922
28315
|
console.log(t("cli.security.audit_enabled"));
|
|
27923
28316
|
});
|
|
27924
28317
|
securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
|
|
27925
|
-
const configPath =
|
|
28318
|
+
const configPath = join32(homedir12(), ".mma", "config.json");
|
|
27926
28319
|
const { config: appConfig } = await bootstrap();
|
|
27927
28320
|
appConfig.security = appConfig.security || {};
|
|
27928
28321
|
appConfig.security.auditNotifier = {
|
|
@@ -27954,12 +28347,12 @@ function createSecurityCommand(program2) {
|
|
|
27954
28347
|
}
|
|
27955
28348
|
|
|
27956
28349
|
// src/cli/commands.ts
|
|
27957
|
-
import { fileURLToPath as
|
|
28350
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
27958
28351
|
function readVersion2() {
|
|
27959
|
-
const here =
|
|
28352
|
+
const here = dirname11(fileURLToPath3(import.meta.url));
|
|
27960
28353
|
const candidates = [
|
|
27961
|
-
|
|
27962
|
-
|
|
28354
|
+
join38(here, "..", "..", "package.json"),
|
|
28355
|
+
join38(here, "..", "package.json")
|
|
27963
28356
|
];
|
|
27964
28357
|
for (const p of candidates) {
|
|
27965
28358
|
if (existsSync43(p)) {
|
|
@@ -27977,7 +28370,7 @@ function createProgram() {
|
|
|
27977
28370
|
const program2 = new Command().name("mma").description(t("cli.description")).version(version).option("--no-agents-md", t("cli.no_agents_md")).option("-d, --dir <path>", t("cli.dir")).option("-e, --exit-on-complete", t("cli.exit_on_complete")).option("-j, --json", t("cli.json"));
|
|
27978
28371
|
program2.command("init").description(t("cli.init")).action(async () => {
|
|
27979
28372
|
const answers = await runSetup();
|
|
27980
|
-
const configPath =
|
|
28373
|
+
const configPath = join38(homedir15(), ".mma", "config.json");
|
|
27981
28374
|
const { config } = await bootstrap();
|
|
27982
28375
|
config.provider.type = answers.provider;
|
|
27983
28376
|
config.provider.baseUrl = answers.apiBase;
|
|
@@ -28022,7 +28415,7 @@ function createProgram() {
|
|
|
28022
28415
|
});
|
|
28023
28416
|
const configCmd = program2.command("config").description(t("cli.manage_config"));
|
|
28024
28417
|
configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
|
|
28025
|
-
const configPath =
|
|
28418
|
+
const configPath = join38(homedir15(), ".mma", "config.json");
|
|
28026
28419
|
const { config } = await bootstrap();
|
|
28027
28420
|
const keys = key.split(".");
|
|
28028
28421
|
let obj = config;
|
|
@@ -28085,7 +28478,7 @@ function createProgram() {
|
|
|
28085
28478
|
console.log(t("cli.model_hint"));
|
|
28086
28479
|
});
|
|
28087
28480
|
model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
|
|
28088
|
-
const configPath =
|
|
28481
|
+
const configPath = join38(homedir15(), ".mma", "config.json");
|
|
28089
28482
|
const { config } = await bootstrap();
|
|
28090
28483
|
config.model = name;
|
|
28091
28484
|
saveConfig(config, configPath);
|
|
@@ -28121,7 +28514,7 @@ function createProgram() {
|
|
|
28121
28514
|
await uncertify2(name, config);
|
|
28122
28515
|
});
|
|
28123
28516
|
program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
|
|
28124
|
-
const configPath =
|
|
28517
|
+
const configPath = join38(homedir15(), ".mma", "config.json");
|
|
28125
28518
|
const { config } = await bootstrap();
|
|
28126
28519
|
const contextWindow = parseInt(size, 10);
|
|
28127
28520
|
if (isNaN(contextWindow) || contextWindow < 1024) {
|
|
@@ -28139,7 +28532,7 @@ function createProgram() {
|
|
|
28139
28532
|
console.log(t("cli.base_url"), config.provider.baseUrl);
|
|
28140
28533
|
});
|
|
28141
28534
|
provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
|
|
28142
|
-
const configPath =
|
|
28535
|
+
const configPath = join38(homedir15(), ".mma", "config.json");
|
|
28143
28536
|
const { config } = await bootstrap();
|
|
28144
28537
|
config.provider.type = name;
|
|
28145
28538
|
saveConfig(config, configPath);
|
|
@@ -28192,9 +28585,9 @@ init_bootstrap();
|
|
|
28192
28585
|
init_colors();
|
|
28193
28586
|
import * as readline2 from "readline";
|
|
28194
28587
|
import { existsSync as existsSync45, readFileSync as readFileSync31, writeFileSync as writeFileSync16 } from "fs";
|
|
28195
|
-
import { join as
|
|
28588
|
+
import { join as join40, dirname as dirname13 } from "path";
|
|
28196
28589
|
import { homedir as homedir17 } from "os";
|
|
28197
|
-
import { fileURLToPath as
|
|
28590
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
28198
28591
|
|
|
28199
28592
|
// src/cli/completer.ts
|
|
28200
28593
|
class SlashCommandProvider {
|
|
@@ -28704,10 +29097,10 @@ init_box();
|
|
|
28704
29097
|
init_i18n();
|
|
28705
29098
|
init_repl_commands();
|
|
28706
29099
|
function readVersion4() {
|
|
28707
|
-
const here =
|
|
29100
|
+
const here = dirname13(fileURLToPath5(import.meta.url));
|
|
28708
29101
|
const candidates = [
|
|
28709
|
-
|
|
28710
|
-
|
|
29102
|
+
join40(here, "..", "..", "package.json"),
|
|
29103
|
+
join40(here, "..", "package.json")
|
|
28711
29104
|
];
|
|
28712
29105
|
for (const p of candidates) {
|
|
28713
29106
|
if (existsSync45(p)) {
|
|
@@ -28766,10 +29159,10 @@ class Repl {
|
|
|
28766
29159
|
this.skillsModule = skillsModule;
|
|
28767
29160
|
this.pluginManager = pluginManager;
|
|
28768
29161
|
this.logger = logger;
|
|
28769
|
-
this.configDir = configDir ||
|
|
29162
|
+
this.configDir = configDir || join40(homedir17(), ".mma");
|
|
28770
29163
|
this.baseDir = baseDir || process.cwd();
|
|
28771
29164
|
this.noAgentsMd = noAgentsMd === true;
|
|
28772
|
-
this.historyPath =
|
|
29165
|
+
this.historyPath = join40(homedir17(), ".mma", "repl-history");
|
|
28773
29166
|
this.loadHistory();
|
|
28774
29167
|
this.rl = readline2.createInterface({
|
|
28775
29168
|
input: process.stdin,
|
|
@@ -29123,9 +29516,9 @@ ${t("image.clipboard_empty")}`));
|
|
|
29123
29516
|
row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
|
|
29124
29517
|
} else {
|
|
29125
29518
|
const agentsMdCandidates = [
|
|
29126
|
-
|
|
29127
|
-
|
|
29128
|
-
|
|
29519
|
+
join40(this.baseDir, "AGENTS.md"),
|
|
29520
|
+
join40(this.baseDir, ".mma", "AGENTS.md"),
|
|
29521
|
+
join40(this.configDir, "AGENTS.md")
|
|
29129
29522
|
];
|
|
29130
29523
|
const foundAgents = agentsMdCandidates.filter((p) => existsSync45(p));
|
|
29131
29524
|
if (foundAgents.length > 0) {
|
|
@@ -29138,7 +29531,7 @@ ${t("image.clipboard_empty")}`));
|
|
|
29138
29531
|
}
|
|
29139
29532
|
const meta = this.sessionManager?.getActiveMeta();
|
|
29140
29533
|
if (meta) {
|
|
29141
|
-
const sessionPath =
|
|
29534
|
+
const sessionPath = join40(this.configDir, "sessions", meta.id);
|
|
29142
29535
|
row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
|
|
29143
29536
|
}
|
|
29144
29537
|
const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
|
|
@@ -29165,9 +29558,9 @@ init_config2();
|
|
|
29165
29558
|
init_i18n();
|
|
29166
29559
|
init_colors();
|
|
29167
29560
|
import { existsSync as existsSync46, readFileSync as readFileSync32 } from "fs";
|
|
29168
|
-
import { join as
|
|
29561
|
+
import { join as join41, dirname as dirname14 } from "path";
|
|
29169
29562
|
import { homedir as homedir18 } from "os";
|
|
29170
|
-
import { fileURLToPath as
|
|
29563
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
29171
29564
|
|
|
29172
29565
|
// src/modules/updater/checker.ts
|
|
29173
29566
|
var defaultRunner2 = async (command, args, options) => {
|
|
@@ -29316,10 +29709,10 @@ class UpdaterModule {
|
|
|
29316
29709
|
}
|
|
29317
29710
|
// src/cli/main.ts
|
|
29318
29711
|
function readVersion5() {
|
|
29319
|
-
const here =
|
|
29712
|
+
const here = dirname14(fileURLToPath6(import.meta.url));
|
|
29320
29713
|
const candidates = [
|
|
29321
|
-
|
|
29322
|
-
|
|
29714
|
+
join41(here, "..", "..", "package.json"),
|
|
29715
|
+
join41(here, "..", "package.json")
|
|
29323
29716
|
];
|
|
29324
29717
|
for (const p of candidates) {
|
|
29325
29718
|
if (existsSync46(p)) {
|
|
@@ -29404,15 +29797,15 @@ async function main() {
|
|
|
29404
29797
|
}
|
|
29405
29798
|
agent.shutdown();
|
|
29406
29799
|
} else {
|
|
29407
|
-
const configPath =
|
|
29800
|
+
const configPath = join41(homedir18(), ".mma", "config.json");
|
|
29408
29801
|
if (!existsSync46(configPath)) {
|
|
29409
29802
|
console.log(pc2.yellow(`
|
|
29410
29803
|
` + t("cli.first_run") + `
|
|
29411
29804
|
`));
|
|
29412
29805
|
const answers = await runSetup();
|
|
29413
29806
|
const config2 = loadConfig({
|
|
29414
|
-
configDir:
|
|
29415
|
-
projectConfigPath: projectDir ?
|
|
29807
|
+
configDir: join41(homedir18(), ".mma"),
|
|
29808
|
+
projectConfigPath: projectDir ? join41(projectDir, ".mmrc") : join41(process.cwd(), ".mmrc")
|
|
29416
29809
|
});
|
|
29417
29810
|
config2.provider.type = answers.provider;
|
|
29418
29811
|
config2.provider.baseUrl = answers.apiBase;
|