@kl-c/matrixos 0.1.17 → 0.1.19

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
@@ -2145,7 +2145,7 @@ var package_default;
2145
2145
  var init_package = __esm(() => {
2146
2146
  package_default = {
2147
2147
  name: "@kl-c/matrixos",
2148
- version: "0.1.17",
2148
+ version: "0.1.19",
2149
2149
  description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
2150
2150
  main: "./dist/index.js",
2151
2151
  types: "dist/index.d.ts",
@@ -141031,101 +141031,63 @@ var AGENT_ROLES = {
141031
141031
  Neo: "Executor",
141032
141032
  Tank: "Deep Work"
141033
141033
  };
141034
+ var OPENCODE_DB_PATH = path24.resolve(os12.homedir(), ".local", "share", "opencode", "opencode.db");
141035
+ var THIRTY_MIN_MS = 30 * 60 * 1000;
141036
+ var FIVE_MIN_MS = 5 * 60 * 1000;
141037
+ var BUDGET_TOTAL = 5000;
141034
141038
  function randomBetween(min2, max2) {
141035
141039
  return Math.floor(Math.random() * (max2 - min2 + 1)) + min2;
141036
141040
  }
141037
141041
  function randomChoice(arr) {
141038
141042
  return arr[Math.floor(Math.random() * arr.length)];
141039
141043
  }
141040
- function generateMockAgents() {
141041
- return AGENT_NAMES.map((name2) => ({
141042
- name: name2,
141043
- role: AGENT_ROLES[name2] ?? "Agent",
141044
- status: randomChoice(["online", "online", "online", "idle", "idle", "offline"]),
141045
- sessions: randomBetween(0, 25),
141046
- uptime: randomBetween(100, 86400),
141047
- cpuPercent: randomBetween(2, 85),
141048
- memoryPercent: randomBetween(10, 75)
141049
- }));
141050
- }
141051
- function generateMockSessions(count) {
141052
- const models2 = ["deepseek-v4-flash-free", "gpt-5.5-pro", "claude-opus-4-7", "gemini-3.1-pro", "glm-5.2"];
141053
- return Array.from({ length: count }, (_2, i3) => ({
141054
- id: `ses_${randomBetween(1e5, 999999).toString(16)}`,
141055
- agent: randomChoice(AGENT_NAMES),
141056
- model: randomChoice(models2),
141057
- duration: randomBetween(5, 600),
141058
- cost: Math.round(randomBetween(1, 500) * 100) / 100,
141059
- status: randomChoice(["active", "completed", "completed", "completed", "failed", "timeout"]),
141060
- startedAt: new Date(Date.now() - randomBetween(0, 86400000)).toISOString()
141061
- }));
141044
+ function parseModel(modelRaw) {
141045
+ if (!modelRaw)
141046
+ return "unknown";
141047
+ try {
141048
+ const parsed = JSON.parse(modelRaw);
141049
+ if (parsed.id)
141050
+ return parsed.id;
141051
+ } catch {}
141052
+ return modelRaw;
141053
+ }
141054
+ function getDb() {
141055
+ if (!fs20.existsSync(OPENCODE_DB_PATH))
141056
+ return;
141057
+ try {
141058
+ return new Database5(OPENCODE_DB_PATH, { readonly: true });
141059
+ } catch {
141060
+ return;
141061
+ }
141062
141062
  }
141063
- function generateMockCost() {
141064
- const agents = AGENT_NAMES.map((name2) => ({
141065
- agent: name2,
141066
- cost: Math.round(randomBetween(50, 2000) * 100) / 100,
141067
- percentage: 0
141068
- }));
141069
- const total = agents.reduce((s, a2) => s + a2.cost, 0);
141070
- agents.forEach((a2) => {
141071
- a2.percentage = Math.round(a2.cost / total * 100);
141072
- });
141073
- return {
141074
- total: Math.round(total * 100) / 100,
141075
- daily: Math.round(randomBetween(50, 300) * 100) / 100,
141076
- monthly: Math.round(randomBetween(1500, 9000) * 100) / 100,
141077
- budgetRemaining: Math.round(randomBetween(500, 5000) * 100) / 100,
141078
- byAgent: agents,
141079
- byDay: Array.from({ length: 30 }, (_2, i3) => ({
141080
- date: new Date(Date.now() - (29 - i3) * 86400000).toISOString().slice(0, 10),
141081
- cost: Math.round(randomBetween(20, 300) * 100) / 100
141082
- })),
141083
- alerts: [
141084
- { severity: "warning", message: "Morpheus approaching budget threshold (85%)" },
141085
- { severity: "critical", message: "Tank exceeded daily budget cap ($500)" }
141086
- ]
141087
- };
141063
+ function midnightMs() {
141064
+ const d = new Date;
141065
+ d.setHours(0, 0, 0, 0);
141066
+ return d.getTime();
141088
141067
  }
141089
- function generateMockKanban() {
141090
- const statuses = ["pending", "in_progress", "completed", "failed"];
141091
- const columns = {};
141092
- for (const s of statuses) {
141093
- columns[s] = Array.from({ length: randomBetween(2, 6) }, (_2, i3) => ({
141094
- id: `task_${randomBetween(1000, 9999)}`,
141095
- title: randomChoice([
141096
- "Implement Watchdog daemon",
141097
- "Design System tokens",
141098
- "API rate limiting",
141099
- "Session persistence",
141100
- "User auth flow",
141101
- "Database migration",
141102
- "Cache invalidation",
141103
- "Webhook integration",
141104
- "Telegram notifications",
141105
- "Cost optimization",
141106
- "Security audit",
141107
- "Performance profiling"
141108
- ]),
141109
- agent: randomChoice(AGENT_NAMES),
141110
- priority: randomChoice(["low", "medium", "high", "critical"]),
141111
- status: s,
141112
- createdAt: new Date(Date.now() - randomBetween(0, 604800000)).toISOString(),
141113
- updatedAt: new Date(Date.now() - randomBetween(0, 86400000)).toISOString()
141114
- }));
141115
- }
141116
- return { columns };
141068
+ function thirtyDaysAgoMs() {
141069
+ return Date.now() - 30 * 24 * 60 * 60 * 1000;
141117
141070
  }
141118
- function generateMockMetrics() {
141119
- return Array.from({ length: 60 }, (_2, i3) => ({
141120
- timestamp: Date.now() - (59 - i3) * 60000,
141121
- cpuPercent: randomBetween(10, 95),
141122
- memoryPercent: randomBetween(30, 85),
141123
- diskPercent: randomBetween(40, 70),
141124
- sessionsActive: randomBetween(1, 8)
141125
- }));
141071
+ function readPackageVersion2() {
141072
+ try {
141073
+ const candidates = [
141074
+ new URL("../package.json", import.meta.url).pathname,
141075
+ new URL("../../package.json", import.meta.url).pathname,
141076
+ path24.resolve(process.cwd(), "package.json")
141077
+ ];
141078
+ for (const candidate of candidates) {
141079
+ if (fs20.existsSync(candidate)) {
141080
+ const pkg = JSON.parse(fs20.readFileSync(candidate, "utf-8"));
141081
+ if (pkg.version)
141082
+ return pkg.version;
141083
+ }
141084
+ }
141085
+ } catch {}
141086
+ return "0.0.0";
141126
141087
  }
141127
141088
  function createDataProvider(config4) {
141128
141089
  const matrixosHome = config4?.matrixosHome ?? ".matrixos";
141090
+ const version3 = readPackageVersion2();
141129
141091
  function readJsonl(filePath) {
141130
141092
  try {
141131
141093
  const fullPath = path24.resolve(matrixosHome, "logs", filePath);
@@ -141141,13 +141103,33 @@ function createDataProvider(config4) {
141141
141103
  async getHealth() {
141142
141104
  const mem = process.memoryUsage();
141143
141105
  const totalMem = os12.totalmem();
141106
+ const db = getDb();
141107
+ let agentsOnline = AGENT_NAMES.length;
141108
+ let activeSessions = 0;
141109
+ let tasksQueued = 0;
141110
+ if (db) {
141111
+ try {
141112
+ const agentRow = db.query("SELECT COUNT(DISTINCT agent) as count FROM session").get();
141113
+ if (agentRow)
141114
+ agentsOnline = agentRow.count;
141115
+ const cutoff = Date.now() - THIRTY_MIN_MS;
141116
+ const sessionRows = db.query("SELECT COUNT(*) as count FROM session WHERE time_archived IS NULL AND time_updated > ?").all(cutoff);
141117
+ if (sessionRows.length > 0)
141118
+ activeSessions = sessionRows[0].count;
141119
+ const todoRows = db.query("SELECT COUNT(*) as count FROM todo WHERE status = 'pending'").all();
141120
+ if (todoRows.length > 0)
141121
+ tasksQueued = todoRows[0].count;
141122
+ } catch {} finally {
141123
+ db.close();
141124
+ }
141125
+ }
141144
141126
  return {
141145
- agentsOnline: AGENT_NAMES.length - randomBetween(1, 3),
141127
+ agentsOnline,
141146
141128
  totalAgents: AGENT_NAMES.length,
141147
- activeSessions: randomBetween(2, 8),
141148
- tasksQueued: randomBetween(5, 20),
141129
+ activeSessions,
141130
+ tasksQueued,
141149
141131
  uptime: process.uptime(),
141150
- version: "0.1.0",
141132
+ version: version3,
141151
141133
  memoryUsage: {
141152
141134
  used: Math.round(mem.rss / 1024 / 1024),
141153
141135
  total: Math.round(totalMem / 1024 / 1024),
@@ -141157,16 +141139,181 @@ function createDataProvider(config4) {
141157
141139
  };
141158
141140
  },
141159
141141
  async getAgents() {
141160
- return generateMockAgents();
141142
+ const db = getDb();
141143
+ if (db) {
141144
+ try {
141145
+ const cutoff = Date.now() - THIRTY_MIN_MS;
141146
+ const rows = db.query(`SELECT agent, COUNT(*) as sessions
141147
+ FROM session
141148
+ WHERE agent IS NOT NULL AND agent != ''
141149
+ GROUP BY agent`).all();
141150
+ if (rows.length > 0) {
141151
+ const result = [];
141152
+ for (const row of rows) {
141153
+ const name2 = row.agent;
141154
+ const onlineRows = db.query("SELECT COUNT(*) as count FROM session WHERE agent = ? AND time_updated > ?").all(name2, cutoff);
141155
+ const status2 = onlineRows.length > 0 && onlineRows[0].count > 0 ? "online" : "idle";
141156
+ result.push({
141157
+ name: name2,
141158
+ role: AGENT_ROLES[name2] ?? "Agent",
141159
+ status: status2,
141160
+ sessions: row.sessions,
141161
+ uptime: 0,
141162
+ cpuPercent: 0,
141163
+ memoryPercent: 0
141164
+ });
141165
+ }
141166
+ db.close();
141167
+ return result;
141168
+ }
141169
+ } catch {} finally {
141170
+ db.close();
141171
+ }
141172
+ }
141173
+ return AGENT_NAMES.map((name2) => ({
141174
+ name: name2,
141175
+ role: AGENT_ROLES[name2] ?? "Agent",
141176
+ status: "idle",
141177
+ sessions: 0,
141178
+ uptime: 0,
141179
+ cpuPercent: 0,
141180
+ memoryPercent: 0
141181
+ }));
141161
141182
  },
141162
141183
  async getSessions(limit = 20) {
141163
- return generateMockSessions(limit).slice(0, limit);
141184
+ const db = getDb();
141185
+ if (!db)
141186
+ return [];
141187
+ try {
141188
+ const now = Date.now();
141189
+ const rows = db.query(`SELECT id, title, agent, model, cost, time_created, time_updated, time_archived
141190
+ FROM session
141191
+ ORDER BY time_updated DESC
141192
+ LIMIT ?`).all(limit);
141193
+ const result = [];
141194
+ for (const row of rows) {
141195
+ const duration3 = Math.max(0, Math.round((row.time_updated - row.time_created) / 1000));
141196
+ let status2 = "completed";
141197
+ if (row.time_archived !== null) {
141198
+ status2 = "completed";
141199
+ } else if (row.time_updated > now - FIVE_MIN_MS) {
141200
+ status2 = "active";
141201
+ } else {
141202
+ status2 = "completed";
141203
+ }
141204
+ result.push({
141205
+ id: row.id,
141206
+ agent: row.agent ?? "unknown",
141207
+ model: parseModel(row.model),
141208
+ duration: duration3,
141209
+ cost: row.cost,
141210
+ status: status2,
141211
+ startedAt: new Date(row.time_created).toISOString()
141212
+ });
141213
+ }
141214
+ return result;
141215
+ } catch {
141216
+ return [];
141217
+ } finally {
141218
+ db.close();
141219
+ }
141164
141220
  },
141165
141221
  async getCost() {
141166
- return generateMockCost();
141222
+ const db = getDb();
141223
+ if (!db) {
141224
+ return {
141225
+ total: 0,
141226
+ daily: 0,
141227
+ monthly: 0,
141228
+ budgetRemaining: BUDGET_TOTAL,
141229
+ byAgent: [],
141230
+ byDay: [],
141231
+ alerts: []
141232
+ };
141233
+ }
141234
+ try {
141235
+ const totalRows = db.query("SELECT COALESCE(SUM(cost), 0) as sum FROM session").all();
141236
+ const total = totalRows.length > 0 ? totalRows[0].sum ?? 0 : 0;
141237
+ const dailyRows = db.query("SELECT COALESCE(SUM(cost), 0) as sum FROM session WHERE time_created > ?").all(midnightMs());
141238
+ const daily = dailyRows.length > 0 ? dailyRows[0].sum ?? 0 : 0;
141239
+ const monthlyRows = db.query("SELECT COALESCE(SUM(cost), 0) as sum FROM session WHERE time_created > ?").all(thirtyDaysAgoMs());
141240
+ const monthly = monthlyRows.length > 0 ? monthlyRows[0].sum ?? 0 : 0;
141241
+ const agentRows = db.query(`SELECT agent, COALESCE(SUM(cost), 0) as cost
141242
+ FROM session
141243
+ WHERE agent IS NOT NULL AND agent != ''
141244
+ GROUP BY agent`).all();
141245
+ const byAgent = agentRows.map((r2) => ({
141246
+ agent: r2.agent,
141247
+ cost: r2.cost,
141248
+ percentage: total > 0 ? Math.round(r2.cost / total * 100) : 0
141249
+ }));
141250
+ const byDayRows = db.query(`SELECT strftime('%Y-%m-%d', time_created / 1000, 'unixepoch') as day,
141251
+ COALESCE(SUM(cost), 0) as cost
141252
+ FROM session
141253
+ WHERE time_created > ?
141254
+ GROUP BY day
141255
+ ORDER BY day ASC`).all(thirtyDaysAgoMs());
141256
+ const byDayMap = new Map;
141257
+ for (const r2 of byDayRows) {
141258
+ byDayMap.set(r2.day, r2.cost);
141259
+ }
141260
+ const byDay = [];
141261
+ const today = new Date;
141262
+ for (let i3 = 29;i3 >= 0; i3--) {
141263
+ const d = new Date(today);
141264
+ d.setDate(d.getDate() - i3);
141265
+ const key = d.toISOString().slice(0, 10);
141266
+ byDay.push({ date: key, cost: byDayMap.get(key) ?? 0 });
141267
+ }
141268
+ const budgetRemaining = Math.max(0, BUDGET_TOTAL - total);
141269
+ const alerts = [];
141270
+ if (total > BUDGET_TOTAL) {
141271
+ alerts.push({ severity: "critical", message: `Total cost $${total.toFixed(2)} exceeds budget $${BUDGET_TOTAL}` });
141272
+ } else if (total > BUDGET_TOTAL * 0.85) {
141273
+ alerts.push({ severity: "warning", message: `Cost $${total.toFixed(2)} approaching budget threshold (85%)` });
141274
+ }
141275
+ return { total, daily, monthly, budgetRemaining, byAgent, byDay, alerts };
141276
+ } catch {
141277
+ return {
141278
+ total: 0,
141279
+ daily: 0,
141280
+ monthly: 0,
141281
+ budgetRemaining: BUDGET_TOTAL,
141282
+ byAgent: [],
141283
+ byDay: [],
141284
+ alerts: []
141285
+ };
141286
+ } finally {
141287
+ db.close();
141288
+ }
141167
141289
  },
141168
141290
  async getKanbanTasks() {
141169
- return generateMockKanban();
141291
+ const board = { columns: { pending: [], in_progress: [], completed: [], failed: [] } };
141292
+ const db = getDb();
141293
+ if (!db)
141294
+ return board;
141295
+ try {
141296
+ const rows = db.query("SELECT content, status, priority, time_created, time_updated FROM todo ORDER BY time_updated DESC").all();
141297
+ let idx = 0;
141298
+ for (const row of rows) {
141299
+ const status2 = row.status;
141300
+ if (!board.columns[status2])
141301
+ continue;
141302
+ const task2 = {
141303
+ id: `todo_${idx++}`,
141304
+ title: row.content,
141305
+ agent: "Unknown",
141306
+ priority: row.priority ?? "medium",
141307
+ status: status2,
141308
+ createdAt: new Date(row.time_created).toISOString(),
141309
+ updatedAt: new Date(row.time_updated).toISOString()
141310
+ };
141311
+ board.columns[status2].push(task2);
141312
+ }
141313
+ } catch {} finally {
141314
+ db.close();
141315
+ }
141316
+ return board;
141170
141317
  },
141171
141318
  async getIncidents(limit = 50) {
141172
141319
  const lines = readJsonl("anti-loop.jsonl");
@@ -141190,7 +141337,33 @@ function createDataProvider(config4) {
141190
141337
  }).filter(Boolean);
141191
141338
  },
141192
141339
  async getMetrics() {
141193
- return generateMockMetrics();
141340
+ const db = getDb();
141341
+ let activeSessions = 0;
141342
+ if (db) {
141343
+ try {
141344
+ const cutoff = Date.now() - THIRTY_MIN_MS;
141345
+ const rows = db.query("SELECT COUNT(*) as count FROM session WHERE time_archived IS NULL AND time_updated > ?").all(cutoff);
141346
+ if (rows.length > 0)
141347
+ activeSessions = rows[0].count;
141348
+ } catch {} finally {
141349
+ db.close();
141350
+ }
141351
+ }
141352
+ const totalMem = os12.totalmem();
141353
+ const mem = process.memoryUsage();
141354
+ const memPercent = Math.round(mem.rss / totalMem * 100);
141355
+ const cpuPercent = Math.round(os12.loadavg()[0] * 100);
141356
+ const snapshots = [];
141357
+ for (let i3 = 0;i3 < 60; i3++) {
141358
+ snapshots.push({
141359
+ timestamp: Date.now() - (59 - i3) * 60000,
141360
+ cpuPercent,
141361
+ memoryPercent: memPercent,
141362
+ diskPercent: 0,
141363
+ sessionsActive: activeSessions
141364
+ });
141365
+ }
141366
+ return snapshots;
141194
141367
  },
141195
141368
  getLogs() {
141196
141369
  const logFiles = [
@@ -141537,7 +141710,7 @@ function createDashboardServer(dataProvider, config4) {
141537
141710
  // packages/omo-opencode/src/cli/dashboard.ts
141538
141711
  async function dashboardCli(options) {
141539
141712
  const port = options.port ?? 9123;
141540
- const host = options.host ?? "127.0.0.1";
141713
+ const host = options.host ?? "0.0.0.0";
141541
141714
  const frontendDir = path25.resolve(import.meta.dir, "../features/dashboard/frontend");
141542
141715
  console.log(`[dashboard] starting MaTrixOS dashboard on http://${host}:${port}`);
141543
141716
  console.log(`[dashboard] frontend: ${frontendDir}`);
@@ -141859,7 +142032,7 @@ function configureRuntimeCommands(program2) {
141859
142032
  const exitCode = await architectRollback({ ...options, id });
141860
142033
  process.exit(exitCode);
141861
142034
  });
141862
- program2.command("dashboard").description("Start the MaTrixOS web dashboard (port 9123)").option("-p, --port <number>", "HTTP port", "9123").option("--host <addr>", "Bind address", "127.0.0.1").option("--daemon", "Run in background (no Ctrl+C)").action(async (options) => {
142035
+ program2.command("dashboard").description("Start the MaTrixOS web dashboard (port 9123)").option("-p, --port <number>", "HTTP port", "9123").option("--host <addr>", "Bind address", "0.0.0.0").option("--daemon", "Run in background (no Ctrl+C)").action(async (options) => {
141863
142036
  const exitCode = await dashboardCli({
141864
142037
  port: parseInt(options.port ?? "9123", 10),
141865
142038
  host: options.host,
@@ -2145,7 +2145,7 @@ var package_default;
2145
2145
  var init_package = __esm(() => {
2146
2146
  package_default = {
2147
2147
  name: "@kl-c/matrixos",
2148
- version: "0.1.17",
2148
+ version: "0.1.19",
2149
2149
  description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
2150
2150
  main: "./dist/index.js",
2151
2151
  types: "dist/index.d.ts",
@@ -141086,101 +141086,63 @@ var AGENT_ROLES = {
141086
141086
  Neo: "Executor",
141087
141087
  Tank: "Deep Work"
141088
141088
  };
141089
+ var OPENCODE_DB_PATH = path24.resolve(os12.homedir(), ".local", "share", "opencode", "opencode.db");
141090
+ var THIRTY_MIN_MS = 30 * 60 * 1000;
141091
+ var FIVE_MIN_MS = 5 * 60 * 1000;
141092
+ var BUDGET_TOTAL = 5000;
141089
141093
  function randomBetween(min2, max2) {
141090
141094
  return Math.floor(Math.random() * (max2 - min2 + 1)) + min2;
141091
141095
  }
141092
141096
  function randomChoice(arr) {
141093
141097
  return arr[Math.floor(Math.random() * arr.length)];
141094
141098
  }
141095
- function generateMockAgents() {
141096
- return AGENT_NAMES.map((name2) => ({
141097
- name: name2,
141098
- role: AGENT_ROLES[name2] ?? "Agent",
141099
- status: randomChoice(["online", "online", "online", "idle", "idle", "offline"]),
141100
- sessions: randomBetween(0, 25),
141101
- uptime: randomBetween(100, 86400),
141102
- cpuPercent: randomBetween(2, 85),
141103
- memoryPercent: randomBetween(10, 75)
141104
- }));
141105
- }
141106
- function generateMockSessions(count) {
141107
- const models2 = ["deepseek-v4-flash-free", "gpt-5.5-pro", "claude-opus-4-7", "gemini-3.1-pro", "glm-5.2"];
141108
- return Array.from({ length: count }, (_2, i3) => ({
141109
- id: `ses_${randomBetween(1e5, 999999).toString(16)}`,
141110
- agent: randomChoice(AGENT_NAMES),
141111
- model: randomChoice(models2),
141112
- duration: randomBetween(5, 600),
141113
- cost: Math.round(randomBetween(1, 500) * 100) / 100,
141114
- status: randomChoice(["active", "completed", "completed", "completed", "failed", "timeout"]),
141115
- startedAt: new Date(Date.now() - randomBetween(0, 86400000)).toISOString()
141116
- }));
141099
+ function parseModel(modelRaw) {
141100
+ if (!modelRaw)
141101
+ return "unknown";
141102
+ try {
141103
+ const parsed = JSON.parse(modelRaw);
141104
+ if (parsed.id)
141105
+ return parsed.id;
141106
+ } catch {}
141107
+ return modelRaw;
141108
+ }
141109
+ function getDb() {
141110
+ if (!fs20.existsSync(OPENCODE_DB_PATH))
141111
+ return;
141112
+ try {
141113
+ return new Database5(OPENCODE_DB_PATH, { readonly: true });
141114
+ } catch {
141115
+ return;
141116
+ }
141117
141117
  }
141118
- function generateMockCost() {
141119
- const agents = AGENT_NAMES.map((name2) => ({
141120
- agent: name2,
141121
- cost: Math.round(randomBetween(50, 2000) * 100) / 100,
141122
- percentage: 0
141123
- }));
141124
- const total = agents.reduce((s, a2) => s + a2.cost, 0);
141125
- agents.forEach((a2) => {
141126
- a2.percentage = Math.round(a2.cost / total * 100);
141127
- });
141128
- return {
141129
- total: Math.round(total * 100) / 100,
141130
- daily: Math.round(randomBetween(50, 300) * 100) / 100,
141131
- monthly: Math.round(randomBetween(1500, 9000) * 100) / 100,
141132
- budgetRemaining: Math.round(randomBetween(500, 5000) * 100) / 100,
141133
- byAgent: agents,
141134
- byDay: Array.from({ length: 30 }, (_2, i3) => ({
141135
- date: new Date(Date.now() - (29 - i3) * 86400000).toISOString().slice(0, 10),
141136
- cost: Math.round(randomBetween(20, 300) * 100) / 100
141137
- })),
141138
- alerts: [
141139
- { severity: "warning", message: "Morpheus approaching budget threshold (85%)" },
141140
- { severity: "critical", message: "Tank exceeded daily budget cap ($500)" }
141141
- ]
141142
- };
141118
+ function midnightMs() {
141119
+ const d = new Date;
141120
+ d.setHours(0, 0, 0, 0);
141121
+ return d.getTime();
141143
141122
  }
141144
- function generateMockKanban() {
141145
- const statuses = ["pending", "in_progress", "completed", "failed"];
141146
- const columns = {};
141147
- for (const s of statuses) {
141148
- columns[s] = Array.from({ length: randomBetween(2, 6) }, (_2, i3) => ({
141149
- id: `task_${randomBetween(1000, 9999)}`,
141150
- title: randomChoice([
141151
- "Implement Watchdog daemon",
141152
- "Design System tokens",
141153
- "API rate limiting",
141154
- "Session persistence",
141155
- "User auth flow",
141156
- "Database migration",
141157
- "Cache invalidation",
141158
- "Webhook integration",
141159
- "Telegram notifications",
141160
- "Cost optimization",
141161
- "Security audit",
141162
- "Performance profiling"
141163
- ]),
141164
- agent: randomChoice(AGENT_NAMES),
141165
- priority: randomChoice(["low", "medium", "high", "critical"]),
141166
- status: s,
141167
- createdAt: new Date(Date.now() - randomBetween(0, 604800000)).toISOString(),
141168
- updatedAt: new Date(Date.now() - randomBetween(0, 86400000)).toISOString()
141169
- }));
141170
- }
141171
- return { columns };
141123
+ function thirtyDaysAgoMs() {
141124
+ return Date.now() - 30 * 24 * 60 * 60 * 1000;
141172
141125
  }
141173
- function generateMockMetrics() {
141174
- return Array.from({ length: 60 }, (_2, i3) => ({
141175
- timestamp: Date.now() - (59 - i3) * 60000,
141176
- cpuPercent: randomBetween(10, 95),
141177
- memoryPercent: randomBetween(30, 85),
141178
- diskPercent: randomBetween(40, 70),
141179
- sessionsActive: randomBetween(1, 8)
141180
- }));
141126
+ function readPackageVersion2() {
141127
+ try {
141128
+ const candidates = [
141129
+ new URL("../package.json", import.meta.url).pathname,
141130
+ new URL("../../package.json", import.meta.url).pathname,
141131
+ path24.resolve(process.cwd(), "package.json")
141132
+ ];
141133
+ for (const candidate of candidates) {
141134
+ if (fs20.existsSync(candidate)) {
141135
+ const pkg = JSON.parse(fs20.readFileSync(candidate, "utf-8"));
141136
+ if (pkg.version)
141137
+ return pkg.version;
141138
+ }
141139
+ }
141140
+ } catch {}
141141
+ return "0.0.0";
141181
141142
  }
141182
141143
  function createDataProvider(config4) {
141183
141144
  const matrixosHome = config4?.matrixosHome ?? ".matrixos";
141145
+ const version3 = readPackageVersion2();
141184
141146
  function readJsonl(filePath) {
141185
141147
  try {
141186
141148
  const fullPath = path24.resolve(matrixosHome, "logs", filePath);
@@ -141196,13 +141158,33 @@ function createDataProvider(config4) {
141196
141158
  async getHealth() {
141197
141159
  const mem = process.memoryUsage();
141198
141160
  const totalMem = os12.totalmem();
141161
+ const db = getDb();
141162
+ let agentsOnline = AGENT_NAMES.length;
141163
+ let activeSessions = 0;
141164
+ let tasksQueued = 0;
141165
+ if (db) {
141166
+ try {
141167
+ const agentRow = db.query("SELECT COUNT(DISTINCT agent) as count FROM session").get();
141168
+ if (agentRow)
141169
+ agentsOnline = agentRow.count;
141170
+ const cutoff = Date.now() - THIRTY_MIN_MS;
141171
+ const sessionRows = db.query("SELECT COUNT(*) as count FROM session WHERE time_archived IS NULL AND time_updated > ?").all(cutoff);
141172
+ if (sessionRows.length > 0)
141173
+ activeSessions = sessionRows[0].count;
141174
+ const todoRows = db.query("SELECT COUNT(*) as count FROM todo WHERE status = 'pending'").all();
141175
+ if (todoRows.length > 0)
141176
+ tasksQueued = todoRows[0].count;
141177
+ } catch {} finally {
141178
+ db.close();
141179
+ }
141180
+ }
141199
141181
  return {
141200
- agentsOnline: AGENT_NAMES.length - randomBetween(1, 3),
141182
+ agentsOnline,
141201
141183
  totalAgents: AGENT_NAMES.length,
141202
- activeSessions: randomBetween(2, 8),
141203
- tasksQueued: randomBetween(5, 20),
141184
+ activeSessions,
141185
+ tasksQueued,
141204
141186
  uptime: process.uptime(),
141205
- version: "0.1.0",
141187
+ version: version3,
141206
141188
  memoryUsage: {
141207
141189
  used: Math.round(mem.rss / 1024 / 1024),
141208
141190
  total: Math.round(totalMem / 1024 / 1024),
@@ -141212,16 +141194,181 @@ function createDataProvider(config4) {
141212
141194
  };
141213
141195
  },
141214
141196
  async getAgents() {
141215
- return generateMockAgents();
141197
+ const db = getDb();
141198
+ if (db) {
141199
+ try {
141200
+ const cutoff = Date.now() - THIRTY_MIN_MS;
141201
+ const rows = db.query(`SELECT agent, COUNT(*) as sessions
141202
+ FROM session
141203
+ WHERE agent IS NOT NULL AND agent != ''
141204
+ GROUP BY agent`).all();
141205
+ if (rows.length > 0) {
141206
+ const result = [];
141207
+ for (const row of rows) {
141208
+ const name2 = row.agent;
141209
+ const onlineRows = db.query("SELECT COUNT(*) as count FROM session WHERE agent = ? AND time_updated > ?").all(name2, cutoff);
141210
+ const status2 = onlineRows.length > 0 && onlineRows[0].count > 0 ? "online" : "idle";
141211
+ result.push({
141212
+ name: name2,
141213
+ role: AGENT_ROLES[name2] ?? "Agent",
141214
+ status: status2,
141215
+ sessions: row.sessions,
141216
+ uptime: 0,
141217
+ cpuPercent: 0,
141218
+ memoryPercent: 0
141219
+ });
141220
+ }
141221
+ db.close();
141222
+ return result;
141223
+ }
141224
+ } catch {} finally {
141225
+ db.close();
141226
+ }
141227
+ }
141228
+ return AGENT_NAMES.map((name2) => ({
141229
+ name: name2,
141230
+ role: AGENT_ROLES[name2] ?? "Agent",
141231
+ status: "idle",
141232
+ sessions: 0,
141233
+ uptime: 0,
141234
+ cpuPercent: 0,
141235
+ memoryPercent: 0
141236
+ }));
141216
141237
  },
141217
141238
  async getSessions(limit = 20) {
141218
- return generateMockSessions(limit).slice(0, limit);
141239
+ const db = getDb();
141240
+ if (!db)
141241
+ return [];
141242
+ try {
141243
+ const now = Date.now();
141244
+ const rows = db.query(`SELECT id, title, agent, model, cost, time_created, time_updated, time_archived
141245
+ FROM session
141246
+ ORDER BY time_updated DESC
141247
+ LIMIT ?`).all(limit);
141248
+ const result = [];
141249
+ for (const row of rows) {
141250
+ const duration3 = Math.max(0, Math.round((row.time_updated - row.time_created) / 1000));
141251
+ let status2 = "completed";
141252
+ if (row.time_archived !== null) {
141253
+ status2 = "completed";
141254
+ } else if (row.time_updated > now - FIVE_MIN_MS) {
141255
+ status2 = "active";
141256
+ } else {
141257
+ status2 = "completed";
141258
+ }
141259
+ result.push({
141260
+ id: row.id,
141261
+ agent: row.agent ?? "unknown",
141262
+ model: parseModel(row.model),
141263
+ duration: duration3,
141264
+ cost: row.cost,
141265
+ status: status2,
141266
+ startedAt: new Date(row.time_created).toISOString()
141267
+ });
141268
+ }
141269
+ return result;
141270
+ } catch {
141271
+ return [];
141272
+ } finally {
141273
+ db.close();
141274
+ }
141219
141275
  },
141220
141276
  async getCost() {
141221
- return generateMockCost();
141277
+ const db = getDb();
141278
+ if (!db) {
141279
+ return {
141280
+ total: 0,
141281
+ daily: 0,
141282
+ monthly: 0,
141283
+ budgetRemaining: BUDGET_TOTAL,
141284
+ byAgent: [],
141285
+ byDay: [],
141286
+ alerts: []
141287
+ };
141288
+ }
141289
+ try {
141290
+ const totalRows = db.query("SELECT COALESCE(SUM(cost), 0) as sum FROM session").all();
141291
+ const total = totalRows.length > 0 ? totalRows[0].sum ?? 0 : 0;
141292
+ const dailyRows = db.query("SELECT COALESCE(SUM(cost), 0) as sum FROM session WHERE time_created > ?").all(midnightMs());
141293
+ const daily = dailyRows.length > 0 ? dailyRows[0].sum ?? 0 : 0;
141294
+ const monthlyRows = db.query("SELECT COALESCE(SUM(cost), 0) as sum FROM session WHERE time_created > ?").all(thirtyDaysAgoMs());
141295
+ const monthly = monthlyRows.length > 0 ? monthlyRows[0].sum ?? 0 : 0;
141296
+ const agentRows = db.query(`SELECT agent, COALESCE(SUM(cost), 0) as cost
141297
+ FROM session
141298
+ WHERE agent IS NOT NULL AND agent != ''
141299
+ GROUP BY agent`).all();
141300
+ const byAgent = agentRows.map((r2) => ({
141301
+ agent: r2.agent,
141302
+ cost: r2.cost,
141303
+ percentage: total > 0 ? Math.round(r2.cost / total * 100) : 0
141304
+ }));
141305
+ const byDayRows = db.query(`SELECT strftime('%Y-%m-%d', time_created / 1000, 'unixepoch') as day,
141306
+ COALESCE(SUM(cost), 0) as cost
141307
+ FROM session
141308
+ WHERE time_created > ?
141309
+ GROUP BY day
141310
+ ORDER BY day ASC`).all(thirtyDaysAgoMs());
141311
+ const byDayMap = new Map;
141312
+ for (const r2 of byDayRows) {
141313
+ byDayMap.set(r2.day, r2.cost);
141314
+ }
141315
+ const byDay = [];
141316
+ const today = new Date;
141317
+ for (let i3 = 29;i3 >= 0; i3--) {
141318
+ const d = new Date(today);
141319
+ d.setDate(d.getDate() - i3);
141320
+ const key = d.toISOString().slice(0, 10);
141321
+ byDay.push({ date: key, cost: byDayMap.get(key) ?? 0 });
141322
+ }
141323
+ const budgetRemaining = Math.max(0, BUDGET_TOTAL - total);
141324
+ const alerts = [];
141325
+ if (total > BUDGET_TOTAL) {
141326
+ alerts.push({ severity: "critical", message: `Total cost $${total.toFixed(2)} exceeds budget $${BUDGET_TOTAL}` });
141327
+ } else if (total > BUDGET_TOTAL * 0.85) {
141328
+ alerts.push({ severity: "warning", message: `Cost $${total.toFixed(2)} approaching budget threshold (85%)` });
141329
+ }
141330
+ return { total, daily, monthly, budgetRemaining, byAgent, byDay, alerts };
141331
+ } catch {
141332
+ return {
141333
+ total: 0,
141334
+ daily: 0,
141335
+ monthly: 0,
141336
+ budgetRemaining: BUDGET_TOTAL,
141337
+ byAgent: [],
141338
+ byDay: [],
141339
+ alerts: []
141340
+ };
141341
+ } finally {
141342
+ db.close();
141343
+ }
141222
141344
  },
141223
141345
  async getKanbanTasks() {
141224
- return generateMockKanban();
141346
+ const board = { columns: { pending: [], in_progress: [], completed: [], failed: [] } };
141347
+ const db = getDb();
141348
+ if (!db)
141349
+ return board;
141350
+ try {
141351
+ const rows = db.query("SELECT content, status, priority, time_created, time_updated FROM todo ORDER BY time_updated DESC").all();
141352
+ let idx = 0;
141353
+ for (const row of rows) {
141354
+ const status2 = row.status;
141355
+ if (!board.columns[status2])
141356
+ continue;
141357
+ const task2 = {
141358
+ id: `todo_${idx++}`,
141359
+ title: row.content,
141360
+ agent: "Unknown",
141361
+ priority: row.priority ?? "medium",
141362
+ status: status2,
141363
+ createdAt: new Date(row.time_created).toISOString(),
141364
+ updatedAt: new Date(row.time_updated).toISOString()
141365
+ };
141366
+ board.columns[status2].push(task2);
141367
+ }
141368
+ } catch {} finally {
141369
+ db.close();
141370
+ }
141371
+ return board;
141225
141372
  },
141226
141373
  async getIncidents(limit = 50) {
141227
141374
  const lines = readJsonl("anti-loop.jsonl");
@@ -141245,7 +141392,33 @@ function createDataProvider(config4) {
141245
141392
  }).filter(Boolean);
141246
141393
  },
141247
141394
  async getMetrics() {
141248
- return generateMockMetrics();
141395
+ const db = getDb();
141396
+ let activeSessions = 0;
141397
+ if (db) {
141398
+ try {
141399
+ const cutoff = Date.now() - THIRTY_MIN_MS;
141400
+ const rows = db.query("SELECT COUNT(*) as count FROM session WHERE time_archived IS NULL AND time_updated > ?").all(cutoff);
141401
+ if (rows.length > 0)
141402
+ activeSessions = rows[0].count;
141403
+ } catch {} finally {
141404
+ db.close();
141405
+ }
141406
+ }
141407
+ const totalMem = os12.totalmem();
141408
+ const mem = process.memoryUsage();
141409
+ const memPercent = Math.round(mem.rss / totalMem * 100);
141410
+ const cpuPercent = Math.round(os12.loadavg()[0] * 100);
141411
+ const snapshots = [];
141412
+ for (let i3 = 0;i3 < 60; i3++) {
141413
+ snapshots.push({
141414
+ timestamp: Date.now() - (59 - i3) * 60000,
141415
+ cpuPercent,
141416
+ memoryPercent: memPercent,
141417
+ diskPercent: 0,
141418
+ sessionsActive: activeSessions
141419
+ });
141420
+ }
141421
+ return snapshots;
141249
141422
  },
141250
141423
  getLogs() {
141251
141424
  const logFiles = [
@@ -141592,7 +141765,7 @@ function createDashboardServer(dataProvider, config4) {
141592
141765
  // packages/omo-opencode/src/cli/dashboard.ts
141593
141766
  async function dashboardCli(options) {
141594
141767
  const port = options.port ?? 9123;
141595
- const host = options.host ?? "127.0.0.1";
141768
+ const host = options.host ?? "0.0.0.0";
141596
141769
  const frontendDir = path25.resolve(import.meta.dir, "../features/dashboard/frontend");
141597
141770
  console.log(`[dashboard] starting MaTrixOS dashboard on http://${host}:${port}`);
141598
141771
  console.log(`[dashboard] frontend: ${frontendDir}`);
@@ -141914,7 +142087,7 @@ function configureRuntimeCommands(program2) {
141914
142087
  const exitCode = await architectRollback({ ...options, id });
141915
142088
  process.exit(exitCode);
141916
142089
  });
141917
- program2.command("dashboard").description("Start the MaTrixOS web dashboard (port 9123)").option("-p, --port <number>", "HTTP port", "9123").option("--host <addr>", "Bind address", "127.0.0.1").option("--daemon", "Run in background (no Ctrl+C)").action(async (options) => {
142090
+ program2.command("dashboard").description("Start the MaTrixOS web dashboard (port 9123)").option("-p, --port <number>", "HTTP port", "9123").option("--host <addr>", "Bind address", "0.0.0.0").option("--daemon", "Run in background (no Ctrl+C)").action(async (options) => {
141918
142091
  const exitCode = await dashboardCli({
141919
142092
  port: parseInt(options.port ?? "9123", 10),
141920
142093
  host: options.host,
@@ -23,11 +23,13 @@
23
23
  <div class="sidebar-section">Operations</div>
24
24
  <a href="#" class="sidebar-item" data-tab="health"><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>Incidents<span class="sidebar-badge danger" id="badgeIncidents">3</span></a>
25
25
  <a href="#" class="sidebar-item" data-tab="logs"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M14 2H2v12h12V2z"/><path d="M5 8h6M5 11h4"/></svg>Logs</a>
26
- <a href="#" class="sidebar-item"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M8 14A6 6 0 108 2a6 6 0 000 12z"/><path d="M8 5v3l2 2"/></svg>Schedule</a>
26
+ <a href="#" class="sidebar-item" data-tab="schedule"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M8 14A6 6 0 108 2a6 6 0 000 12z"/><path d="M8 5v3l2 2"/></svg>Schedule</a>
27
+ <a href="#" class="sidebar-item" data-tab="memory"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><rect x="2" y="3" width="12" height="11" rx="1"/><path d="M2 6h12"/><circle cx="8" cy="10" r="1.5"/></svg>Memory</a>
28
+ <a href="#" class="sidebar-item" data-tab="skills"><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="6" r="3"/><path d="M3 14c0-3 2.5-5 5-5s5 2 5 5"/></svg>Skills</a>
27
29
  <div class="sidebar-section">System</div>
28
30
  <a href="#" class="sidebar-item" data-tab="config"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><rect x="2" y="2" width="12" height="12" rx="2"/><path d="M6 6h4M6 8h4M6 10h2"/></svg>Config</a>
29
- <a href="#" class="sidebar-item"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M12 8A4 4 0 114 8a4 4 0 018 0z"/><path d="M8 2v1M8 13v1M2 8h1M13 8h1"/></svg>Settings</a>
30
- <a href="#" class="sidebar-item"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M9 2H4a1 1 0 00-1 1v10a1 1 0 001 1h8a1 1 0 001-1V7l-5-5z"/><path d="M9 2v5h5"/></svg>Audit Trail</a>
31
+ <a href="#" class="sidebar-item" data-tab="config"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M12 8A4 4 0 114 8a4 4 0 018 0z"/><path d="M8 2v1M8 13v1M2 8h1M13 8h1"/></svg>Settings</a>
32
+ <a href="#" class="sidebar-item" data-tab="logs"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M9 2H4a1 1 0 00-1 1v10a1 1 0 001 1h8a1 1 0 001-1V7l-5-5z"/><path d="M9 2v5h5"/></svg>Audit Trail</a>
31
33
  </nav>
32
34
  <div class="sidebar-footer">
33
35
  <div class="sidebar-avatar">SM</div>
@@ -165,6 +167,13 @@
165
167
  </div>
166
168
  <div class="card"><div class="card-header"><span class="card-title">matrixos.jsonc</span><span id="configStatus" style="font-size:var(--text-xs);color:var(--text-tertiary)"></span></div><div class="card-body"><textarea id="configEditor" class="config-editor" spellcheck="false"></textarea></div></div>
167
169
  </div>
170
+
171
+ <div id="tab-schedule" class="tab-panel">
172
+ <div class="page-header">
173
+ <div><h1 class="page-title">Schedule</h1><p class="page-subtitle">Cron jobs and scheduled tasks for MaTrixOS agents</p></div>
174
+ </div>
175
+ <div class="card"><div class="card-body" id="scheduleBody"></div></div>
176
+ </div>
168
177
  </div>
169
178
  </div>
170
179
  <script src="js/api.js"></script>
@@ -10,7 +10,7 @@ document.querySelectorAll('[data-tab]').forEach(el=>{
10
10
  el.addEventListener('click',e=>{
11
11
  e.preventDefault()
12
12
  const tab=el.dataset.tab
13
- if(!tab||!['architect','health','cost','kanban','agents','sessions','logs','config'].includes(tab))return
13
+ if(!tab||!['architect','health','cost','kanban','agents','sessions','logs','config','memory','skills','schedule'].includes(tab))return
14
14
  const realTab=tab==='agents'||tab==='sessions'?'architect':tab
15
15
  document.querySelectorAll('.sidebar-item.active,.header-tab.active,.tab-panel.active').forEach(n=>n.classList.remove('active'))
16
16
  document.querySelectorAll(`.sidebar-item[data-tab="${tab}"],.header-tab[data-tab="${realTab}"]`).forEach(n=>n.classList.add('active'))
@@ -20,7 +20,7 @@ document.querySelectorAll('[data-tab]').forEach(el=>{
20
20
  })
21
21
 
22
22
  // Tab loading dispatch
23
- function loadTab(tab){const f={architect:loadArchitect,health:loadHealth,cost:loadCost,kanban:loadKanban,logs:loadLogs,config:loadConfig,memory:loadMemory,skills:loadSkills}[tab];f&&f()}
23
+ function loadTab(tab){const f={architect:loadArchitect,health:loadHealth,cost:loadCost,kanban:loadKanban,logs:loadLogs,config:loadConfig,memory:loadMemory,skills:loadSkills,schedule:loadSchedule}[tab];f&&f()}
24
24
 
25
25
  // Skeleton helpers
26
26
  function showSkeleton(container,type,count=4){
@@ -338,6 +338,16 @@ async function loadSkills(){
338
338
  }catch(e){grid.innerHTML=`<div class="error"><p>Failed to load skills: ${e.message}</p></div>`}
339
339
  }
340
340
 
341
+ // ===== SCHEDULE =====
342
+ function loadSchedule(){
343
+ const body=document.getElementById('scheduleBody')
344
+ if(!body)return
345
+ body.innerHTML=`<div class="empty" style="padding:40px">
346
+ <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
347
+ <p>Schedule feature not configured — enable cron in matrixos.jsonc to start scheduling agent tasks.</p>
348
+ </div>`
349
+ }
350
+
341
351
  // ===== INIT =====
342
352
  document.getElementById('refreshBtn').onclick=()=>{const t=document.querySelector('.header-tab.active');t&&loadTab(t.dataset.tab)}
343
353
  document.getElementById('archRefresh').onclick=()=>loadArchitect()
package/dist/index.js CHANGED
@@ -367932,7 +367932,7 @@ function getCachedVersion(options = {}) {
367932
367932
  // package.json
367933
367933
  var package_default = {
367934
367934
  name: "@kl-c/matrixos",
367935
- version: "0.1.17",
367935
+ version: "0.1.19",
367936
367936
  description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
367937
367937
  main: "./dist/index.js",
367938
367938
  types: "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kl-c/matrixos",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "MaTrixOS — Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "dist/index.d.ts",