@kl-c/matrixos 0.3.26 → 0.3.28
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 +368 -9
- package/dist/cli/service.d.ts +6 -0
- package/dist/cli-node/index.js +368 -9
- package/dist/features/dashboard/data-provider.d.ts +23 -0
- package/dist/features/dashboard/frontend/css/style.css +17 -0
- package/dist/features/dashboard/frontend/js/api.js +22 -2
- package/dist/features/dashboard/frontend/js/app.js +101 -10
- package/dist/index.js +1 -1
- package/package.json +1 -1
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.28",
|
|
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",
|
|
@@ -167053,6 +167053,226 @@ function executeRgpdConsentCommand(args) {
|
|
|
167053
167053
|
}
|
|
167054
167054
|
}
|
|
167055
167055
|
|
|
167056
|
+
// packages/omo-opencode/src/cli/service.ts
|
|
167057
|
+
var exports_service = {};
|
|
167058
|
+
__export(exports_service, {
|
|
167059
|
+
serviceInstallCommand: () => serviceInstallCommand
|
|
167060
|
+
});
|
|
167061
|
+
import * as os15 from "os";
|
|
167062
|
+
import * as fs24 from "fs";
|
|
167063
|
+
import * as path29 from "path";
|
|
167064
|
+
import { execSync as execSync3 } from "child_process";
|
|
167065
|
+
function resolveMatrixosBin2() {
|
|
167066
|
+
try {
|
|
167067
|
+
const p2 = execSync3("command -v matrixos", { encoding: "utf-8" }).trim();
|
|
167068
|
+
if (p2)
|
|
167069
|
+
return p2;
|
|
167070
|
+
} catch {}
|
|
167071
|
+
for (const cand of ["/usr/local/bin/matrixos", "/usr/bin/matrixos", path29.join(os15.homedir(), ".bun/bin/matrixos")]) {
|
|
167072
|
+
if (fs24.existsSync(cand))
|
|
167073
|
+
return cand;
|
|
167074
|
+
}
|
|
167075
|
+
return "matrixos";
|
|
167076
|
+
}
|
|
167077
|
+
function resolveBunBin() {
|
|
167078
|
+
try {
|
|
167079
|
+
const p2 = execSync3("command -v bun", { encoding: "utf-8" }).trim();
|
|
167080
|
+
if (p2)
|
|
167081
|
+
return p2;
|
|
167082
|
+
} catch {}
|
|
167083
|
+
return "/usr/bin/bun";
|
|
167084
|
+
}
|
|
167085
|
+
function writeFileEnsureDir(filePath, content) {
|
|
167086
|
+
fs24.mkdirSync(path29.dirname(filePath), { recursive: true });
|
|
167087
|
+
fs24.writeFileSync(filePath, content, "utf-8");
|
|
167088
|
+
console.log(`[service] written: ${filePath}`);
|
|
167089
|
+
}
|
|
167090
|
+
function installSystemd(opts) {
|
|
167091
|
+
const bin = resolveMatrixosBin2();
|
|
167092
|
+
const bun = resolveBunBin();
|
|
167093
|
+
const scope = opts.user ? "--user" : "";
|
|
167094
|
+
const unitDir = opts.user ? path29.join(os15.homedir(), ".config", "systemd", "user") : "/etc/systemd/system";
|
|
167095
|
+
const envPath = `/usr/local/bin:/usr/bin:/bin:${path29.dirname(bun)}`;
|
|
167096
|
+
if (opts.dashboard !== false) {
|
|
167097
|
+
const unit = `[Unit]
|
|
167098
|
+
Description=MaTrixOS Dashboard
|
|
167099
|
+
After=network.target
|
|
167100
|
+
|
|
167101
|
+
[Service]
|
|
167102
|
+
Type=simple
|
|
167103
|
+
User=${os15.userInfo().username}
|
|
167104
|
+
WorkingDirectory=${os15.homedir()}
|
|
167105
|
+
Environment=PATH=${envPath}
|
|
167106
|
+
Environment=HOME=${os15.homedir()}
|
|
167107
|
+
ExecStart=${bin} dashboard --host 0.0.0.0 --daemon
|
|
167108
|
+
Restart=always
|
|
167109
|
+
RestartSec=5
|
|
167110
|
+
|
|
167111
|
+
[Install]
|
|
167112
|
+
WantedBy=${opts.user ? "default.target" : "multi-user.target"}
|
|
167113
|
+
`;
|
|
167114
|
+
writeFileEnsureDir(path29.join(unitDir, "matrixos-dashboard.service"), unit);
|
|
167115
|
+
}
|
|
167116
|
+
if (opts.gateway !== false) {
|
|
167117
|
+
const unit = `[Unit]
|
|
167118
|
+
Description=MaTrixOS Telegram Gateway
|
|
167119
|
+
After=network.target
|
|
167120
|
+
|
|
167121
|
+
[Service]
|
|
167122
|
+
Type=simple
|
|
167123
|
+
User=${os15.userInfo().username}
|
|
167124
|
+
WorkingDirectory=${os15.homedir()}
|
|
167125
|
+
Environment=PATH=${envPath}
|
|
167126
|
+
Environment=HOME=${os15.homedir()}
|
|
167127
|
+
ExecStart=${bin} gateway start --command "${bin} run"
|
|
167128
|
+
Restart=always
|
|
167129
|
+
RestartSec=5
|
|
167130
|
+
|
|
167131
|
+
[Install]
|
|
167132
|
+
WantedBy=${opts.user ? "default.target" : "multi-user.target"}
|
|
167133
|
+
`;
|
|
167134
|
+
writeFileEnsureDir(path29.join(unitDir, "matrixos-gateway.service"), unit);
|
|
167135
|
+
}
|
|
167136
|
+
console.log("[service] reloading systemd...");
|
|
167137
|
+
if (scope) {
|
|
167138
|
+
execSync3(`${scope} systemctl --user daemon-reload`, { stdio: "inherit" });
|
|
167139
|
+
if (opts.dashboard !== false)
|
|
167140
|
+
execSync3(`${scope} systemctl --user enable matrixos-dashboard.service`, { stdio: "inherit" });
|
|
167141
|
+
if (opts.gateway !== false)
|
|
167142
|
+
execSync3(`${scope} systemctl --user enable matrixos-gateway.service`, { stdio: "inherit" });
|
|
167143
|
+
if (opts.dashboard !== false)
|
|
167144
|
+
execSync3(`${scope} systemctl --user start matrixos-dashboard.service`, { stdio: "inherit" });
|
|
167145
|
+
if (opts.gateway !== false)
|
|
167146
|
+
execSync3(`${scope} systemctl --user start matrixos-gateway.service`, { stdio: "inherit" });
|
|
167147
|
+
} else {
|
|
167148
|
+
execSync3("systemctl daemon-reload", { stdio: "inherit" });
|
|
167149
|
+
if (opts.dashboard !== false)
|
|
167150
|
+
execSync3("systemctl enable matrixos-dashboard.service", { stdio: "inherit" });
|
|
167151
|
+
if (opts.gateway !== false)
|
|
167152
|
+
execSync3("systemctl enable matrixos-gateway.service", { stdio: "inherit" });
|
|
167153
|
+
if (opts.dashboard !== false)
|
|
167154
|
+
execSync3("systemctl start matrixos-dashboard.service", { stdio: "inherit" });
|
|
167155
|
+
if (opts.gateway !== false)
|
|
167156
|
+
execSync3("systemctl start matrixos-gateway.service", { stdio: "inherit" });
|
|
167157
|
+
}
|
|
167158
|
+
console.log("[service] systemd units installed and started.");
|
|
167159
|
+
}
|
|
167160
|
+
function installLaunchd(opts) {
|
|
167161
|
+
const bin = resolveMatrixosBin2();
|
|
167162
|
+
const bun = resolveBunBin();
|
|
167163
|
+
const launchDir = path29.join(os15.homedir(), "Library", "LaunchAgents");
|
|
167164
|
+
const envPath = `/usr/local/bin:/usr/bin:/bin:${path29.dirname(bun)}`;
|
|
167165
|
+
if (opts.dashboard !== false) {
|
|
167166
|
+
const label = "com.klc.matrixos.dashboard";
|
|
167167
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
167168
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
167169
|
+
<plist version="1.0">
|
|
167170
|
+
<dict>
|
|
167171
|
+
<key>Label</key>
|
|
167172
|
+
<string>${label}</string>
|
|
167173
|
+
<key>ProgramArguments</key>
|
|
167174
|
+
<array>
|
|
167175
|
+
<string>${bin}</string>
|
|
167176
|
+
<string>dashboard</string>
|
|
167177
|
+
<string>--host</string>
|
|
167178
|
+
<string>0.0.0.0</string>
|
|
167179
|
+
<string>--daemon</string>
|
|
167180
|
+
</array>
|
|
167181
|
+
<key>WorkingDirectory</key>
|
|
167182
|
+
<string>${os15.homedir()}</string>
|
|
167183
|
+
<key>EnvironmentVariables</key>
|
|
167184
|
+
<dict>
|
|
167185
|
+
<key>PATH</key>
|
|
167186
|
+
<string>${envPath}</string>
|
|
167187
|
+
<key>HOME</key>
|
|
167188
|
+
<string>${os15.homedir()}</string>
|
|
167189
|
+
</dict>
|
|
167190
|
+
<key>RunAtLoad</key>
|
|
167191
|
+
<true/>
|
|
167192
|
+
<key>KeepAlive</key>
|
|
167193
|
+
<true/>
|
|
167194
|
+
<key>StandardOutPath</key>
|
|
167195
|
+
<string>${os15.homedir()}/Library/Logs/matrixos-dashboard.log</string>
|
|
167196
|
+
<key>StandardErrorPath</key>
|
|
167197
|
+
<string>${os15.homedir()}/Library/Logs/matrixos-dashboard.log</string>
|
|
167198
|
+
</dict>
|
|
167199
|
+
</plist>
|
|
167200
|
+
`;
|
|
167201
|
+
writeFileEnsureDir(path29.join(launchDir, `${label}.plist`), plist);
|
|
167202
|
+
execSync3(`launchctl load ${path29.join(launchDir, `${label}.plist`)}`, { stdio: "inherit" });
|
|
167203
|
+
}
|
|
167204
|
+
if (opts.gateway !== false) {
|
|
167205
|
+
const label = "com.klc.matrixos.gateway";
|
|
167206
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
167207
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
167208
|
+
<plist version="1.0">
|
|
167209
|
+
<dict>
|
|
167210
|
+
<key>Label</key>
|
|
167211
|
+
<string>${label}</string>
|
|
167212
|
+
<key>ProgramArguments</key>
|
|
167213
|
+
<array>
|
|
167214
|
+
<string>${bin}</string>
|
|
167215
|
+
<string>gateway</string>
|
|
167216
|
+
<string>start</string>
|
|
167217
|
+
<string>--command</string>
|
|
167218
|
+
<string>${bin} run</string>
|
|
167219
|
+
</array>
|
|
167220
|
+
<key>WorkingDirectory</key>
|
|
167221
|
+
<string>${os15.homedir()}</string>
|
|
167222
|
+
<key>EnvironmentVariables</key>
|
|
167223
|
+
<dict>
|
|
167224
|
+
<key>PATH</key>
|
|
167225
|
+
<string>${envPath}</string>
|
|
167226
|
+
<key>HOME</key>
|
|
167227
|
+
<string>${os15.homedir()}</string>
|
|
167228
|
+
</dict>
|
|
167229
|
+
<key>RunAtLoad</key>
|
|
167230
|
+
<true/>
|
|
167231
|
+
<key>KeepAlive</key>
|
|
167232
|
+
<true/>
|
|
167233
|
+
<key>StandardOutPath</key>
|
|
167234
|
+
<string>${os15.homedir()}/Library/Logs/matrixos-gateway.log</string>
|
|
167235
|
+
<key>StandardErrorPath</key>
|
|
167236
|
+
<string>${os15.homedir()}/Library/Logs/matrixos-gateway.log</string>
|
|
167237
|
+
</dict>
|
|
167238
|
+
</plist>
|
|
167239
|
+
`;
|
|
167240
|
+
writeFileEnsureDir(path29.join(launchDir, `${label}.plist`), plist);
|
|
167241
|
+
execSync3(`launchctl load ${path29.join(launchDir, `${label}.plist`)}`, { stdio: "inherit" });
|
|
167242
|
+
}
|
|
167243
|
+
console.log("[service] launchd agents installed and loaded.");
|
|
167244
|
+
}
|
|
167245
|
+
function installWindowsNote() {
|
|
167246
|
+
console.log("[service] Windows: no auto-service installer yet.");
|
|
167247
|
+
console.log(" Use Task Scheduler to run `matrixos dashboard --host 0.0.0.0 --daemon`");
|
|
167248
|
+
console.log(' and `matrixos gateway start --command "matrixos run"` at logon.');
|
|
167249
|
+
console.log(" Or run them in the background via a startup script.");
|
|
167250
|
+
}
|
|
167251
|
+
async function serviceInstallCommand(options) {
|
|
167252
|
+
const platform2 = process.platform;
|
|
167253
|
+
console.log(`[service] detected platform: ${platform2}`);
|
|
167254
|
+
if (platform2 === "linux") {
|
|
167255
|
+
if (!fs24.existsSync("/run/systemd/system") && !fs24.existsSync("/etc/systemd/system")) {
|
|
167256
|
+
console.error("[service] systemd not detected \u2014 cannot install service automatically.");
|
|
167257
|
+
console.error(" Start manually: matrixos dashboard --host 0.0.0.0 --daemon");
|
|
167258
|
+
return 1;
|
|
167259
|
+
}
|
|
167260
|
+
installSystemd(options);
|
|
167261
|
+
return 0;
|
|
167262
|
+
}
|
|
167263
|
+
if (platform2 === "darwin") {
|
|
167264
|
+
installLaunchd(options);
|
|
167265
|
+
return 0;
|
|
167266
|
+
}
|
|
167267
|
+
if (platform2 === "win32") {
|
|
167268
|
+
installWindowsNote();
|
|
167269
|
+
return 0;
|
|
167270
|
+
}
|
|
167271
|
+
console.error(`[service] unsupported platform: ${platform2}`);
|
|
167272
|
+
return 1;
|
|
167273
|
+
}
|
|
167274
|
+
var init_service = () => {};
|
|
167275
|
+
|
|
167056
167276
|
// node_modules/.bun/commander@14.0.3/node_modules/commander/esm.mjs
|
|
167057
167277
|
var import__ = __toESM(require_commander(), 1);
|
|
167058
167278
|
var {
|
|
@@ -186709,6 +186929,30 @@ function getDb() {
|
|
|
186709
186929
|
return;
|
|
186710
186930
|
}
|
|
186711
186931
|
}
|
|
186932
|
+
function getDbWrite() {
|
|
186933
|
+
if (!fs21.existsSync(OPENCODE_DB_PATH))
|
|
186934
|
+
return;
|
|
186935
|
+
try {
|
|
186936
|
+
const db = new Database5(OPENCODE_DB_PATH);
|
|
186937
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
186938
|
+
return db;
|
|
186939
|
+
} catch {
|
|
186940
|
+
return;
|
|
186941
|
+
}
|
|
186942
|
+
}
|
|
186943
|
+
function ensureKanbanTable(db) {
|
|
186944
|
+
db.exec(`
|
|
186945
|
+
CREATE TABLE IF NOT EXISTS matrixos_kanban (
|
|
186946
|
+
id TEXT PRIMARY KEY,
|
|
186947
|
+
title TEXT NOT NULL,
|
|
186948
|
+
agent TEXT NOT NULL DEFAULT 'Unknown',
|
|
186949
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
186950
|
+
priority TEXT NOT NULL DEFAULT 'medium',
|
|
186951
|
+
created_at INTEGER NOT NULL,
|
|
186952
|
+
updated_at INTEGER NOT NULL
|
|
186953
|
+
)
|
|
186954
|
+
`);
|
|
186955
|
+
}
|
|
186712
186956
|
function midnightMs() {
|
|
186713
186957
|
const d = new Date;
|
|
186714
186958
|
d.setHours(0, 0, 0, 0);
|
|
@@ -186971,24 +187215,24 @@ function createDataProvider(config5) {
|
|
|
186971
187215
|
},
|
|
186972
187216
|
async getKanbanTasks() {
|
|
186973
187217
|
const board = { columns: { pending: [], in_progress: [], completed: [], failed: [] } };
|
|
186974
|
-
const db =
|
|
187218
|
+
const db = getDbWrite();
|
|
186975
187219
|
if (!db)
|
|
186976
187220
|
return board;
|
|
186977
187221
|
try {
|
|
186978
|
-
|
|
186979
|
-
|
|
187222
|
+
ensureKanbanTable(db);
|
|
187223
|
+
const rows = db.query("SELECT id, title, agent, status, priority, created_at, updated_at FROM matrixos_kanban ORDER BY updated_at DESC").all();
|
|
186980
187224
|
for (const row of rows) {
|
|
186981
187225
|
const status2 = row.status;
|
|
186982
187226
|
if (!board.columns[status2])
|
|
186983
187227
|
continue;
|
|
186984
187228
|
const task2 = {
|
|
186985
|
-
id:
|
|
186986
|
-
title: row.
|
|
186987
|
-
agent: "Unknown",
|
|
187229
|
+
id: row.id,
|
|
187230
|
+
title: row.title,
|
|
187231
|
+
agent: row.agent || "Unknown",
|
|
186988
187232
|
priority: row.priority ?? "medium",
|
|
186989
187233
|
status: status2,
|
|
186990
|
-
createdAt: new Date(row.
|
|
186991
|
-
updatedAt: new Date(row.
|
|
187234
|
+
createdAt: new Date(row.created_at).toISOString(),
|
|
187235
|
+
updatedAt: new Date(row.updated_at).toISOString()
|
|
186992
187236
|
};
|
|
186993
187237
|
board.columns[status2].push(task2);
|
|
186994
187238
|
}
|
|
@@ -186997,6 +187241,76 @@ function createDataProvider(config5) {
|
|
|
186997
187241
|
}
|
|
186998
187242
|
return board;
|
|
186999
187243
|
},
|
|
187244
|
+
async createKanbanTask(input) {
|
|
187245
|
+
const db = getDbWrite();
|
|
187246
|
+
if (!db)
|
|
187247
|
+
return { ok: false, error: "database unavailable" };
|
|
187248
|
+
try {
|
|
187249
|
+
ensureKanbanTable(db);
|
|
187250
|
+
const id = `kb_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
187251
|
+
const now = Date.now();
|
|
187252
|
+
const status2 = input.status ?? "pending";
|
|
187253
|
+
const priority = input.priority ?? "medium";
|
|
187254
|
+
db.query("INSERT INTO matrixos_kanban (id, title, agent, status, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)").run(id, input.title, input.agent ?? "Unknown", status2, priority, now, now);
|
|
187255
|
+
return { ok: true, id };
|
|
187256
|
+
} catch (e) {
|
|
187257
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
187258
|
+
} finally {
|
|
187259
|
+
db.close();
|
|
187260
|
+
}
|
|
187261
|
+
},
|
|
187262
|
+
async updateKanbanTask(id, input) {
|
|
187263
|
+
const db = getDbWrite();
|
|
187264
|
+
if (!db)
|
|
187265
|
+
return { ok: false, error: "database unavailable" };
|
|
187266
|
+
try {
|
|
187267
|
+
ensureKanbanTable(db);
|
|
187268
|
+
const existing = db.query("SELECT id FROM matrixos_kanban WHERE id = ?").get(id);
|
|
187269
|
+
if (!existing)
|
|
187270
|
+
return { ok: false, error: "task not found" };
|
|
187271
|
+
const sets = [];
|
|
187272
|
+
const params = [];
|
|
187273
|
+
if (input.title !== undefined) {
|
|
187274
|
+
sets.push("title = ?");
|
|
187275
|
+
params.push(input.title);
|
|
187276
|
+
}
|
|
187277
|
+
if (input.agent !== undefined) {
|
|
187278
|
+
sets.push("agent = ?");
|
|
187279
|
+
params.push(input.agent);
|
|
187280
|
+
}
|
|
187281
|
+
if (input.status !== undefined) {
|
|
187282
|
+
sets.push("status = ?");
|
|
187283
|
+
params.push(input.status);
|
|
187284
|
+
}
|
|
187285
|
+
if (input.priority !== undefined) {
|
|
187286
|
+
sets.push("priority = ?");
|
|
187287
|
+
params.push(input.priority);
|
|
187288
|
+
}
|
|
187289
|
+
sets.push("updated_at = ?");
|
|
187290
|
+
params.push(String(Date.now()));
|
|
187291
|
+
params.push(id);
|
|
187292
|
+
db.query(`UPDATE matrixos_kanban SET ${sets.join(", ")} WHERE id = ?`).run(...params);
|
|
187293
|
+
return { ok: true };
|
|
187294
|
+
} catch (e) {
|
|
187295
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
187296
|
+
} finally {
|
|
187297
|
+
db.close();
|
|
187298
|
+
}
|
|
187299
|
+
},
|
|
187300
|
+
async deleteKanbanTask(id) {
|
|
187301
|
+
const db = getDbWrite();
|
|
187302
|
+
if (!db)
|
|
187303
|
+
return { ok: false, error: "database unavailable" };
|
|
187304
|
+
try {
|
|
187305
|
+
ensureKanbanTable(db);
|
|
187306
|
+
db.query("DELETE FROM matrixos_kanban WHERE id = ?").run(id);
|
|
187307
|
+
return { ok: true };
|
|
187308
|
+
} catch (e) {
|
|
187309
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
187310
|
+
} finally {
|
|
187311
|
+
db.close();
|
|
187312
|
+
}
|
|
187313
|
+
},
|
|
187000
187314
|
async getIncidents(limit = 50) {
|
|
187001
187315
|
const lines = readJsonl("anti-loop.jsonl");
|
|
187002
187316
|
if (lines.length === 0) {
|
|
@@ -187310,6 +187624,34 @@ function createDashboardServer(dataProvider, config5) {
|
|
|
187310
187624
|
return Response.json(await dataProvider.getCost(), { headers: jsonHeaders });
|
|
187311
187625
|
case "/api/kanban":
|
|
187312
187626
|
return Response.json(await dataProvider.getKanbanTasks(), { headers: jsonHeaders });
|
|
187627
|
+
case "/api/kanban/task": {
|
|
187628
|
+
if (req.method === "POST") {
|
|
187629
|
+
const body = await req.json();
|
|
187630
|
+
if (!body.title || !body.title.trim()) {
|
|
187631
|
+
return Response.json({ ok: false, error: "title required" }, { status: 400, headers: jsonHeaders });
|
|
187632
|
+
}
|
|
187633
|
+
const result = await dataProvider.createKanbanTask(body);
|
|
187634
|
+
return Response.json(result, { status: result.ok ? 201 : 500, headers: jsonHeaders });
|
|
187635
|
+
}
|
|
187636
|
+
if (req.method === "PUT") {
|
|
187637
|
+
const body = await req.json();
|
|
187638
|
+
if (!body.id) {
|
|
187639
|
+
return Response.json({ ok: false, error: "id required" }, { status: 400, headers: jsonHeaders });
|
|
187640
|
+
}
|
|
187641
|
+
const result = await dataProvider.updateKanbanTask(body.id, body);
|
|
187642
|
+
return Response.json(result, { status: result.ok ? 200 : 500, headers: jsonHeaders });
|
|
187643
|
+
}
|
|
187644
|
+
if (req.method === "DELETE") {
|
|
187645
|
+
const url22 = new URL(req.url);
|
|
187646
|
+
const id = url22.searchParams.get("id");
|
|
187647
|
+
if (!id) {
|
|
187648
|
+
return Response.json({ ok: false, error: "id required" }, { status: 400, headers: jsonHeaders });
|
|
187649
|
+
}
|
|
187650
|
+
const result = await dataProvider.deleteKanbanTask(id);
|
|
187651
|
+
return Response.json(result, { status: result.ok ? 200 : 500, headers: jsonHeaders });
|
|
187652
|
+
}
|
|
187653
|
+
return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
|
|
187654
|
+
}
|
|
187313
187655
|
case "/api/incidents": {
|
|
187314
187656
|
const limit = parseInt(url3.searchParams.get("limit") ?? "50", 10);
|
|
187315
187657
|
return Response.json(await dataProvider.getIncidents(limit), { headers: jsonHeaders });
|
|
@@ -188224,6 +188566,23 @@ Examples:
|
|
|
188224
188566
|
process.stdout.write(result.stdout);
|
|
188225
188567
|
process.exit(result.exitCode);
|
|
188226
188568
|
});
|
|
188569
|
+
program2.command("service").description("Install MaTrixOS as a persistent OS service (dashboard + gateway)").argument("<action>", "install | uninstall").option("--no-dashboard", "Skip dashboard service").option("--no-gateway", "Skip gateway service").option("--user", "Install as current user (systemd --user / launchd user agent)").action(async (action, options) => {
|
|
188570
|
+
if (action !== "install" && action !== "uninstall") {
|
|
188571
|
+
console.error(`[service] unknown action: ${action}. Use 'install' or 'uninstall'.`);
|
|
188572
|
+
process.exit(1);
|
|
188573
|
+
}
|
|
188574
|
+
if (action === "uninstall") {
|
|
188575
|
+
console.log("[service] uninstall not yet implemented \u2014 remove units manually (systemctl disable / launchctl unload).");
|
|
188576
|
+
process.exit(0);
|
|
188577
|
+
}
|
|
188578
|
+
const { serviceInstallCommand: serviceInstallCommand2 } = await Promise.resolve().then(() => (init_service(), exports_service));
|
|
188579
|
+
const exitCode = await serviceInstallCommand2({
|
|
188580
|
+
dashboard: options.dashboard ?? true,
|
|
188581
|
+
gateway: options.gateway ?? true,
|
|
188582
|
+
user: options.user ?? false
|
|
188583
|
+
});
|
|
188584
|
+
process.exit(exitCode);
|
|
188585
|
+
});
|
|
188227
188586
|
|
|
188228
188587
|
// packages/omo-opencode/src/cli/index.ts
|
|
188229
188588
|
runCli();
|
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.28",
|
|
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",
|
|
@@ -167108,6 +167108,226 @@ function executeRgpdConsentCommand(args) {
|
|
|
167108
167108
|
}
|
|
167109
167109
|
}
|
|
167110
167110
|
|
|
167111
|
+
// packages/omo-opencode/src/cli/service.ts
|
|
167112
|
+
var exports_service = {};
|
|
167113
|
+
__export(exports_service, {
|
|
167114
|
+
serviceInstallCommand: () => serviceInstallCommand
|
|
167115
|
+
});
|
|
167116
|
+
import * as os15 from "os";
|
|
167117
|
+
import * as fs24 from "fs";
|
|
167118
|
+
import * as path29 from "path";
|
|
167119
|
+
import { execSync as execSync3 } from "child_process";
|
|
167120
|
+
function resolveMatrixosBin2() {
|
|
167121
|
+
try {
|
|
167122
|
+
const p2 = execSync3("command -v matrixos", { encoding: "utf-8" }).trim();
|
|
167123
|
+
if (p2)
|
|
167124
|
+
return p2;
|
|
167125
|
+
} catch {}
|
|
167126
|
+
for (const cand of ["/usr/local/bin/matrixos", "/usr/bin/matrixos", path29.join(os15.homedir(), ".bun/bin/matrixos")]) {
|
|
167127
|
+
if (fs24.existsSync(cand))
|
|
167128
|
+
return cand;
|
|
167129
|
+
}
|
|
167130
|
+
return "matrixos";
|
|
167131
|
+
}
|
|
167132
|
+
function resolveBunBin() {
|
|
167133
|
+
try {
|
|
167134
|
+
const p2 = execSync3("command -v bun", { encoding: "utf-8" }).trim();
|
|
167135
|
+
if (p2)
|
|
167136
|
+
return p2;
|
|
167137
|
+
} catch {}
|
|
167138
|
+
return "/usr/bin/bun";
|
|
167139
|
+
}
|
|
167140
|
+
function writeFileEnsureDir(filePath, content) {
|
|
167141
|
+
fs24.mkdirSync(path29.dirname(filePath), { recursive: true });
|
|
167142
|
+
fs24.writeFileSync(filePath, content, "utf-8");
|
|
167143
|
+
console.log(`[service] written: ${filePath}`);
|
|
167144
|
+
}
|
|
167145
|
+
function installSystemd(opts) {
|
|
167146
|
+
const bin = resolveMatrixosBin2();
|
|
167147
|
+
const bun = resolveBunBin();
|
|
167148
|
+
const scope = opts.user ? "--user" : "";
|
|
167149
|
+
const unitDir = opts.user ? path29.join(os15.homedir(), ".config", "systemd", "user") : "/etc/systemd/system";
|
|
167150
|
+
const envPath = `/usr/local/bin:/usr/bin:/bin:${path29.dirname(bun)}`;
|
|
167151
|
+
if (opts.dashboard !== false) {
|
|
167152
|
+
const unit = `[Unit]
|
|
167153
|
+
Description=MaTrixOS Dashboard
|
|
167154
|
+
After=network.target
|
|
167155
|
+
|
|
167156
|
+
[Service]
|
|
167157
|
+
Type=simple
|
|
167158
|
+
User=${os15.userInfo().username}
|
|
167159
|
+
WorkingDirectory=${os15.homedir()}
|
|
167160
|
+
Environment=PATH=${envPath}
|
|
167161
|
+
Environment=HOME=${os15.homedir()}
|
|
167162
|
+
ExecStart=${bin} dashboard --host 0.0.0.0 --daemon
|
|
167163
|
+
Restart=always
|
|
167164
|
+
RestartSec=5
|
|
167165
|
+
|
|
167166
|
+
[Install]
|
|
167167
|
+
WantedBy=${opts.user ? "default.target" : "multi-user.target"}
|
|
167168
|
+
`;
|
|
167169
|
+
writeFileEnsureDir(path29.join(unitDir, "matrixos-dashboard.service"), unit);
|
|
167170
|
+
}
|
|
167171
|
+
if (opts.gateway !== false) {
|
|
167172
|
+
const unit = `[Unit]
|
|
167173
|
+
Description=MaTrixOS Telegram Gateway
|
|
167174
|
+
After=network.target
|
|
167175
|
+
|
|
167176
|
+
[Service]
|
|
167177
|
+
Type=simple
|
|
167178
|
+
User=${os15.userInfo().username}
|
|
167179
|
+
WorkingDirectory=${os15.homedir()}
|
|
167180
|
+
Environment=PATH=${envPath}
|
|
167181
|
+
Environment=HOME=${os15.homedir()}
|
|
167182
|
+
ExecStart=${bin} gateway start --command "${bin} run"
|
|
167183
|
+
Restart=always
|
|
167184
|
+
RestartSec=5
|
|
167185
|
+
|
|
167186
|
+
[Install]
|
|
167187
|
+
WantedBy=${opts.user ? "default.target" : "multi-user.target"}
|
|
167188
|
+
`;
|
|
167189
|
+
writeFileEnsureDir(path29.join(unitDir, "matrixos-gateway.service"), unit);
|
|
167190
|
+
}
|
|
167191
|
+
console.log("[service] reloading systemd...");
|
|
167192
|
+
if (scope) {
|
|
167193
|
+
execSync3(`${scope} systemctl --user daemon-reload`, { stdio: "inherit" });
|
|
167194
|
+
if (opts.dashboard !== false)
|
|
167195
|
+
execSync3(`${scope} systemctl --user enable matrixos-dashboard.service`, { stdio: "inherit" });
|
|
167196
|
+
if (opts.gateway !== false)
|
|
167197
|
+
execSync3(`${scope} systemctl --user enable matrixos-gateway.service`, { stdio: "inherit" });
|
|
167198
|
+
if (opts.dashboard !== false)
|
|
167199
|
+
execSync3(`${scope} systemctl --user start matrixos-dashboard.service`, { stdio: "inherit" });
|
|
167200
|
+
if (opts.gateway !== false)
|
|
167201
|
+
execSync3(`${scope} systemctl --user start matrixos-gateway.service`, { stdio: "inherit" });
|
|
167202
|
+
} else {
|
|
167203
|
+
execSync3("systemctl daemon-reload", { stdio: "inherit" });
|
|
167204
|
+
if (opts.dashboard !== false)
|
|
167205
|
+
execSync3("systemctl enable matrixos-dashboard.service", { stdio: "inherit" });
|
|
167206
|
+
if (opts.gateway !== false)
|
|
167207
|
+
execSync3("systemctl enable matrixos-gateway.service", { stdio: "inherit" });
|
|
167208
|
+
if (opts.dashboard !== false)
|
|
167209
|
+
execSync3("systemctl start matrixos-dashboard.service", { stdio: "inherit" });
|
|
167210
|
+
if (opts.gateway !== false)
|
|
167211
|
+
execSync3("systemctl start matrixos-gateway.service", { stdio: "inherit" });
|
|
167212
|
+
}
|
|
167213
|
+
console.log("[service] systemd units installed and started.");
|
|
167214
|
+
}
|
|
167215
|
+
function installLaunchd(opts) {
|
|
167216
|
+
const bin = resolveMatrixosBin2();
|
|
167217
|
+
const bun = resolveBunBin();
|
|
167218
|
+
const launchDir = path29.join(os15.homedir(), "Library", "LaunchAgents");
|
|
167219
|
+
const envPath = `/usr/local/bin:/usr/bin:/bin:${path29.dirname(bun)}`;
|
|
167220
|
+
if (opts.dashboard !== false) {
|
|
167221
|
+
const label = "com.klc.matrixos.dashboard";
|
|
167222
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
167223
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
167224
|
+
<plist version="1.0">
|
|
167225
|
+
<dict>
|
|
167226
|
+
<key>Label</key>
|
|
167227
|
+
<string>${label}</string>
|
|
167228
|
+
<key>ProgramArguments</key>
|
|
167229
|
+
<array>
|
|
167230
|
+
<string>${bin}</string>
|
|
167231
|
+
<string>dashboard</string>
|
|
167232
|
+
<string>--host</string>
|
|
167233
|
+
<string>0.0.0.0</string>
|
|
167234
|
+
<string>--daemon</string>
|
|
167235
|
+
</array>
|
|
167236
|
+
<key>WorkingDirectory</key>
|
|
167237
|
+
<string>${os15.homedir()}</string>
|
|
167238
|
+
<key>EnvironmentVariables</key>
|
|
167239
|
+
<dict>
|
|
167240
|
+
<key>PATH</key>
|
|
167241
|
+
<string>${envPath}</string>
|
|
167242
|
+
<key>HOME</key>
|
|
167243
|
+
<string>${os15.homedir()}</string>
|
|
167244
|
+
</dict>
|
|
167245
|
+
<key>RunAtLoad</key>
|
|
167246
|
+
<true/>
|
|
167247
|
+
<key>KeepAlive</key>
|
|
167248
|
+
<true/>
|
|
167249
|
+
<key>StandardOutPath</key>
|
|
167250
|
+
<string>${os15.homedir()}/Library/Logs/matrixos-dashboard.log</string>
|
|
167251
|
+
<key>StandardErrorPath</key>
|
|
167252
|
+
<string>${os15.homedir()}/Library/Logs/matrixos-dashboard.log</string>
|
|
167253
|
+
</dict>
|
|
167254
|
+
</plist>
|
|
167255
|
+
`;
|
|
167256
|
+
writeFileEnsureDir(path29.join(launchDir, `${label}.plist`), plist);
|
|
167257
|
+
execSync3(`launchctl load ${path29.join(launchDir, `${label}.plist`)}`, { stdio: "inherit" });
|
|
167258
|
+
}
|
|
167259
|
+
if (opts.gateway !== false) {
|
|
167260
|
+
const label = "com.klc.matrixos.gateway";
|
|
167261
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
167262
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
167263
|
+
<plist version="1.0">
|
|
167264
|
+
<dict>
|
|
167265
|
+
<key>Label</key>
|
|
167266
|
+
<string>${label}</string>
|
|
167267
|
+
<key>ProgramArguments</key>
|
|
167268
|
+
<array>
|
|
167269
|
+
<string>${bin}</string>
|
|
167270
|
+
<string>gateway</string>
|
|
167271
|
+
<string>start</string>
|
|
167272
|
+
<string>--command</string>
|
|
167273
|
+
<string>${bin} run</string>
|
|
167274
|
+
</array>
|
|
167275
|
+
<key>WorkingDirectory</key>
|
|
167276
|
+
<string>${os15.homedir()}</string>
|
|
167277
|
+
<key>EnvironmentVariables</key>
|
|
167278
|
+
<dict>
|
|
167279
|
+
<key>PATH</key>
|
|
167280
|
+
<string>${envPath}</string>
|
|
167281
|
+
<key>HOME</key>
|
|
167282
|
+
<string>${os15.homedir()}</string>
|
|
167283
|
+
</dict>
|
|
167284
|
+
<key>RunAtLoad</key>
|
|
167285
|
+
<true/>
|
|
167286
|
+
<key>KeepAlive</key>
|
|
167287
|
+
<true/>
|
|
167288
|
+
<key>StandardOutPath</key>
|
|
167289
|
+
<string>${os15.homedir()}/Library/Logs/matrixos-gateway.log</string>
|
|
167290
|
+
<key>StandardErrorPath</key>
|
|
167291
|
+
<string>${os15.homedir()}/Library/Logs/matrixos-gateway.log</string>
|
|
167292
|
+
</dict>
|
|
167293
|
+
</plist>
|
|
167294
|
+
`;
|
|
167295
|
+
writeFileEnsureDir(path29.join(launchDir, `${label}.plist`), plist);
|
|
167296
|
+
execSync3(`launchctl load ${path29.join(launchDir, `${label}.plist`)}`, { stdio: "inherit" });
|
|
167297
|
+
}
|
|
167298
|
+
console.log("[service] launchd agents installed and loaded.");
|
|
167299
|
+
}
|
|
167300
|
+
function installWindowsNote() {
|
|
167301
|
+
console.log("[service] Windows: no auto-service installer yet.");
|
|
167302
|
+
console.log(" Use Task Scheduler to run `matrixos dashboard --host 0.0.0.0 --daemon`");
|
|
167303
|
+
console.log(' and `matrixos gateway start --command "matrixos run"` at logon.');
|
|
167304
|
+
console.log(" Or run them in the background via a startup script.");
|
|
167305
|
+
}
|
|
167306
|
+
async function serviceInstallCommand(options) {
|
|
167307
|
+
const platform2 = process.platform;
|
|
167308
|
+
console.log(`[service] detected platform: ${platform2}`);
|
|
167309
|
+
if (platform2 === "linux") {
|
|
167310
|
+
if (!fs24.existsSync("/run/systemd/system") && !fs24.existsSync("/etc/systemd/system")) {
|
|
167311
|
+
console.error("[service] systemd not detected \u2014 cannot install service automatically.");
|
|
167312
|
+
console.error(" Start manually: matrixos dashboard --host 0.0.0.0 --daemon");
|
|
167313
|
+
return 1;
|
|
167314
|
+
}
|
|
167315
|
+
installSystemd(options);
|
|
167316
|
+
return 0;
|
|
167317
|
+
}
|
|
167318
|
+
if (platform2 === "darwin") {
|
|
167319
|
+
installLaunchd(options);
|
|
167320
|
+
return 0;
|
|
167321
|
+
}
|
|
167322
|
+
if (platform2 === "win32") {
|
|
167323
|
+
installWindowsNote();
|
|
167324
|
+
return 0;
|
|
167325
|
+
}
|
|
167326
|
+
console.error(`[service] unsupported platform: ${platform2}`);
|
|
167327
|
+
return 1;
|
|
167328
|
+
}
|
|
167329
|
+
var init_service = () => {};
|
|
167330
|
+
|
|
167111
167331
|
// node_modules/.bun/commander@14.0.3/node_modules/commander/esm.mjs
|
|
167112
167332
|
var import__ = __toESM(require_commander(), 1);
|
|
167113
167333
|
var {
|
|
@@ -186764,6 +186984,30 @@ function getDb() {
|
|
|
186764
186984
|
return;
|
|
186765
186985
|
}
|
|
186766
186986
|
}
|
|
186987
|
+
function getDbWrite() {
|
|
186988
|
+
if (!fs21.existsSync(OPENCODE_DB_PATH))
|
|
186989
|
+
return;
|
|
186990
|
+
try {
|
|
186991
|
+
const db = new Database5(OPENCODE_DB_PATH);
|
|
186992
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
186993
|
+
return db;
|
|
186994
|
+
} catch {
|
|
186995
|
+
return;
|
|
186996
|
+
}
|
|
186997
|
+
}
|
|
186998
|
+
function ensureKanbanTable(db) {
|
|
186999
|
+
db.exec(`
|
|
187000
|
+
CREATE TABLE IF NOT EXISTS matrixos_kanban (
|
|
187001
|
+
id TEXT PRIMARY KEY,
|
|
187002
|
+
title TEXT NOT NULL,
|
|
187003
|
+
agent TEXT NOT NULL DEFAULT 'Unknown',
|
|
187004
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
187005
|
+
priority TEXT NOT NULL DEFAULT 'medium',
|
|
187006
|
+
created_at INTEGER NOT NULL,
|
|
187007
|
+
updated_at INTEGER NOT NULL
|
|
187008
|
+
)
|
|
187009
|
+
`);
|
|
187010
|
+
}
|
|
186767
187011
|
function midnightMs() {
|
|
186768
187012
|
const d = new Date;
|
|
186769
187013
|
d.setHours(0, 0, 0, 0);
|
|
@@ -187026,24 +187270,24 @@ function createDataProvider(config5) {
|
|
|
187026
187270
|
},
|
|
187027
187271
|
async getKanbanTasks() {
|
|
187028
187272
|
const board = { columns: { pending: [], in_progress: [], completed: [], failed: [] } };
|
|
187029
|
-
const db =
|
|
187273
|
+
const db = getDbWrite();
|
|
187030
187274
|
if (!db)
|
|
187031
187275
|
return board;
|
|
187032
187276
|
try {
|
|
187033
|
-
|
|
187034
|
-
|
|
187277
|
+
ensureKanbanTable(db);
|
|
187278
|
+
const rows = db.query("SELECT id, title, agent, status, priority, created_at, updated_at FROM matrixos_kanban ORDER BY updated_at DESC").all();
|
|
187035
187279
|
for (const row of rows) {
|
|
187036
187280
|
const status2 = row.status;
|
|
187037
187281
|
if (!board.columns[status2])
|
|
187038
187282
|
continue;
|
|
187039
187283
|
const task2 = {
|
|
187040
|
-
id:
|
|
187041
|
-
title: row.
|
|
187042
|
-
agent: "Unknown",
|
|
187284
|
+
id: row.id,
|
|
187285
|
+
title: row.title,
|
|
187286
|
+
agent: row.agent || "Unknown",
|
|
187043
187287
|
priority: row.priority ?? "medium",
|
|
187044
187288
|
status: status2,
|
|
187045
|
-
createdAt: new Date(row.
|
|
187046
|
-
updatedAt: new Date(row.
|
|
187289
|
+
createdAt: new Date(row.created_at).toISOString(),
|
|
187290
|
+
updatedAt: new Date(row.updated_at).toISOString()
|
|
187047
187291
|
};
|
|
187048
187292
|
board.columns[status2].push(task2);
|
|
187049
187293
|
}
|
|
@@ -187052,6 +187296,76 @@ function createDataProvider(config5) {
|
|
|
187052
187296
|
}
|
|
187053
187297
|
return board;
|
|
187054
187298
|
},
|
|
187299
|
+
async createKanbanTask(input) {
|
|
187300
|
+
const db = getDbWrite();
|
|
187301
|
+
if (!db)
|
|
187302
|
+
return { ok: false, error: "database unavailable" };
|
|
187303
|
+
try {
|
|
187304
|
+
ensureKanbanTable(db);
|
|
187305
|
+
const id = `kb_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
187306
|
+
const now = Date.now();
|
|
187307
|
+
const status2 = input.status ?? "pending";
|
|
187308
|
+
const priority = input.priority ?? "medium";
|
|
187309
|
+
db.query("INSERT INTO matrixos_kanban (id, title, agent, status, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)").run(id, input.title, input.agent ?? "Unknown", status2, priority, now, now);
|
|
187310
|
+
return { ok: true, id };
|
|
187311
|
+
} catch (e) {
|
|
187312
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
187313
|
+
} finally {
|
|
187314
|
+
db.close();
|
|
187315
|
+
}
|
|
187316
|
+
},
|
|
187317
|
+
async updateKanbanTask(id, input) {
|
|
187318
|
+
const db = getDbWrite();
|
|
187319
|
+
if (!db)
|
|
187320
|
+
return { ok: false, error: "database unavailable" };
|
|
187321
|
+
try {
|
|
187322
|
+
ensureKanbanTable(db);
|
|
187323
|
+
const existing = db.query("SELECT id FROM matrixos_kanban WHERE id = ?").get(id);
|
|
187324
|
+
if (!existing)
|
|
187325
|
+
return { ok: false, error: "task not found" };
|
|
187326
|
+
const sets = [];
|
|
187327
|
+
const params = [];
|
|
187328
|
+
if (input.title !== undefined) {
|
|
187329
|
+
sets.push("title = ?");
|
|
187330
|
+
params.push(input.title);
|
|
187331
|
+
}
|
|
187332
|
+
if (input.agent !== undefined) {
|
|
187333
|
+
sets.push("agent = ?");
|
|
187334
|
+
params.push(input.agent);
|
|
187335
|
+
}
|
|
187336
|
+
if (input.status !== undefined) {
|
|
187337
|
+
sets.push("status = ?");
|
|
187338
|
+
params.push(input.status);
|
|
187339
|
+
}
|
|
187340
|
+
if (input.priority !== undefined) {
|
|
187341
|
+
sets.push("priority = ?");
|
|
187342
|
+
params.push(input.priority);
|
|
187343
|
+
}
|
|
187344
|
+
sets.push("updated_at = ?");
|
|
187345
|
+
params.push(String(Date.now()));
|
|
187346
|
+
params.push(id);
|
|
187347
|
+
db.query(`UPDATE matrixos_kanban SET ${sets.join(", ")} WHERE id = ?`).run(...params);
|
|
187348
|
+
return { ok: true };
|
|
187349
|
+
} catch (e) {
|
|
187350
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
187351
|
+
} finally {
|
|
187352
|
+
db.close();
|
|
187353
|
+
}
|
|
187354
|
+
},
|
|
187355
|
+
async deleteKanbanTask(id) {
|
|
187356
|
+
const db = getDbWrite();
|
|
187357
|
+
if (!db)
|
|
187358
|
+
return { ok: false, error: "database unavailable" };
|
|
187359
|
+
try {
|
|
187360
|
+
ensureKanbanTable(db);
|
|
187361
|
+
db.query("DELETE FROM matrixos_kanban WHERE id = ?").run(id);
|
|
187362
|
+
return { ok: true };
|
|
187363
|
+
} catch (e) {
|
|
187364
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
187365
|
+
} finally {
|
|
187366
|
+
db.close();
|
|
187367
|
+
}
|
|
187368
|
+
},
|
|
187055
187369
|
async getIncidents(limit = 50) {
|
|
187056
187370
|
const lines = readJsonl("anti-loop.jsonl");
|
|
187057
187371
|
if (lines.length === 0) {
|
|
@@ -187365,6 +187679,34 @@ function createDashboardServer(dataProvider, config5) {
|
|
|
187365
187679
|
return Response.json(await dataProvider.getCost(), { headers: jsonHeaders });
|
|
187366
187680
|
case "/api/kanban":
|
|
187367
187681
|
return Response.json(await dataProvider.getKanbanTasks(), { headers: jsonHeaders });
|
|
187682
|
+
case "/api/kanban/task": {
|
|
187683
|
+
if (req.method === "POST") {
|
|
187684
|
+
const body = await req.json();
|
|
187685
|
+
if (!body.title || !body.title.trim()) {
|
|
187686
|
+
return Response.json({ ok: false, error: "title required" }, { status: 400, headers: jsonHeaders });
|
|
187687
|
+
}
|
|
187688
|
+
const result = await dataProvider.createKanbanTask(body);
|
|
187689
|
+
return Response.json(result, { status: result.ok ? 201 : 500, headers: jsonHeaders });
|
|
187690
|
+
}
|
|
187691
|
+
if (req.method === "PUT") {
|
|
187692
|
+
const body = await req.json();
|
|
187693
|
+
if (!body.id) {
|
|
187694
|
+
return Response.json({ ok: false, error: "id required" }, { status: 400, headers: jsonHeaders });
|
|
187695
|
+
}
|
|
187696
|
+
const result = await dataProvider.updateKanbanTask(body.id, body);
|
|
187697
|
+
return Response.json(result, { status: result.ok ? 200 : 500, headers: jsonHeaders });
|
|
187698
|
+
}
|
|
187699
|
+
if (req.method === "DELETE") {
|
|
187700
|
+
const url22 = new URL(req.url);
|
|
187701
|
+
const id = url22.searchParams.get("id");
|
|
187702
|
+
if (!id) {
|
|
187703
|
+
return Response.json({ ok: false, error: "id required" }, { status: 400, headers: jsonHeaders });
|
|
187704
|
+
}
|
|
187705
|
+
const result = await dataProvider.deleteKanbanTask(id);
|
|
187706
|
+
return Response.json(result, { status: result.ok ? 200 : 500, headers: jsonHeaders });
|
|
187707
|
+
}
|
|
187708
|
+
return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
|
|
187709
|
+
}
|
|
187368
187710
|
case "/api/incidents": {
|
|
187369
187711
|
const limit = parseInt(url3.searchParams.get("limit") ?? "50", 10);
|
|
187370
187712
|
return Response.json(await dataProvider.getIncidents(limit), { headers: jsonHeaders });
|
|
@@ -188279,6 +188621,23 @@ Examples:
|
|
|
188279
188621
|
process.stdout.write(result.stdout);
|
|
188280
188622
|
process.exit(result.exitCode);
|
|
188281
188623
|
});
|
|
188624
|
+
program2.command("service").description("Install MaTrixOS as a persistent OS service (dashboard + gateway)").argument("<action>", "install | uninstall").option("--no-dashboard", "Skip dashboard service").option("--no-gateway", "Skip gateway service").option("--user", "Install as current user (systemd --user / launchd user agent)").action(async (action, options) => {
|
|
188625
|
+
if (action !== "install" && action !== "uninstall") {
|
|
188626
|
+
console.error(`[service] unknown action: ${action}. Use 'install' or 'uninstall'.`);
|
|
188627
|
+
process.exit(1);
|
|
188628
|
+
}
|
|
188629
|
+
if (action === "uninstall") {
|
|
188630
|
+
console.log("[service] uninstall not yet implemented \u2014 remove units manually (systemctl disable / launchctl unload).");
|
|
188631
|
+
process.exit(0);
|
|
188632
|
+
}
|
|
188633
|
+
const { serviceInstallCommand: serviceInstallCommand2 } = await Promise.resolve().then(() => (init_service(), exports_service));
|
|
188634
|
+
const exitCode = await serviceInstallCommand2({
|
|
188635
|
+
dashboard: options.dashboard ?? true,
|
|
188636
|
+
gateway: options.gateway ?? true,
|
|
188637
|
+
user: options.user ?? false
|
|
188638
|
+
});
|
|
188639
|
+
process.exit(exitCode);
|
|
188640
|
+
});
|
|
188282
188641
|
|
|
188283
188642
|
// packages/omo-opencode/src/cli/index.ts
|
|
188284
188643
|
runCli();
|
|
@@ -13,6 +13,29 @@ export interface DataProvider {
|
|
|
13
13
|
getSessions(limit?: number): Promise<SessionSummary[]>;
|
|
14
14
|
getCost(): Promise<CostSummary>;
|
|
15
15
|
getKanbanTasks(): Promise<KanbanBoard>;
|
|
16
|
+
createKanbanTask(input: {
|
|
17
|
+
title: string;
|
|
18
|
+
agent?: string;
|
|
19
|
+
status?: string;
|
|
20
|
+
priority?: string;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
ok: boolean;
|
|
23
|
+
id?: string;
|
|
24
|
+
error?: string;
|
|
25
|
+
}>;
|
|
26
|
+
updateKanbanTask(id: string, input: {
|
|
27
|
+
title?: string;
|
|
28
|
+
agent?: string;
|
|
29
|
+
status?: string;
|
|
30
|
+
priority?: string;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
ok: boolean;
|
|
33
|
+
error?: string;
|
|
34
|
+
}>;
|
|
35
|
+
deleteKanbanTask(id: string): Promise<{
|
|
36
|
+
ok: boolean;
|
|
37
|
+
error?: string;
|
|
38
|
+
}>;
|
|
16
39
|
getIncidents(limit?: number): Promise<IncidentEntry[]>;
|
|
17
40
|
getMetrics(range?: string): Promise<MetricsSnapshot[]>;
|
|
18
41
|
getLogs(): LogEntry[];
|
|
@@ -225,5 +225,22 @@ body{font-family:var(--font-body);font-size:var(--text-base);color:var(--text-pr
|
|
|
225
225
|
.agent-model-select:focus{outline:none;border-color:var(--accent-primary)}
|
|
226
226
|
.agent-model-select option{background:var(--bg-elevated);color:var(--text-primary)}
|
|
227
227
|
|
|
228
|
+
.btn-primary{background:var(--accent-primary);color:#fff;border:none;border-radius:var(--radius-md);padding:8px 16px;font-size:var(--text-sm);font-weight:600;cursor:pointer;transition:background .15s}
|
|
229
|
+
.btn-primary:hover{background:var(--accent-hover)}
|
|
230
|
+
.btn-secondary{background:var(--bg-elevated);color:var(--text-primary);border:1px solid var(--border-default);border-radius:var(--radius-md);padding:8px 16px;font-size:var(--text-sm);cursor:pointer}
|
|
231
|
+
.kanban-del{position:absolute;top:6px;right:6px;background:transparent;border:none;color:var(--text-tertiary);font-size:18px;line-height:1;cursor:pointer;opacity:0;transition:opacity .15s}
|
|
232
|
+
.kanban-card{position:relative}
|
|
233
|
+
.kanban-card:hover .kanban-del{opacity:1}
|
|
234
|
+
.kanban-card[draggable=true]{cursor:grab}
|
|
235
|
+
.kanban-card[draggable=true]:active{cursor:grabbing}
|
|
236
|
+
.kanban-col.drag-over{outline:2px dashed var(--accent-primary);outline-offset:-4px}
|
|
237
|
+
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;z-index:1000}
|
|
238
|
+
.modal-box{background:var(--bg-card);border:1px solid var(--border-default);border-radius:var(--radius-xl);padding:24px;width:380px;max-width:90vw;display:flex;flex-direction:column;gap:14px}
|
|
239
|
+
.modal-box h3{font-size:var(--text-lg);font-weight:700;margin-bottom:4px}
|
|
240
|
+
.modal-box label{display:flex;flex-direction:column;gap:6px;font-size:var(--text-xs);color:var(--text-secondary);text-transform:uppercase;letter-spacing:.04em}
|
|
241
|
+
.modal-box .input{background:var(--bg-secondary);border:1px solid var(--border-default);border-radius:var(--radius-md);padding:10px 12px;color:var(--text-primary);font-size:var(--text-sm);font-family:var(--font-body)}
|
|
242
|
+
.modal-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:8px}
|
|
243
|
+
|
|
244
|
+
|
|
228
245
|
@media(max-width:1024px){.kpi-grid,.grid-2{grid-template-columns:repeat(2,1fr)}.kanban-board{grid-template-columns:repeat(2,1fr)}.gauge-grid{grid-template-columns:repeat(2,1fr)}}
|
|
229
246
|
@media(max-width:768px){.kpi-grid,.grid-2{grid-template-columns:1fr}.kanban-board{grid-template-columns:1fr}.agent-grid{grid-template-columns:1fr}}
|
|
@@ -1,2 +1,22 @@
|
|
|
1
|
-
const API={
|
|
2
|
-
|
|
1
|
+
const API={
|
|
2
|
+
health:()=>fetchJSON('/health'),
|
|
3
|
+
agents:()=>fetchJSON('/agents'),
|
|
4
|
+
models:()=>fetchJSON('/models'),
|
|
5
|
+
sessions:(l)=>fetchJSON(`/sessions?limit=${l}`),
|
|
6
|
+
cost:()=>fetchJSON('/cost'),
|
|
7
|
+
kanban:()=>fetchJSON('/kanban'),
|
|
8
|
+
kanbanCreate:(body)=>fetchJSON('/kanban/task',{method:'POST',body}),
|
|
9
|
+
kanbanUpdate:(body)=>fetchJSON('/kanban/task',{method:'PUT',body}),
|
|
10
|
+
kanbanDelete:(id)=>fetchJSON(`/kanban/task?id=${id}`,{method:'DELETE'}),
|
|
11
|
+
incidents:(l)=>fetchJSON(`/incidents?limit=${l}`),
|
|
12
|
+
metrics:()=>fetchJSON('/metrics'),
|
|
13
|
+
config:()=>fetchJSON('/config'),
|
|
14
|
+
memory:()=>fetchJSON('/memory'),
|
|
15
|
+
skills:()=>fetchJSON('/skills'),
|
|
16
|
+
gatewayToken:(type,token,passphrase)=>fetch('/api/gateway/token',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({type,token,passphrase})}).then(r=>r.json())
|
|
17
|
+
}
|
|
18
|
+
async function fetchJSON(e,opts){
|
|
19
|
+
const r=await fetch(`/api${e}`,opts)
|
|
20
|
+
if(!r.ok)throw new Error(`API ${e}: ${r.status}`)
|
|
21
|
+
return r.json()
|
|
22
|
+
}
|
|
@@ -183,20 +183,111 @@ async function loadCost(){
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
// ===== KANBAN =====
|
|
186
|
+
let kanbanData={columns:{}}
|
|
187
|
+
const KANBAN_STATUSES=['pending','in_progress','completed','failed']
|
|
188
|
+
const KANBAN_LABELS={pending:'Pending',in_progress:'In Progress',completed:'Completed',failed:'Failed'}
|
|
189
|
+
|
|
186
190
|
async function loadKanban(){
|
|
187
191
|
const board=document.getElementById('kanbanBoard')
|
|
188
192
|
try{
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
193
|
+
kanbanData=await API.kanban()
|
|
194
|
+
renderKanban()
|
|
195
|
+
}catch(e){board.innerHTML=`<div class="error" style="grid-column:1/-1"><p>Failed to load Kanban</p></div>`}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function renderKanban(){
|
|
199
|
+
const board=document.getElementById('kanbanBoard')
|
|
200
|
+
const cols=kanbanData.columns||{}
|
|
201
|
+
board.innerHTML=`
|
|
202
|
+
<div style="grid-column:1/-1;display:flex;justify-content:flex-end;margin-bottom:12px">
|
|
203
|
+
<button class="btn-primary" onclick="openKanbanModal()">+ New Task</button>
|
|
204
|
+
</div>`+
|
|
205
|
+
KANBAN_STATUSES.map(status=>{
|
|
206
|
+
const tasks=cols[status]||[]
|
|
207
|
+
return `<div class="kanban-col" data-status="${status}" ondragover="onKanbanDragOver(event)" ondrop="onKanbanDrop(event,'${status}')">
|
|
208
|
+
<div class="kanban-header"><span>${KANBAN_LABELS[status]}</span><span class="kanban-count">${tasks.length}</span></div>
|
|
209
|
+
<div class="kanban-body">${
|
|
210
|
+
tasks.length?tasks.map(t=>`<div class="kanban-card" draggable="true" ondragstart="onKanbanDragStart(event,'${t.id}')" ondblclick="openKanbanModal('${t.id}')">
|
|
211
|
+
<div class="kanban-card-title">${escapeHtml(t.title)}</div>
|
|
212
|
+
<div class="kanban-card-meta"><span>${escapeHtml(t.agent)}</span><span class="prio ${t.priority}">${t.priority}</span></div>
|
|
213
|
+
<button class="kanban-del" onclick="deleteKanbanTask('${t.id}')" title="Delete">×</button>
|
|
214
|
+
</div>`).join(''):'<div style="padding:20px;text-align:center;color:var(--text-tertiary);font-size:var(--text-xs)">No tasks</div>'
|
|
215
|
+
}</div>
|
|
216
|
+
</div>`
|
|
198
217
|
}).join('')
|
|
199
|
-
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function escapeHtml(s){return (s||'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]))}
|
|
221
|
+
|
|
222
|
+
let dragTaskId=null
|
|
223
|
+
function onKanbanDragStart(e,id){dragTaskId=id;e.dataTransfer.setData('text/plain',id)}
|
|
224
|
+
function onKanbanDragOver(e){e.preventDefault()}
|
|
225
|
+
async function onKanbanDrop(e,status){
|
|
226
|
+
e.preventDefault()
|
|
227
|
+
if(!dragTaskId)return
|
|
228
|
+
const id=dragTaskId;dragTaskId=null
|
|
229
|
+
const task=findKanbanTask(id)
|
|
230
|
+
if(!task||task.status===status)return
|
|
231
|
+
try{
|
|
232
|
+
await API.kanbanUpdate({id,status})
|
|
233
|
+
task.status=status
|
|
234
|
+
renderKanban()
|
|
235
|
+
}catch(err){alert('Erreur: '+err.message)}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function findKanbanTask(id){
|
|
239
|
+
for(const s of KANBAN_STATUSES){const t=(kanbanData.columns[s]||[]).find(x=>x.id===id);if(t)return t}
|
|
240
|
+
return null
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function deleteKanbanTask(id){
|
|
244
|
+
if(!confirm('Delete this task?'))return
|
|
245
|
+
try{
|
|
246
|
+
await API.kanbanDelete(id)
|
|
247
|
+
for(const s of KANBAN_STATUSES){kanbanData.columns[s]=(kanbanData.columns[s]||[]).filter(t=>t.id!==id)}
|
|
248
|
+
renderKanban()
|
|
249
|
+
}catch(err){alert('Erreur: '+err.message)}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function openKanbanModal(id){
|
|
253
|
+
const task=id?findKanbanTask(id):null
|
|
254
|
+
const modal=document.createElement('div')
|
|
255
|
+
modal.className='modal-overlay'
|
|
256
|
+
modal.innerHTML=`
|
|
257
|
+
<div class="modal-box">
|
|
258
|
+
<h3>${task?'Edit Task':'New Task'}</h3>
|
|
259
|
+
<label>Title<input id="kbTitle" class="input" value="${task?escapeHtml(task.title):''}"></label>
|
|
260
|
+
<label>Agent<input id="kbAgent" class="input" value="${task?escapeHtml(task.agent):''}" placeholder="e.g. Morpheus"></label>
|
|
261
|
+
<label>Priority<select id="kbPriority" class="input">
|
|
262
|
+
${['low','medium','high','urgent'].map(p=>`<option value="${p}" ${task&&task.priority===p?'selected':''}>${p}</option>`).join('')}
|
|
263
|
+
</select></label>
|
|
264
|
+
<label>Status<select id="kbStatus" class="input">
|
|
265
|
+
${KANBAN_STATUSES.map(s=>`<option value="${s}" ${task&&task.status===s?'selected':( !task&&s==='pending'?'selected':'')}>${KANBAN_LABELS[s]}</option>`).join('')}
|
|
266
|
+
</select></label>
|
|
267
|
+
<div class="modal-actions">
|
|
268
|
+
<button class="btn-secondary" onclick="this.closest('.modal-overlay').remove()">Cancel</button>
|
|
269
|
+
<button class="btn-primary" onclick="saveKanban('${id||''}')">${task?'Save':'Create'}</button>
|
|
270
|
+
</div>
|
|
271
|
+
</div>`
|
|
272
|
+
document.body.appendChild(modal)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function saveKanban(id){
|
|
276
|
+
const title=document.getElementById('kbTitle').value.trim()
|
|
277
|
+
const agent=document.getElementById('kbAgent').value.trim()
|
|
278
|
+
const priority=document.getElementById('kbPriority').value
|
|
279
|
+
const status=document.getElementById('kbStatus').value
|
|
280
|
+
if(!title){alert('Title required');return}
|
|
281
|
+
try{
|
|
282
|
+
if(id){
|
|
283
|
+
await API.kanbanUpdate({id,title,agent,priority,status})
|
|
284
|
+
}else{
|
|
285
|
+
const res=await API.kanbanCreate({title,agent,priority,status})
|
|
286
|
+
if(!res.ok){throw new Error(res.error||'create failed')}
|
|
287
|
+
}
|
|
288
|
+
document.querySelector('.modal-overlay')?.remove()
|
|
289
|
+
await loadKanban()
|
|
290
|
+
}catch(err){alert('Erreur: '+err.message)}
|
|
200
291
|
}
|
|
201
292
|
|
|
202
293
|
// ===== LOGS =====
|
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.28",
|
|
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