@kl-c/matrixos 0.3.0 → 0.3.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/dist/cli/index.js
CHANGED
|
@@ -2163,7 +2163,7 @@ var package_default;
|
|
|
2163
2163
|
var init_package = __esm(() => {
|
|
2164
2164
|
package_default = {
|
|
2165
2165
|
name: "@kl-c/matrixos",
|
|
2166
|
-
version: "0.3.
|
|
2166
|
+
version: "0.3.2",
|
|
2167
2167
|
description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
|
|
2168
2168
|
main: "./dist/index.js",
|
|
2169
2169
|
types: "dist/index.d.ts",
|
|
@@ -186568,6 +186568,36 @@ var AGENT_ROLES = {
|
|
|
186568
186568
|
Neo: "Executor",
|
|
186569
186569
|
Tank: "Deep Work"
|
|
186570
186570
|
};
|
|
186571
|
+
var DEFAULT_MODEL = "opencode/deepseek-v4-flash-free";
|
|
186572
|
+
var AVAILABLE_MODELS = [
|
|
186573
|
+
"opencode/deepseek-v4-flash-free",
|
|
186574
|
+
"opencode/laguna-s-2.1-free",
|
|
186575
|
+
"opencode/mimo-v2.5-free",
|
|
186576
|
+
"opencode/nemotron-3-ultra-free",
|
|
186577
|
+
"opencode/north-mini-code-free",
|
|
186578
|
+
"opencode/big-pickle",
|
|
186579
|
+
"github-copilot/claude-opus-4.7",
|
|
186580
|
+
"anthropic/claude-opus-4",
|
|
186581
|
+
"openai/gpt-5"
|
|
186582
|
+
];
|
|
186583
|
+
function readAgentModels() {
|
|
186584
|
+
try {
|
|
186585
|
+
const cfgPath = path24.resolve(os12.homedir(), ".matrixos", "matrixos.json");
|
|
186586
|
+
if (fs21.existsSync(cfgPath)) {
|
|
186587
|
+
const raw = fs21.readFileSync(cfgPath, "utf-8").replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
186588
|
+
const parsed = JSON.parse(raw);
|
|
186589
|
+
const result = {};
|
|
186590
|
+
if (parsed.agents) {
|
|
186591
|
+
for (const [name2, cfg] of Object.entries(parsed.agents)) {
|
|
186592
|
+
if (cfg?.model)
|
|
186593
|
+
result[name2] = cfg.model;
|
|
186594
|
+
}
|
|
186595
|
+
}
|
|
186596
|
+
return result;
|
|
186597
|
+
}
|
|
186598
|
+
} catch {}
|
|
186599
|
+
return {};
|
|
186600
|
+
}
|
|
186571
186601
|
var OPENCODE_DB_PATH = path24.resolve(os12.homedir(), ".local", "share", "opencode", "opencode.db");
|
|
186572
186602
|
var THIRTY_MIN_MS = 30 * 60 * 1000;
|
|
186573
186603
|
var FIVE_MIN_MS = 5 * 60 * 1000;
|
|
@@ -186685,11 +186715,13 @@ function createDataProvider(config5) {
|
|
|
186685
186715
|
WHERE agent IS NOT NULL AND agent != ''
|
|
186686
186716
|
GROUP BY agent`).all();
|
|
186687
186717
|
if (rows.length > 0) {
|
|
186718
|
+
const cfgAgents2 = readAgentModels();
|
|
186688
186719
|
const result = [];
|
|
186689
186720
|
for (const row of rows) {
|
|
186690
186721
|
const name2 = row.agent;
|
|
186691
186722
|
const onlineRows = db.query("SELECT COUNT(*) as count FROM session WHERE agent = ? AND time_updated > ?").all(name2, cutoff);
|
|
186692
186723
|
const status2 = onlineRows.length > 0 && onlineRows[0].count > 0 ? "online" : "idle";
|
|
186724
|
+
const model = cfgAgents2[name2];
|
|
186693
186725
|
result.push({
|
|
186694
186726
|
name: name2,
|
|
186695
186727
|
role: AGENT_ROLES[name2] ?? "Agent",
|
|
@@ -186697,7 +186729,9 @@ function createDataProvider(config5) {
|
|
|
186697
186729
|
sessions: row.sessions,
|
|
186698
186730
|
uptime: 0,
|
|
186699
186731
|
cpuPercent: 0,
|
|
186700
|
-
memoryPercent: 0
|
|
186732
|
+
memoryPercent: 0,
|
|
186733
|
+
model: model ?? DEFAULT_MODEL,
|
|
186734
|
+
modelInherited: !model
|
|
186701
186735
|
});
|
|
186702
186736
|
}
|
|
186703
186737
|
db.close();
|
|
@@ -186707,15 +186741,45 @@ function createDataProvider(config5) {
|
|
|
186707
186741
|
db.close();
|
|
186708
186742
|
}
|
|
186709
186743
|
}
|
|
186710
|
-
|
|
186711
|
-
|
|
186712
|
-
|
|
186713
|
-
|
|
186714
|
-
|
|
186715
|
-
|
|
186716
|
-
|
|
186717
|
-
|
|
186718
|
-
|
|
186744
|
+
const cfgAgents = readAgentModels();
|
|
186745
|
+
return AGENT_NAMES.map((name2) => {
|
|
186746
|
+
const model = cfgAgents[name2];
|
|
186747
|
+
return {
|
|
186748
|
+
name: name2,
|
|
186749
|
+
role: AGENT_ROLES[name2] ?? "Agent",
|
|
186750
|
+
status: "idle",
|
|
186751
|
+
sessions: 0,
|
|
186752
|
+
uptime: 0,
|
|
186753
|
+
cpuPercent: 0,
|
|
186754
|
+
memoryPercent: 0,
|
|
186755
|
+
model: model ?? DEFAULT_MODEL,
|
|
186756
|
+
modelInherited: !model
|
|
186757
|
+
};
|
|
186758
|
+
});
|
|
186759
|
+
},
|
|
186760
|
+
getModels() {
|
|
186761
|
+
return AVAILABLE_MODELS;
|
|
186762
|
+
},
|
|
186763
|
+
updateAgentModel(agentName, model) {
|
|
186764
|
+
try {
|
|
186765
|
+
const cfgPath = path24.resolve(matrixosHome, "matrixos.json");
|
|
186766
|
+
let cfg = {};
|
|
186767
|
+
if (fs21.existsSync(cfgPath)) {
|
|
186768
|
+
try {
|
|
186769
|
+
const raw = fs21.readFileSync(cfgPath, "utf-8").replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
186770
|
+
const parsed = JSON.parse(raw);
|
|
186771
|
+
if (parsed && typeof parsed === "object")
|
|
186772
|
+
cfg = parsed;
|
|
186773
|
+
} catch {}
|
|
186774
|
+
}
|
|
186775
|
+
const agents = cfg.agents ?? {};
|
|
186776
|
+
agents[agentName] = { ...agents[agentName] ?? {}, model };
|
|
186777
|
+
cfg.agents = agents;
|
|
186778
|
+
fs21.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf-8");
|
|
186779
|
+
return { ok: true };
|
|
186780
|
+
} catch (error51) {
|
|
186781
|
+
return { ok: false, error: error51 instanceof Error ? error51.message : "Write failed" };
|
|
186782
|
+
}
|
|
186719
186783
|
},
|
|
186720
186784
|
async getSessions(limit = 20) {
|
|
186721
186785
|
const db = getDb();
|
|
@@ -186855,15 +186919,7 @@ function createDataProvider(config5) {
|
|
|
186855
186919
|
async getIncidents(limit = 50) {
|
|
186856
186920
|
const lines = readJsonl("anti-loop.jsonl");
|
|
186857
186921
|
if (lines.length === 0) {
|
|
186858
|
-
return
|
|
186859
|
-
timestamp: Date.now() - randomBetween(0, 86400000),
|
|
186860
|
-
trigger: randomChoice(["heartbeat_loss", "memory_exceeded", "cpu_exceeded", "doom_loop", "stuck"]),
|
|
186861
|
-
fromLevel: randomChoice(["nudge", "fallback", "restart"]),
|
|
186862
|
-
toLevel: randomChoice(["nudge", "fallback", "restart", "notify", "safe"]),
|
|
186863
|
-
actionTaken: randomChoice(["nudge", "fallback", "restart", "notify"]),
|
|
186864
|
-
outcome: randomChoice(["success", "success", "success", "failed"]),
|
|
186865
|
-
detail: "Mock incident data"
|
|
186866
|
-
})).slice(0, limit);
|
|
186922
|
+
return [];
|
|
186867
186923
|
}
|
|
186868
186924
|
return lines.slice(0, limit).map((l2) => {
|
|
186869
186925
|
try {
|
|
@@ -186890,13 +186946,18 @@ function createDataProvider(config5) {
|
|
|
186890
186946
|
const mem = process.memoryUsage();
|
|
186891
186947
|
const memPercent = Math.round(mem.rss / totalMem * 100);
|
|
186892
186948
|
const cpuPercent = Math.round(os12.loadavg()[0] * 100);
|
|
186949
|
+
let diskPercent = 0;
|
|
186950
|
+
try {
|
|
186951
|
+
const stat = fs21.statfsSync("/");
|
|
186952
|
+
diskPercent = Math.round((stat.blocks - stat.bavail) / stat.blocks * 100);
|
|
186953
|
+
} catch {}
|
|
186893
186954
|
const snapshots = [];
|
|
186894
186955
|
for (let i3 = 0;i3 < 60; i3++) {
|
|
186895
186956
|
snapshots.push({
|
|
186896
186957
|
timestamp: Date.now() - (59 - i3) * 60000,
|
|
186897
186958
|
cpuPercent,
|
|
186898
186959
|
memoryPercent: memPercent,
|
|
186899
|
-
diskPercent
|
|
186960
|
+
diskPercent,
|
|
186900
186961
|
sessionsActive: activeSessions
|
|
186901
186962
|
});
|
|
186902
186963
|
}
|
|
@@ -186922,34 +186983,6 @@ function createDataProvider(config5) {
|
|
|
186922
186983
|
} catch {}
|
|
186923
186984
|
}
|
|
186924
186985
|
}
|
|
186925
|
-
if (entries.length < 20) {
|
|
186926
|
-
const mockMsgs = [
|
|
186927
|
-
["Session started", "info"],
|
|
186928
|
-
["Tool executed: read_file", "info"],
|
|
186929
|
-
["Token count: 12,847", "debug"],
|
|
186930
|
-
["Model switch: deepseek-v4-flash-free", "info"],
|
|
186931
|
-
["Cost threshold warning: 78%", "warn"],
|
|
186932
|
-
["Heartbeat received from Morpheus", "debug"],
|
|
186933
|
-
["Session completed (4m 23s)", "info"],
|
|
186934
|
-
["Memory compaction triggered", "info"],
|
|
186935
|
-
["Config change detected", "info"],
|
|
186936
|
-
["Anti-loop triggered: Boulder retry cycle", "error"],
|
|
186937
|
-
["Cache hit rate: 89%", "info"],
|
|
186938
|
-
["Background task completed", "info"],
|
|
186939
|
-
["Gateway reconnected", "info"],
|
|
186940
|
-
["API rate limit: 45/60", "warn"],
|
|
186941
|
-
["Watchdog cycle #1247", "debug"],
|
|
186942
|
-
["Session ses_a1b2c3d4 failed", "error"]
|
|
186943
|
-
];
|
|
186944
|
-
for (const [msg, level] of mockMsgs.slice(0, 30 - entries.length)) {
|
|
186945
|
-
entries.push({
|
|
186946
|
-
timestamp: new Date(Date.now() - randomBetween(0, 3600000)).toISOString(),
|
|
186947
|
-
level,
|
|
186948
|
-
source: randomChoice(["system", "gateway", "agent", "watchdog"]),
|
|
186949
|
-
message: msg
|
|
186950
|
-
});
|
|
186951
|
-
}
|
|
186952
|
-
}
|
|
186953
186986
|
return entries.sort((a2, b2) => b2.timestamp.localeCompare(a2.timestamp)).slice(0, 100);
|
|
186954
186987
|
},
|
|
186955
186988
|
getConfig() {
|
|
@@ -187175,8 +187208,19 @@ function createDashboardServer(dataProvider, config5) {
|
|
|
187175
187208
|
switch (path25) {
|
|
187176
187209
|
case "/api/health":
|
|
187177
187210
|
return Response.json(await dataProvider.getHealth(), { headers: jsonHeaders });
|
|
187178
|
-
case "/api/agents":
|
|
187211
|
+
case "/api/agents": {
|
|
187212
|
+
if (req.method === "PUT") {
|
|
187213
|
+
const body = await req.json();
|
|
187214
|
+
if (!body.agentName || !body.model) {
|
|
187215
|
+
return Response.json({ ok: false, error: "agentName and model required" }, { status: 400, headers: jsonHeaders });
|
|
187216
|
+
}
|
|
187217
|
+
const result = dataProvider.updateAgentModel(body.agentName, body.model);
|
|
187218
|
+
return Response.json(result, { headers: jsonHeaders });
|
|
187219
|
+
}
|
|
187179
187220
|
return Response.json(await dataProvider.getAgents(), { headers: jsonHeaders });
|
|
187221
|
+
}
|
|
187222
|
+
case "/api/models":
|
|
187223
|
+
return Response.json(dataProvider.getModels(), { headers: jsonHeaders });
|
|
187180
187224
|
case "/api/sessions": {
|
|
187181
187225
|
const limit = parseInt(url3.searchParams.get("limit") ?? "20", 10);
|
|
187182
187226
|
return Response.json(await dataProvider.getSessions(limit), { headers: jsonHeaders });
|
package/dist/cli-node/index.js
CHANGED
|
@@ -2163,7 +2163,7 @@ var package_default;
|
|
|
2163
2163
|
var init_package = __esm(() => {
|
|
2164
2164
|
package_default = {
|
|
2165
2165
|
name: "@kl-c/matrixos",
|
|
2166
|
-
version: "0.3.
|
|
2166
|
+
version: "0.3.2",
|
|
2167
2167
|
description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
|
|
2168
2168
|
main: "./dist/index.js",
|
|
2169
2169
|
types: "dist/index.d.ts",
|
|
@@ -186623,6 +186623,36 @@ var AGENT_ROLES = {
|
|
|
186623
186623
|
Neo: "Executor",
|
|
186624
186624
|
Tank: "Deep Work"
|
|
186625
186625
|
};
|
|
186626
|
+
var DEFAULT_MODEL = "opencode/deepseek-v4-flash-free";
|
|
186627
|
+
var AVAILABLE_MODELS = [
|
|
186628
|
+
"opencode/deepseek-v4-flash-free",
|
|
186629
|
+
"opencode/laguna-s-2.1-free",
|
|
186630
|
+
"opencode/mimo-v2.5-free",
|
|
186631
|
+
"opencode/nemotron-3-ultra-free",
|
|
186632
|
+
"opencode/north-mini-code-free",
|
|
186633
|
+
"opencode/big-pickle",
|
|
186634
|
+
"github-copilot/claude-opus-4.7",
|
|
186635
|
+
"anthropic/claude-opus-4",
|
|
186636
|
+
"openai/gpt-5"
|
|
186637
|
+
];
|
|
186638
|
+
function readAgentModels() {
|
|
186639
|
+
try {
|
|
186640
|
+
const cfgPath = path24.resolve(os12.homedir(), ".matrixos", "matrixos.json");
|
|
186641
|
+
if (fs21.existsSync(cfgPath)) {
|
|
186642
|
+
const raw = fs21.readFileSync(cfgPath, "utf-8").replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
186643
|
+
const parsed = JSON.parse(raw);
|
|
186644
|
+
const result = {};
|
|
186645
|
+
if (parsed.agents) {
|
|
186646
|
+
for (const [name2, cfg] of Object.entries(parsed.agents)) {
|
|
186647
|
+
if (cfg?.model)
|
|
186648
|
+
result[name2] = cfg.model;
|
|
186649
|
+
}
|
|
186650
|
+
}
|
|
186651
|
+
return result;
|
|
186652
|
+
}
|
|
186653
|
+
} catch {}
|
|
186654
|
+
return {};
|
|
186655
|
+
}
|
|
186626
186656
|
var OPENCODE_DB_PATH = path24.resolve(os12.homedir(), ".local", "share", "opencode", "opencode.db");
|
|
186627
186657
|
var THIRTY_MIN_MS = 30 * 60 * 1000;
|
|
186628
186658
|
var FIVE_MIN_MS = 5 * 60 * 1000;
|
|
@@ -186740,11 +186770,13 @@ function createDataProvider(config5) {
|
|
|
186740
186770
|
WHERE agent IS NOT NULL AND agent != ''
|
|
186741
186771
|
GROUP BY agent`).all();
|
|
186742
186772
|
if (rows.length > 0) {
|
|
186773
|
+
const cfgAgents2 = readAgentModels();
|
|
186743
186774
|
const result = [];
|
|
186744
186775
|
for (const row of rows) {
|
|
186745
186776
|
const name2 = row.agent;
|
|
186746
186777
|
const onlineRows = db.query("SELECT COUNT(*) as count FROM session WHERE agent = ? AND time_updated > ?").all(name2, cutoff);
|
|
186747
186778
|
const status2 = onlineRows.length > 0 && onlineRows[0].count > 0 ? "online" : "idle";
|
|
186779
|
+
const model = cfgAgents2[name2];
|
|
186748
186780
|
result.push({
|
|
186749
186781
|
name: name2,
|
|
186750
186782
|
role: AGENT_ROLES[name2] ?? "Agent",
|
|
@@ -186752,7 +186784,9 @@ function createDataProvider(config5) {
|
|
|
186752
186784
|
sessions: row.sessions,
|
|
186753
186785
|
uptime: 0,
|
|
186754
186786
|
cpuPercent: 0,
|
|
186755
|
-
memoryPercent: 0
|
|
186787
|
+
memoryPercent: 0,
|
|
186788
|
+
model: model ?? DEFAULT_MODEL,
|
|
186789
|
+
modelInherited: !model
|
|
186756
186790
|
});
|
|
186757
186791
|
}
|
|
186758
186792
|
db.close();
|
|
@@ -186762,15 +186796,45 @@ function createDataProvider(config5) {
|
|
|
186762
186796
|
db.close();
|
|
186763
186797
|
}
|
|
186764
186798
|
}
|
|
186765
|
-
|
|
186766
|
-
|
|
186767
|
-
|
|
186768
|
-
|
|
186769
|
-
|
|
186770
|
-
|
|
186771
|
-
|
|
186772
|
-
|
|
186773
|
-
|
|
186799
|
+
const cfgAgents = readAgentModels();
|
|
186800
|
+
return AGENT_NAMES.map((name2) => {
|
|
186801
|
+
const model = cfgAgents[name2];
|
|
186802
|
+
return {
|
|
186803
|
+
name: name2,
|
|
186804
|
+
role: AGENT_ROLES[name2] ?? "Agent",
|
|
186805
|
+
status: "idle",
|
|
186806
|
+
sessions: 0,
|
|
186807
|
+
uptime: 0,
|
|
186808
|
+
cpuPercent: 0,
|
|
186809
|
+
memoryPercent: 0,
|
|
186810
|
+
model: model ?? DEFAULT_MODEL,
|
|
186811
|
+
modelInherited: !model
|
|
186812
|
+
};
|
|
186813
|
+
});
|
|
186814
|
+
},
|
|
186815
|
+
getModels() {
|
|
186816
|
+
return AVAILABLE_MODELS;
|
|
186817
|
+
},
|
|
186818
|
+
updateAgentModel(agentName, model) {
|
|
186819
|
+
try {
|
|
186820
|
+
const cfgPath = path24.resolve(matrixosHome, "matrixos.json");
|
|
186821
|
+
let cfg = {};
|
|
186822
|
+
if (fs21.existsSync(cfgPath)) {
|
|
186823
|
+
try {
|
|
186824
|
+
const raw = fs21.readFileSync(cfgPath, "utf-8").replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
186825
|
+
const parsed = JSON.parse(raw);
|
|
186826
|
+
if (parsed && typeof parsed === "object")
|
|
186827
|
+
cfg = parsed;
|
|
186828
|
+
} catch {}
|
|
186829
|
+
}
|
|
186830
|
+
const agents = cfg.agents ?? {};
|
|
186831
|
+
agents[agentName] = { ...agents[agentName] ?? {}, model };
|
|
186832
|
+
cfg.agents = agents;
|
|
186833
|
+
fs21.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf-8");
|
|
186834
|
+
return { ok: true };
|
|
186835
|
+
} catch (error51) {
|
|
186836
|
+
return { ok: false, error: error51 instanceof Error ? error51.message : "Write failed" };
|
|
186837
|
+
}
|
|
186774
186838
|
},
|
|
186775
186839
|
async getSessions(limit = 20) {
|
|
186776
186840
|
const db = getDb();
|
|
@@ -186910,15 +186974,7 @@ function createDataProvider(config5) {
|
|
|
186910
186974
|
async getIncidents(limit = 50) {
|
|
186911
186975
|
const lines = readJsonl("anti-loop.jsonl");
|
|
186912
186976
|
if (lines.length === 0) {
|
|
186913
|
-
return
|
|
186914
|
-
timestamp: Date.now() - randomBetween(0, 86400000),
|
|
186915
|
-
trigger: randomChoice(["heartbeat_loss", "memory_exceeded", "cpu_exceeded", "doom_loop", "stuck"]),
|
|
186916
|
-
fromLevel: randomChoice(["nudge", "fallback", "restart"]),
|
|
186917
|
-
toLevel: randomChoice(["nudge", "fallback", "restart", "notify", "safe"]),
|
|
186918
|
-
actionTaken: randomChoice(["nudge", "fallback", "restart", "notify"]),
|
|
186919
|
-
outcome: randomChoice(["success", "success", "success", "failed"]),
|
|
186920
|
-
detail: "Mock incident data"
|
|
186921
|
-
})).slice(0, limit);
|
|
186977
|
+
return [];
|
|
186922
186978
|
}
|
|
186923
186979
|
return lines.slice(0, limit).map((l2) => {
|
|
186924
186980
|
try {
|
|
@@ -186945,13 +187001,18 @@ function createDataProvider(config5) {
|
|
|
186945
187001
|
const mem = process.memoryUsage();
|
|
186946
187002
|
const memPercent = Math.round(mem.rss / totalMem * 100);
|
|
186947
187003
|
const cpuPercent = Math.round(os12.loadavg()[0] * 100);
|
|
187004
|
+
let diskPercent = 0;
|
|
187005
|
+
try {
|
|
187006
|
+
const stat = fs21.statfsSync("/");
|
|
187007
|
+
diskPercent = Math.round((stat.blocks - stat.bavail) / stat.blocks * 100);
|
|
187008
|
+
} catch {}
|
|
186948
187009
|
const snapshots = [];
|
|
186949
187010
|
for (let i3 = 0;i3 < 60; i3++) {
|
|
186950
187011
|
snapshots.push({
|
|
186951
187012
|
timestamp: Date.now() - (59 - i3) * 60000,
|
|
186952
187013
|
cpuPercent,
|
|
186953
187014
|
memoryPercent: memPercent,
|
|
186954
|
-
diskPercent
|
|
187015
|
+
diskPercent,
|
|
186955
187016
|
sessionsActive: activeSessions
|
|
186956
187017
|
});
|
|
186957
187018
|
}
|
|
@@ -186977,34 +187038,6 @@ function createDataProvider(config5) {
|
|
|
186977
187038
|
} catch {}
|
|
186978
187039
|
}
|
|
186979
187040
|
}
|
|
186980
|
-
if (entries.length < 20) {
|
|
186981
|
-
const mockMsgs = [
|
|
186982
|
-
["Session started", "info"],
|
|
186983
|
-
["Tool executed: read_file", "info"],
|
|
186984
|
-
["Token count: 12,847", "debug"],
|
|
186985
|
-
["Model switch: deepseek-v4-flash-free", "info"],
|
|
186986
|
-
["Cost threshold warning: 78%", "warn"],
|
|
186987
|
-
["Heartbeat received from Morpheus", "debug"],
|
|
186988
|
-
["Session completed (4m 23s)", "info"],
|
|
186989
|
-
["Memory compaction triggered", "info"],
|
|
186990
|
-
["Config change detected", "info"],
|
|
186991
|
-
["Anti-loop triggered: Boulder retry cycle", "error"],
|
|
186992
|
-
["Cache hit rate: 89%", "info"],
|
|
186993
|
-
["Background task completed", "info"],
|
|
186994
|
-
["Gateway reconnected", "info"],
|
|
186995
|
-
["API rate limit: 45/60", "warn"],
|
|
186996
|
-
["Watchdog cycle #1247", "debug"],
|
|
186997
|
-
["Session ses_a1b2c3d4 failed", "error"]
|
|
186998
|
-
];
|
|
186999
|
-
for (const [msg, level] of mockMsgs.slice(0, 30 - entries.length)) {
|
|
187000
|
-
entries.push({
|
|
187001
|
-
timestamp: new Date(Date.now() - randomBetween(0, 3600000)).toISOString(),
|
|
187002
|
-
level,
|
|
187003
|
-
source: randomChoice(["system", "gateway", "agent", "watchdog"]),
|
|
187004
|
-
message: msg
|
|
187005
|
-
});
|
|
187006
|
-
}
|
|
187007
|
-
}
|
|
187008
187041
|
return entries.sort((a2, b2) => b2.timestamp.localeCompare(a2.timestamp)).slice(0, 100);
|
|
187009
187042
|
},
|
|
187010
187043
|
getConfig() {
|
|
@@ -187230,8 +187263,19 @@ function createDashboardServer(dataProvider, config5) {
|
|
|
187230
187263
|
switch (path25) {
|
|
187231
187264
|
case "/api/health":
|
|
187232
187265
|
return Response.json(await dataProvider.getHealth(), { headers: jsonHeaders });
|
|
187233
|
-
case "/api/agents":
|
|
187266
|
+
case "/api/agents": {
|
|
187267
|
+
if (req.method === "PUT") {
|
|
187268
|
+
const body = await req.json();
|
|
187269
|
+
if (!body.agentName || !body.model) {
|
|
187270
|
+
return Response.json({ ok: false, error: "agentName and model required" }, { status: 400, headers: jsonHeaders });
|
|
187271
|
+
}
|
|
187272
|
+
const result = dataProvider.updateAgentModel(body.agentName, body.model);
|
|
187273
|
+
return Response.json(result, { headers: jsonHeaders });
|
|
187274
|
+
}
|
|
187234
187275
|
return Response.json(await dataProvider.getAgents(), { headers: jsonHeaders });
|
|
187276
|
+
}
|
|
187277
|
+
case "/api/models":
|
|
187278
|
+
return Response.json(dataProvider.getModels(), { headers: jsonHeaders });
|
|
187235
187279
|
case "/api/sessions": {
|
|
187236
187280
|
const limit = parseInt(url3.searchParams.get("limit") ?? "20", 10);
|
|
187237
187281
|
return Response.json(await dataProvider.getSessions(limit), { headers: jsonHeaders });
|
|
@@ -5,6 +5,11 @@ export interface DataProviderConfig {
|
|
|
5
5
|
export interface DataProvider {
|
|
6
6
|
getHealth(): Promise<HealthResponse>;
|
|
7
7
|
getAgents(): Promise<AgentStatus[]>;
|
|
8
|
+
getModels(): string[];
|
|
9
|
+
updateAgentModel(agentName: string, model: string): {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
error?: string;
|
|
12
|
+
};
|
|
8
13
|
getSessions(limit?: number): Promise<SessionSummary[]>;
|
|
9
14
|
getCost(): Promise<CostSummary>;
|
|
10
15
|
getKanbanTasks(): Promise<KanbanBoard>;
|
|
@@ -116,44 +116,39 @@ async function loadHealth(){
|
|
|
116
116
|
const kpi=document.getElementById('healthKpis'),gauges=document.getElementById('gaugeGrid'),hb=document.getElementById('heartbeatGrid'),inc=document.getElementById('incidentList')
|
|
117
117
|
showSkeleton(kpi,'kpi')
|
|
118
118
|
try{
|
|
119
|
-
const[health,metrics,incidents]=await Promise.all([API.health(),API.metrics(),API.incidents(8)])
|
|
120
|
-
const cpu=metrics.length?metrics[metrics.length-1].cpuPercent:
|
|
121
|
-
const mem=health.memoryUsage?health.memoryUsage.percent||
|
|
122
|
-
const disk=
|
|
119
|
+
const[health,metrics,incidents,agents]=await Promise.all([API.health(),API.metrics(),API.incidents(8),API.agents()])
|
|
120
|
+
const cpu=metrics.length?metrics[metrics.length-1].cpuPercent:0
|
|
121
|
+
const mem=health.memoryUsage?health.memoryUsage.percent||0:0
|
|
122
|
+
const disk=metrics.length?metrics[metrics.length-1].diskPercent||0:0
|
|
123
123
|
const cpuColor=cpu>80?'var(--danger)':cpu>60?'var(--warning)':'var(--success)'
|
|
124
124
|
const memColor=mem>80?'var(--danger)':mem>60?'var(--warning)':'var(--success)'
|
|
125
125
|
const diskColor=disk>80?'var(--danger)':disk>60?'var(--warning)':'var(--info)'
|
|
126
126
|
|
|
127
127
|
kpi.innerHTML=`
|
|
128
|
-
<div class="kpi-card"><div class="kpi-card-header"><span class="kpi-label">System Status</span><div class="kpi-icon green"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 8l3 3 5-6"/></svg></div></div><div class="kpi-value" style="color:var(--success)">
|
|
129
|
-
<div class="kpi-card"><div class="kpi-card-header"><span class="kpi-label">Uptime</span><div class="kpi-icon cyan"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="8" cy="8" r="6"/><path d="M8 4.5v3.5l2.5 1.5"/></svg></div></div><div class="kpi-value"
|
|
130
|
-
<div class="kpi-card"><div class="kpi-card-header"><span class="kpi-label">Active Incidents</span><div class="kpi-icon red"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M8 2L1.5 13h13L8 2z"/><path d="M8 7v2.5M8 11.5v.5"/></svg></div></div><div class="kpi-value" style="color
|
|
131
|
-
<div class="kpi-card"><div class="kpi-card-header"><span class="kpi-label">
|
|
128
|
+
<div class="kpi-card"><div class="kpi-card-header"><span class="kpi-label">System Status</span><div class="kpi-icon green"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 8l3 3 5-6"/></svg></div></div><div class="kpi-value" style="color:var(--success)">Online</div><div class="kpi-trend flat"><span class="live-dot" style="margin-right:4px"></span>v${health.version}</div></div>
|
|
129
|
+
<div class="kpi-card"><div class="kpi-card-header"><span class="kpi-label">Uptime</span><div class="kpi-icon cyan"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="8" cy="8" r="6"/><path d="M8 4.5v3.5l2.5 1.5"/></svg></div></div><div class="kpi-value">${fmtDur(Math.round(health.uptime))}</div><div class="kpi-trend up">Since last restart</div></div>
|
|
130
|
+
<div class="kpi-card"><div class="kpi-card-header"><span class="kpi-label">Active Incidents</span><div class="kpi-icon red"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M8 2L1.5 13h13L8 2z"/><path d="M8 7v2.5M8 11.5v.5"/></svg></div></div><div class="kpi-value" style="color:${incidents.length?'var(--danger)':'var(--success)'}">${incidents.length}</div><div class="kpi-trend ${incidents.length?'down':'flat'}">${incidents.length?'Needs attention':'All clear'}</div></div>
|
|
131
|
+
<div class="kpi-card"><div class="kpi-card-header"><span class="kpi-label">Active Sessions</span><div class="kpi-icon blue"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="8" cy="8" r="6"/><path d="M8 5v3"/><circle cx="8" cy="11" r="0.5" fill="currentColor"/></svg></div></div><div class="kpi-value">${health.activeSessions}</div><div class="kpi-trend flat">${health.tasksQueued} queued</div></div>`
|
|
132
132
|
|
|
133
133
|
// Resource gauges (SVG)
|
|
134
134
|
function gauge(pct,color,label,sub){
|
|
135
135
|
const r=16,c=2*Math.PI*r,offset=c-(c*pct/100)
|
|
136
136
|
return `<div class="gauge-card"><div class="gauge-ring"><svg viewBox="0 0 40 40"><circle class="track" cx="20" cy="20" r="${r}"/><circle stroke="${color}" cx="20" cy="20" r="${r}" stroke-dasharray="${c}" stroke-dashoffset="${offset}" style="transition:stroke-dashoffset 500ms"/></svg><div class="gauge-val" style="color:${color}">${pct}%</div></div><div class="gauge-label">${label}</div><div class="gauge-sub">${sub}</div></div>`
|
|
137
137
|
}
|
|
138
|
-
const totalMem=(health.memoryUsage&&health.memoryUsage.total)||
|
|
138
|
+
const totalMem=(health.memoryUsage&&health.memoryUsage.total)||0
|
|
139
139
|
const usedMem=Math.round(totalMem*(mem||0)/100)
|
|
140
|
-
gauges.innerHTML=gauge(Math.round(cpu),cpuColor,'CPU Usage','
|
|
140
|
+
gauges.innerHTML=gauge(Math.round(cpu),cpuColor,'CPU Usage','Load avg')+gauge(mem,memColor,'Memory',`${usedMem} / ${totalMem} MB`)+gauge(disk,diskColor,'Disk','/ filesystem')
|
|
141
141
|
|
|
142
|
-
// Heartbeat Grid
|
|
143
|
-
const agents
|
|
142
|
+
// Heartbeat Grid — real agents
|
|
143
|
+
const agentNames=agents.slice(0,8).map(a=>a.name)
|
|
144
144
|
const hbLegendEl=document.getElementById('hbLegend')
|
|
145
|
-
hbLegendEl.innerHTML=`<span style="display:flex;align-items:center;gap:4px;font-size:var(--text-xs);color:var(--success)"><span style="width:6px;height:6px;border-radius:50%;background:var(--success)"></span>
|
|
146
|
-
hb.innerHTML=
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
const r=Math.random()
|
|
151
|
-
const cls=r>0.85?'fail':r>0.7&&i>2?'warn':'healthy'
|
|
152
|
-
cells.push(`<div class="hb-cell ${cls}" title="${name} t-${(7-t)*10}s">${initial}</div>`)
|
|
153
|
-
}
|
|
154
|
-
return cells.join('')
|
|
145
|
+
hbLegendEl.innerHTML=`<span style="display:flex;align-items:center;gap:4px;font-size:var(--text-xs);color:var(--success)"><span style="width:6px;height:6px;border-radius:50%;background:var(--success)"></span>Online</span><span style="display:flex;align-items:center;gap:4px;font-size:var(--text-xs);color:var(--warning)"><span style="width:6px;height:6px;border-radius:50%;background:var(--warning)"></span>Idle</span><span style="display:flex;align-items:center;gap:4px;font-size:var(--text-xs);color:var(--danger)"><span style="width:6px;height:6px;border-radius:50%;background:var(--danger)"></span>Offline</span>`
|
|
146
|
+
hb.innerHTML=agentNames.map((name)=>{
|
|
147
|
+
const agent=agents.find(a=>a.name===name)
|
|
148
|
+
const cls=agent&&agent.status==='online'?'healthy':agent&&agent.status==='idle'?'warn':'fail'
|
|
149
|
+
return `<div class="hb-cell ${cls}" title="${name}">${name[0]}</div>`
|
|
155
150
|
}).join('')
|
|
156
|
-
hb.insertAdjacentHTML('afterend',`<div style="margin-top:var(--space-3);font-size:var(--text-xs);color:var(--text-tertiary)">Agents: ${
|
|
151
|
+
hb.insertAdjacentHTML('afterend',`<div style="margin-top:var(--space-3);font-size:var(--text-xs);color:var(--text-tertiary)">Agents: ${agentNames.map(a=>a[0]+'='+a).join(', ')}</div>`)
|
|
157
152
|
|
|
158
153
|
// Incidents
|
|
159
154
|
if(!incidents.length){showEmpty(inc,'No incidents recorded');return}
|
package/dist/index.js
CHANGED
|
@@ -368019,7 +368019,7 @@ function getCachedVersion(options = {}) {
|
|
|
368019
368019
|
// package.json
|
|
368020
368020
|
var package_default = {
|
|
368021
368021
|
name: "@kl-c/matrixos",
|
|
368022
|
-
version: "0.3.
|
|
368022
|
+
version: "0.3.2",
|
|
368023
368023
|
description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
|
|
368024
368024
|
main: "./dist/index.js",
|
|
368025
368025
|
types: "dist/index.d.ts",
|
package/package.json
CHANGED