@kl-c/matrixos 0.3.55 → 0.3.57
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/deployment.d.ts +19 -0
- package/dist/cli/index.js +67 -5
- package/dist/cli-node/index.js +67 -5
- package/dist/features/dashboard/data-provider.d.ts +2 -1
- package/dist/features/dashboard/frontend/css/style.css +10 -0
- package/dist/features/dashboard/frontend/index.html +25 -1
- package/dist/features/dashboard/frontend/js/api.js +2 -0
- package/dist/features/dashboard/frontend/js/app.js +40 -2
- package/dist/features/dashboard/types.d.ts +7 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI: `matrixos deploy <target>`
|
|
3
|
+
*
|
|
4
|
+
* Deploy helper (A9). Honest minimal implementation:
|
|
5
|
+
* - `--dry-run` (default) prints the plan for the given target.
|
|
6
|
+
* - Apply mode reports the target is not yet wired (no false deployment).
|
|
7
|
+
*
|
|
8
|
+
* This is a user-on-demand feature (generic OS, not KLC-specific). Full
|
|
9
|
+
* VPS/vercel/static deployment is out of scope until a user requests it.
|
|
10
|
+
*/
|
|
11
|
+
export interface DeployOptions {
|
|
12
|
+
target: string;
|
|
13
|
+
environment?: "staging" | "production" | "preview";
|
|
14
|
+
dryRun?: boolean;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
projectRoot?: string;
|
|
17
|
+
params?: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function runDeploy(options: DeployOptions): Promise<number>;
|
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.57",
|
|
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",
|
|
@@ -189164,18 +189164,54 @@ ${row.description ? `Description: ${row.description}
|
|
|
189164
189164
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
189165
189165
|
}
|
|
189166
189166
|
},
|
|
189167
|
-
|
|
189167
|
+
getIncidents(limit = 50) {
|
|
189168
189168
|
const lines = readJsonl("anti-loop.jsonl");
|
|
189169
189169
|
if (lines.length === 0) {
|
|
189170
|
-
return [];
|
|
189170
|
+
return Promise.resolve([]);
|
|
189171
189171
|
}
|
|
189172
|
-
return lines.slice(0, limit).map((l2) => {
|
|
189172
|
+
return Promise.resolve(lines.slice(0, limit).map((l2) => {
|
|
189173
189173
|
try {
|
|
189174
189174
|
return JSON.parse(l2);
|
|
189175
189175
|
} catch {
|
|
189176
189176
|
return null;
|
|
189177
189177
|
}
|
|
189178
|
-
}).filter(Boolean);
|
|
189178
|
+
}).filter(Boolean));
|
|
189179
|
+
},
|
|
189180
|
+
async getNotifications() {
|
|
189181
|
+
const notes = [];
|
|
189182
|
+
try {
|
|
189183
|
+
const board = await this.getKanbanTasks();
|
|
189184
|
+
for (const col of Object.values(board.columns)) {
|
|
189185
|
+
for (const t2 of col) {
|
|
189186
|
+
if (t2.status === "failed") {
|
|
189187
|
+
notes.push({
|
|
189188
|
+
id: `kanban-${t2.id}`,
|
|
189189
|
+
kind: "kanban_failed",
|
|
189190
|
+
title: `Kanban task failed: ${t2.title}`,
|
|
189191
|
+
detail: t2.agent ? `agent: ${t2.agent}` : "",
|
|
189192
|
+
ts: Date.parse(t2.updatedAt) || Date.parse(t2.createdAt) || 0
|
|
189193
|
+
});
|
|
189194
|
+
}
|
|
189195
|
+
}
|
|
189196
|
+
}
|
|
189197
|
+
} catch {}
|
|
189198
|
+
try {
|
|
189199
|
+
const incidents = readJsonl("anti-loop.jsonl").slice(0, 10);
|
|
189200
|
+
for (const line of incidents) {
|
|
189201
|
+
try {
|
|
189202
|
+
const inc = JSON.parse(line);
|
|
189203
|
+
notes.push({
|
|
189204
|
+
id: `incident-${inc.timestamp}`,
|
|
189205
|
+
kind: "incident",
|
|
189206
|
+
title: inc.trigger ?? "Incident",
|
|
189207
|
+
detail: inc.detail ?? inc.actionTaken ?? "",
|
|
189208
|
+
ts: inc.timestamp ?? 0
|
|
189209
|
+
});
|
|
189210
|
+
} catch {}
|
|
189211
|
+
}
|
|
189212
|
+
} catch {}
|
|
189213
|
+
notes.sort((a2, b2) => b2.ts - a2.ts);
|
|
189214
|
+
return notes;
|
|
189179
189215
|
},
|
|
189180
189216
|
async getMetrics() {
|
|
189181
189217
|
const db = getDb();
|
|
@@ -189556,6 +189592,32 @@ function createDashboardServer(dataProvider, config5) {
|
|
|
189556
189592
|
const result = await dataProvider.decomposeGoal(body.id);
|
|
189557
189593
|
return Response.json(result, { status: result.ok ? 200 : 500, headers: jsonHeaders });
|
|
189558
189594
|
}
|
|
189595
|
+
case "/api/deploy": {
|
|
189596
|
+
if (req.method !== "POST") {
|
|
189597
|
+
return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
|
|
189598
|
+
}
|
|
189599
|
+
const body = await req.json();
|
|
189600
|
+
if (!body.target) {
|
|
189601
|
+
return Response.json({ ok: false, error: "target required" }, { status: 400, headers: jsonHeaders });
|
|
189602
|
+
}
|
|
189603
|
+
try {
|
|
189604
|
+
const { spawnSync: spawnSync4 } = await import("child_process");
|
|
189605
|
+
const args = ["deploy", body.target];
|
|
189606
|
+
if (body.environment)
|
|
189607
|
+
args.push("--env", body.environment);
|
|
189608
|
+
if (body.projectRoot)
|
|
189609
|
+
args.push("--project-root", body.projectRoot);
|
|
189610
|
+
if (body.dryRun !== false)
|
|
189611
|
+
args.push("--dry-run");
|
|
189612
|
+
const res = spawnSync4("matrixos", args, { encoding: "utf-8" });
|
|
189613
|
+
const output = (res.stdout || res.stderr || "no output").trim();
|
|
189614
|
+
return Response.json({ ok: true, output }, { headers: jsonHeaders });
|
|
189615
|
+
} catch (e) {
|
|
189616
|
+
return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e) }, { status: 500, headers: jsonHeaders });
|
|
189617
|
+
}
|
|
189618
|
+
}
|
|
189619
|
+
case "/api/notifications":
|
|
189620
|
+
return Response.json(await dataProvider.getNotifications(), { headers: jsonHeaders });
|
|
189559
189621
|
case "/api/incidents": {
|
|
189560
189622
|
const limit = parseInt(url3.searchParams.get("limit") ?? "50", 10);
|
|
189561
189623
|
return Response.json(await dataProvider.getIncidents(limit), { headers: jsonHeaders });
|
package/dist/cli-node/index.js
CHANGED
|
@@ -2163,7 +2163,7 @@ var package_default;
|
|
|
2163
2163
|
var init_package = __esm(() => {
|
|
2164
2164
|
package_default = {
|
|
2165
2165
|
name: "@kl-c/matrixos",
|
|
2166
|
-
version: "0.3.
|
|
2166
|
+
version: "0.3.57",
|
|
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",
|
|
@@ -189219,18 +189219,54 @@ ${row.description ? `Description: ${row.description}
|
|
|
189219
189219
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
189220
189220
|
}
|
|
189221
189221
|
},
|
|
189222
|
-
|
|
189222
|
+
getIncidents(limit = 50) {
|
|
189223
189223
|
const lines = readJsonl("anti-loop.jsonl");
|
|
189224
189224
|
if (lines.length === 0) {
|
|
189225
|
-
return [];
|
|
189225
|
+
return Promise.resolve([]);
|
|
189226
189226
|
}
|
|
189227
|
-
return lines.slice(0, limit).map((l2) => {
|
|
189227
|
+
return Promise.resolve(lines.slice(0, limit).map((l2) => {
|
|
189228
189228
|
try {
|
|
189229
189229
|
return JSON.parse(l2);
|
|
189230
189230
|
} catch {
|
|
189231
189231
|
return null;
|
|
189232
189232
|
}
|
|
189233
|
-
}).filter(Boolean);
|
|
189233
|
+
}).filter(Boolean));
|
|
189234
|
+
},
|
|
189235
|
+
async getNotifications() {
|
|
189236
|
+
const notes = [];
|
|
189237
|
+
try {
|
|
189238
|
+
const board = await this.getKanbanTasks();
|
|
189239
|
+
for (const col of Object.values(board.columns)) {
|
|
189240
|
+
for (const t2 of col) {
|
|
189241
|
+
if (t2.status === "failed") {
|
|
189242
|
+
notes.push({
|
|
189243
|
+
id: `kanban-${t2.id}`,
|
|
189244
|
+
kind: "kanban_failed",
|
|
189245
|
+
title: `Kanban task failed: ${t2.title}`,
|
|
189246
|
+
detail: t2.agent ? `agent: ${t2.agent}` : "",
|
|
189247
|
+
ts: Date.parse(t2.updatedAt) || Date.parse(t2.createdAt) || 0
|
|
189248
|
+
});
|
|
189249
|
+
}
|
|
189250
|
+
}
|
|
189251
|
+
}
|
|
189252
|
+
} catch {}
|
|
189253
|
+
try {
|
|
189254
|
+
const incidents = readJsonl("anti-loop.jsonl").slice(0, 10);
|
|
189255
|
+
for (const line of incidents) {
|
|
189256
|
+
try {
|
|
189257
|
+
const inc = JSON.parse(line);
|
|
189258
|
+
notes.push({
|
|
189259
|
+
id: `incident-${inc.timestamp}`,
|
|
189260
|
+
kind: "incident",
|
|
189261
|
+
title: inc.trigger ?? "Incident",
|
|
189262
|
+
detail: inc.detail ?? inc.actionTaken ?? "",
|
|
189263
|
+
ts: inc.timestamp ?? 0
|
|
189264
|
+
});
|
|
189265
|
+
} catch {}
|
|
189266
|
+
}
|
|
189267
|
+
} catch {}
|
|
189268
|
+
notes.sort((a2, b2) => b2.ts - a2.ts);
|
|
189269
|
+
return notes;
|
|
189234
189270
|
},
|
|
189235
189271
|
async getMetrics() {
|
|
189236
189272
|
const db = getDb();
|
|
@@ -189611,6 +189647,32 @@ function createDashboardServer(dataProvider, config5) {
|
|
|
189611
189647
|
const result = await dataProvider.decomposeGoal(body.id);
|
|
189612
189648
|
return Response.json(result, { status: result.ok ? 200 : 500, headers: jsonHeaders });
|
|
189613
189649
|
}
|
|
189650
|
+
case "/api/deploy": {
|
|
189651
|
+
if (req.method !== "POST") {
|
|
189652
|
+
return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
|
|
189653
|
+
}
|
|
189654
|
+
const body = await req.json();
|
|
189655
|
+
if (!body.target) {
|
|
189656
|
+
return Response.json({ ok: false, error: "target required" }, { status: 400, headers: jsonHeaders });
|
|
189657
|
+
}
|
|
189658
|
+
try {
|
|
189659
|
+
const { spawnSync: spawnSync4 } = await import("child_process");
|
|
189660
|
+
const args = ["deploy", body.target];
|
|
189661
|
+
if (body.environment)
|
|
189662
|
+
args.push("--env", body.environment);
|
|
189663
|
+
if (body.projectRoot)
|
|
189664
|
+
args.push("--project-root", body.projectRoot);
|
|
189665
|
+
if (body.dryRun !== false)
|
|
189666
|
+
args.push("--dry-run");
|
|
189667
|
+
const res = spawnSync4("matrixos", args, { encoding: "utf-8" });
|
|
189668
|
+
const output = (res.stdout || res.stderr || "no output").trim();
|
|
189669
|
+
return Response.json({ ok: true, output }, { headers: jsonHeaders });
|
|
189670
|
+
} catch (e) {
|
|
189671
|
+
return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e) }, { status: 500, headers: jsonHeaders });
|
|
189672
|
+
}
|
|
189673
|
+
}
|
|
189674
|
+
case "/api/notifications":
|
|
189675
|
+
return Response.json(await dataProvider.getNotifications(), { headers: jsonHeaders });
|
|
189614
189676
|
case "/api/incidents": {
|
|
189615
189677
|
const limit = parseInt(url3.searchParams.get("limit") ?? "50", 10);
|
|
189616
189678
|
return Response.json(await dataProvider.getIncidents(limit), { headers: jsonHeaders });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CronJob } from "../cron/store";
|
|
2
|
-
import type { AgentStatus, SessionSummary, CostSummary, KanbanBoard, Goal, IncidentEntry, HealthResponse, MetricsSnapshot } from "./types";
|
|
2
|
+
import type { AgentStatus, SessionSummary, CostSummary, KanbanBoard, Goal, IncidentEntry, HealthResponse, MetricsSnapshot, NotificationEntry } from "./types";
|
|
3
3
|
export interface DataProviderConfig {
|
|
4
4
|
matrixosHome: string;
|
|
5
5
|
}
|
|
@@ -89,6 +89,7 @@ export interface DataProvider {
|
|
|
89
89
|
ok: boolean;
|
|
90
90
|
error?: string;
|
|
91
91
|
};
|
|
92
|
+
getNotifications(): Promise<NotificationEntry[]>;
|
|
92
93
|
getIncidents(limit?: number): Promise<IncidentEntry[]>;
|
|
93
94
|
getMetrics(range?: string): Promise<MetricsSnapshot[]>;
|
|
94
95
|
getLogs(): LogEntry[];
|
|
@@ -419,3 +419,13 @@ body{font-family:var(--font-body);font-size:var(--text-base);color:var(--text-pr
|
|
|
419
419
|
.schedule-table td{padding:10px 12px;border-bottom:1px solid var(--border-subtle);color:var(--text-primary)}
|
|
420
420
|
.schedule-table code{background:var(--bg-code);padding:2px 6px;border-radius:4px;font-size:11px;color:var(--text-secondary)}
|
|
421
421
|
.badge-green{background:rgba(16,185,129,.15);color:#10b981}
|
|
422
|
+
|
|
423
|
+
.notif-panel{position:absolute;top:52px;right:16px;width:320px;max-height:420px;overflow-y:auto;background:var(--bg-surface,#1a1d23);border:1px solid var(--border-default,#2a2e36);border-radius:10px;box-shadow:0 10px 30px rgba(0,0,0,.4);z-index:50;padding:8px}
|
|
424
|
+
.notif-empty{color:var(--text-tertiary);padding:16px;text-align:center;font-size:var(--text-sm)}
|
|
425
|
+
.notif-item{padding:10px 12px;border-bottom:1px solid var(--border-subtle,#222);border-left:3px solid var(--accent,#4a9eff)}
|
|
426
|
+
.notif-item:last-child{border-bottom:none}
|
|
427
|
+
.notif-kanban_failed{border-left-color:#ff6b6b}
|
|
428
|
+
.notif-incident{border-left-color:#ffa94d}
|
|
429
|
+
.notif-title{font-size:var(--text-sm);color:var(--text-primary);font-weight:600}
|
|
430
|
+
.notif-detail{font-size:var(--text-xs);color:var(--text-secondary);margin-top:2px}
|
|
431
|
+
.notif-time{font-size:var(--text-xs);color:var(--text-tertiary);margin-top:4px}
|
|
@@ -52,7 +52,8 @@
|
|
|
52
52
|
</div>
|
|
53
53
|
<div class="header-right">
|
|
54
54
|
<div class="header-search"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="6" cy="6" r="4.5"/><path d="M9.5 9.5L13 13"/></svg>Search agents, sessions...<kbd>Ctrl+K</kbd></div>
|
|
55
|
-
<button class="header-icon-btn" id="notifBtn"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M12 6a4 4 0 10-8 0c0 4-2 5-2 5h12s-2-1-2-5"/><path d="M6.5 14a1.5 1.5 0 003 0"/></svg><span class="notif-dot"></span></button>
|
|
55
|
+
<button class="header-icon-btn" id="notifBtn"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M12 6a4 4 0 10-8 0c0 4-2 5-2 5h12s-2-1-2-5"/><path d="M6.5 14a1.5 1.5 0 003 0"/></svg><span class="notif-dot" style="display:none"></span></button>
|
|
56
|
+
<div class="notif-panel" id="notifPanel" style="display:none"></div>
|
|
56
57
|
<button class="header-icon-btn" id="refreshBtn"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><polyline points="14 3 14 8 9 8"/><path d="M12.5 11.5A6 6 0 104 4L2 6"/></svg></button>
|
|
57
58
|
</div>
|
|
58
59
|
</header>
|
|
@@ -233,6 +234,29 @@
|
|
|
233
234
|
<div class="modal-footer"><button class="btn btn-secondary" onclick="closeCronModal()">Cancel</button><button class="btn btn-primary" onclick="createCron()">Create</button></div>
|
|
234
235
|
</div>
|
|
235
236
|
</div>
|
|
237
|
+
<div class="modal-overlay" id="deployModal" style="display:none">
|
|
238
|
+
<div class="modal-box">
|
|
239
|
+
<div class="modal-header"><h3>Deploy</h3><button class="modal-close" onclick="closeDeployModal()">×</button></div>
|
|
240
|
+
<div class="modal-body">
|
|
241
|
+
<label class="modal-label">Target</label>
|
|
242
|
+
<select class="input" id="deployTarget">
|
|
243
|
+
<option value="static">static</option>
|
|
244
|
+
<option value="vps">vps</option>
|
|
245
|
+
<option value="vercel">vercel</option>
|
|
246
|
+
</select>
|
|
247
|
+
<label class="modal-label">Environment</label>
|
|
248
|
+
<select class="input" id="deployEnv">
|
|
249
|
+
<option value="production">production</option>
|
|
250
|
+
<option value="staging">staging</option>
|
|
251
|
+
<option value="preview">preview</option>
|
|
252
|
+
</select>
|
|
253
|
+
<label class="modal-label">Project root</label>
|
|
254
|
+
<input class="input" id="deployRoot" placeholder="/path/to/project" />
|
|
255
|
+
<p class="modal-help">Dry-run par défaut : aucun changement. Le mode apply est en cours de câblage par target.</p>
|
|
256
|
+
</div>
|
|
257
|
+
<div class="modal-footer"><button class="btn btn-secondary" onclick="closeDeployModal()">Cancel</button><button class="btn btn-primary" onclick="runDeploy()">Dry-run</button></div>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
236
260
|
</div>
|
|
237
261
|
</div>
|
|
238
262
|
</div>
|
|
@@ -20,6 +20,8 @@ const API={
|
|
|
20
20
|
cronList:()=>fetchJSON('/cron'),
|
|
21
21
|
cronAdd:(body)=>fetchJSON('/cron',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)}),
|
|
22
22
|
cronRemove:(id)=>fetchJSON(`/cron?id=${encodeURIComponent(id)}`,{method:'DELETE'}),
|
|
23
|
+
notifications:()=>fetchJSON('/notifications'),
|
|
24
|
+
deploy:(body)=>fetchJSON('/deploy',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)}),
|
|
23
25
|
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())
|
|
24
26
|
}
|
|
25
27
|
async function fetchJSON(e, opts) {
|
|
@@ -713,9 +713,46 @@ document.getElementById('refreshBtn').onclick=()=>{const t=document.querySelecto
|
|
|
713
713
|
document.getElementById('archRefresh').onclick=()=>loadArchitect()
|
|
714
714
|
document.getElementById('newSkillBtn').onclick=()=>openSkillModal()
|
|
715
715
|
document.getElementById('newCronBtn').onclick=()=>openCronModal()
|
|
716
|
-
document.getElementById('deployBtn').onclick=()=>
|
|
716
|
+
document.getElementById('deployBtn').onclick=()=>openDeployModal()
|
|
717
|
+
function openDeployModal(){document.getElementById('deployModal').style.display='flex'}
|
|
718
|
+
function closeDeployModal(){document.getElementById('deployModal').style.display='none'}
|
|
719
|
+
async function runDeploy(){
|
|
720
|
+
const target=document.getElementById('deployTarget').value
|
|
721
|
+
const env=document.getElementById('deployEnv').value
|
|
722
|
+
const root=document.getElementById('deployRoot').value.trim()
|
|
723
|
+
closeDeployModal()
|
|
724
|
+
try{
|
|
725
|
+
const res=await API.deploy({target,environment:env,projectRoot:root||undefined,dryRun:true})
|
|
726
|
+
if(res&&res.output)alert(res.output)
|
|
727
|
+
else alert('Deploy dry-run done (no output)')
|
|
728
|
+
}catch(e){alert('Deploy failed: '+e.message)}
|
|
729
|
+
}
|
|
717
730
|
document.getElementById('diagBtn').onclick=()=>alert('Diagnostics — coming soon')
|
|
718
|
-
document.getElementById('notifBtn').onclick=()=>
|
|
731
|
+
document.getElementById('notifBtn').onclick=(e)=>{e.stopPropagation();toggleNotifications()}
|
|
732
|
+
async function loadNotifications(){
|
|
733
|
+
try{
|
|
734
|
+
const notes=await API.notifications()
|
|
735
|
+
const dot=document.querySelector('#notifBtn .notif-dot')
|
|
736
|
+
if(dot)dot.style.display=notes.length?'block':'none'
|
|
737
|
+
const panel=document.getElementById('notifPanel')
|
|
738
|
+
if(!notes.length){panel.innerHTML='<div class="notif-empty">No notifications</div>';return}
|
|
739
|
+
panel.innerHTML=notes.map(n=>`<div class="notif-item notif-${n.kind}">
|
|
740
|
+
<div class="notif-title">${n.title}</div>
|
|
741
|
+
${n.detail?`<div class="notif-detail">${n.detail}</div>`:''}
|
|
742
|
+
<div class="notif-time">${new Date(n.ts).toLocaleString()}</div>
|
|
743
|
+
</div>`).join('')
|
|
744
|
+
}catch(e){/* ignore */}
|
|
745
|
+
}
|
|
746
|
+
function toggleNotifications(){
|
|
747
|
+
const panel=document.getElementById('notifPanel')
|
|
748
|
+
if(panel.style.display==='block'){panel.style.display='none';return}
|
|
749
|
+
panel.style.display='block'
|
|
750
|
+
loadNotifications()
|
|
751
|
+
}
|
|
752
|
+
document.addEventListener('click',(e)=>{
|
|
753
|
+
const panel=document.getElementById('notifPanel')
|
|
754
|
+
if(panel&&!panel.contains(e.target)&&e.target.id!=='notifBtn')panel.style.display='none'
|
|
755
|
+
})
|
|
719
756
|
const createGoalBtn=document.getElementById('createGoalBtn')
|
|
720
757
|
if(createGoalBtn)createGoalBtn.onclick=createGoal
|
|
721
758
|
const refreshGoalsBtn=document.getElementById('refreshGoalsBtn')
|
|
@@ -724,4 +761,5 @@ const newKanbanBtn=document.getElementById('newKanbanBtn')
|
|
|
724
761
|
if(newKanbanBtn)newKanbanBtn.onclick=()=>openKanbanModal()
|
|
725
762
|
|
|
726
763
|
loadTab('architect')
|
|
764
|
+
loadNotifications()
|
|
727
765
|
setInterval(()=>{const t=document.querySelector('.header-tab.active');t&&loadTab(t.dataset.tab)},30000)
|
|
@@ -69,6 +69,13 @@ export interface IncidentEntry {
|
|
|
69
69
|
outcome: string;
|
|
70
70
|
detail?: string;
|
|
71
71
|
}
|
|
72
|
+
export interface NotificationEntry {
|
|
73
|
+
id: string;
|
|
74
|
+
kind: "kanban_failed" | "incident";
|
|
75
|
+
title: string;
|
|
76
|
+
detail: string;
|
|
77
|
+
ts: number;
|
|
78
|
+
}
|
|
72
79
|
export interface HealthResponse {
|
|
73
80
|
agentsOnline: number;
|
|
74
81
|
totalAgents: number;
|
package/dist/index.js
CHANGED
|
@@ -368086,7 +368086,7 @@ function getCachedVersion(options = {}) {
|
|
|
368086
368086
|
// package.json
|
|
368087
368087
|
var package_default = {
|
|
368088
368088
|
name: "@kl-c/matrixos",
|
|
368089
|
-
version: "0.3.
|
|
368089
|
+
version: "0.3.57",
|
|
368090
368090
|
description: "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
|
|
368091
368091
|
main: "./dist/index.js",
|
|
368092
368092
|
types: "dist/index.d.ts",
|
package/package.json
CHANGED