@kl-c/matrixos 0.3.34 → 0.3.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -2163,7 +2163,7 @@ var package_default;
2163
2163
  var init_package = __esm(() => {
2164
2164
  package_default = {
2165
2165
  name: "@kl-c/matrixos",
2166
- version: "0.3.34",
2166
+ version: "0.3.36",
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",
@@ -186953,6 +186953,11 @@ function ensureKanbanTable(db) {
186953
186953
  updated_at INTEGER NOT NULL
186954
186954
  )
186955
186955
  `);
186956
+ try {
186957
+ db.query("SELECT description FROM matrixos_kanban LIMIT 1").all();
186958
+ } catch {
186959
+ db.exec("ALTER TABLE matrixos_kanban ADD COLUMN description TEXT NOT NULL DEFAULT ''");
186960
+ }
186956
186961
  }
186957
186962
  function midnightMs() {
186958
186963
  const d = new Date;
@@ -187303,6 +187308,44 @@ function createDataProvider(config5) {
187303
187308
  db.close();
187304
187309
  }
187305
187310
  },
187311
+ async executeKanbanTask(id) {
187312
+ const db = getDbWrite();
187313
+ if (!db)
187314
+ return { ok: false, error: "database unavailable" };
187315
+ try {
187316
+ ensureKanbanTable(db);
187317
+ const row = db.query("SELECT title, description, agent, status FROM matrixos_kanban WHERE id = ?").get(id);
187318
+ if (!row)
187319
+ return { ok: false, error: "task not found" };
187320
+ const agent2 = row.agent || "Morpheus";
187321
+ const prompt = `Task: ${row.title}
187322
+ ${row.description ? `Description: ${row.description}
187323
+ ` : ""}Execute this task.`;
187324
+ db.query("UPDATE matrixos_kanban SET status = ?, updated_at = ? WHERE id = ?").run("in_progress", Date.now(), id);
187325
+ const proc = Bun.spawn({
187326
+ cmd: ["matrixos", "run", "--agent", agent2, "--json", JSON.stringify(prompt)],
187327
+ env: { ...process.env, PATH: `${process.env.PATH || ""}:/root/.bun/bin:/usr/bin` },
187328
+ stdout: "pipe",
187329
+ stderr: "pipe"
187330
+ });
187331
+ const result = await proc.exited;
187332
+ const decoder = new TextDecoder;
187333
+ const output = decoder.decode(await new Response(proc.stdout).arrayBuffer());
187334
+ const errOutput = decoder.decode(await new Response(proc.stderr).arrayBuffer());
187335
+ const combined = [output, errOutput].filter(Boolean).join(`
187336
+ `).slice(0, 4000);
187337
+ const finalStatus = result === 0 ? "completed" : "failed";
187338
+ db.query("UPDATE matrixos_kanban SET status = ?, updated_at = ? WHERE id = ?").run(finalStatus, Date.now(), id);
187339
+ return { ok: true, status: finalStatus, output: combined };
187340
+ } catch (e) {
187341
+ try {
187342
+ db.query("UPDATE matrixos_kanban SET status = ?, updated_at = ? WHERE id = ?").run("failed", Date.now(), id);
187343
+ } catch {}
187344
+ return { ok: false, error: e instanceof Error ? e.message : String(e), status: "failed" };
187345
+ } finally {
187346
+ db.close();
187347
+ }
187348
+ },
187306
187349
  async deleteKanbanTask(id) {
187307
187350
  const db = getDbWrite();
187308
187351
  if (!db)
@@ -187658,6 +187701,17 @@ function createDashboardServer(dataProvider, config5) {
187658
187701
  }
187659
187702
  return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
187660
187703
  }
187704
+ case "/api/kanban/execute": {
187705
+ if (req.method !== "POST") {
187706
+ return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
187707
+ }
187708
+ const body = await req.json();
187709
+ if (!body.id) {
187710
+ return Response.json({ ok: false, error: "id required" }, { status: 400, headers: jsonHeaders });
187711
+ }
187712
+ const result = await dataProvider.executeKanbanTask(body.id);
187713
+ return Response.json(result, { status: result.ok ? 200 : 500, headers: jsonHeaders });
187714
+ }
187661
187715
  case "/api/incidents": {
187662
187716
  const limit = parseInt(url3.searchParams.get("limit") ?? "50", 10);
187663
187717
  return Response.json(await dataProvider.getIncidents(limit), { headers: jsonHeaders });
@@ -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.34",
2166
+ version: "0.3.36",
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",
@@ -187008,6 +187008,11 @@ function ensureKanbanTable(db) {
187008
187008
  updated_at INTEGER NOT NULL
187009
187009
  )
187010
187010
  `);
187011
+ try {
187012
+ db.query("SELECT description FROM matrixos_kanban LIMIT 1").all();
187013
+ } catch {
187014
+ db.exec("ALTER TABLE matrixos_kanban ADD COLUMN description TEXT NOT NULL DEFAULT ''");
187015
+ }
187011
187016
  }
187012
187017
  function midnightMs() {
187013
187018
  const d = new Date;
@@ -187358,6 +187363,44 @@ function createDataProvider(config5) {
187358
187363
  db.close();
187359
187364
  }
187360
187365
  },
187366
+ async executeKanbanTask(id) {
187367
+ const db = getDbWrite();
187368
+ if (!db)
187369
+ return { ok: false, error: "database unavailable" };
187370
+ try {
187371
+ ensureKanbanTable(db);
187372
+ const row = db.query("SELECT title, description, agent, status FROM matrixos_kanban WHERE id = ?").get(id);
187373
+ if (!row)
187374
+ return { ok: false, error: "task not found" };
187375
+ const agent2 = row.agent || "Morpheus";
187376
+ const prompt = `Task: ${row.title}
187377
+ ${row.description ? `Description: ${row.description}
187378
+ ` : ""}Execute this task.`;
187379
+ db.query("UPDATE matrixos_kanban SET status = ?, updated_at = ? WHERE id = ?").run("in_progress", Date.now(), id);
187380
+ const proc = Bun.spawn({
187381
+ cmd: ["matrixos", "run", "--agent", agent2, "--json", JSON.stringify(prompt)],
187382
+ env: { ...process.env, PATH: `${process.env.PATH || ""}:/root/.bun/bin:/usr/bin` },
187383
+ stdout: "pipe",
187384
+ stderr: "pipe"
187385
+ });
187386
+ const result = await proc.exited;
187387
+ const decoder = new TextDecoder;
187388
+ const output = decoder.decode(await new Response(proc.stdout).arrayBuffer());
187389
+ const errOutput = decoder.decode(await new Response(proc.stderr).arrayBuffer());
187390
+ const combined = [output, errOutput].filter(Boolean).join(`
187391
+ `).slice(0, 4000);
187392
+ const finalStatus = result === 0 ? "completed" : "failed";
187393
+ db.query("UPDATE matrixos_kanban SET status = ?, updated_at = ? WHERE id = ?").run(finalStatus, Date.now(), id);
187394
+ return { ok: true, status: finalStatus, output: combined };
187395
+ } catch (e) {
187396
+ try {
187397
+ db.query("UPDATE matrixos_kanban SET status = ?, updated_at = ? WHERE id = ?").run("failed", Date.now(), id);
187398
+ } catch {}
187399
+ return { ok: false, error: e instanceof Error ? e.message : String(e), status: "failed" };
187400
+ } finally {
187401
+ db.close();
187402
+ }
187403
+ },
187361
187404
  async deleteKanbanTask(id) {
187362
187405
  const db = getDbWrite();
187363
187406
  if (!db)
@@ -187713,6 +187756,17 @@ function createDashboardServer(dataProvider, config5) {
187713
187756
  }
187714
187757
  return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
187715
187758
  }
187759
+ case "/api/kanban/execute": {
187760
+ if (req.method !== "POST") {
187761
+ return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
187762
+ }
187763
+ const body = await req.json();
187764
+ if (!body.id) {
187765
+ return Response.json({ ok: false, error: "id required" }, { status: 400, headers: jsonHeaders });
187766
+ }
187767
+ const result = await dataProvider.executeKanbanTask(body.id);
187768
+ return Response.json(result, { status: result.ok ? 200 : 500, headers: jsonHeaders });
187769
+ }
187716
187770
  case "/api/incidents": {
187717
187771
  const limit = parseInt(url3.searchParams.get("limit") ?? "50", 10);
187718
187772
  return Response.json(await dataProvider.getIncidents(limit), { headers: jsonHeaders });
@@ -15,6 +15,7 @@ export interface DataProvider {
15
15
  getKanbanTasks(): Promise<KanbanBoard>;
16
16
  createKanbanTask(input: {
17
17
  title: string;
18
+ description?: string;
18
19
  agent?: string;
19
20
  status?: string;
20
21
  priority?: string;
@@ -25,6 +26,7 @@ export interface DataProvider {
25
26
  }>;
26
27
  updateKanbanTask(id: string, input: {
27
28
  title?: string;
29
+ description?: string;
28
30
  agent?: string;
29
31
  status?: string;
30
32
  priority?: string;
@@ -32,6 +34,12 @@ export interface DataProvider {
32
34
  ok: boolean;
33
35
  error?: string;
34
36
  }>;
37
+ executeKanbanTask(id: string): Promise<{
38
+ ok: boolean;
39
+ error?: string;
40
+ output?: string;
41
+ status?: string;
42
+ }>;
35
43
  deleteKanbanTask(id: string): Promise<{
36
44
  ok: boolean;
37
45
  error?: string;
@@ -243,6 +243,11 @@ body{font-family:var(--font-body);font-size:var(--text-base);color:var(--text-pr
243
243
  .modal-box select.input option{background:var(--bg-elevated);color:var(--text-primary)}
244
244
  .modal-box textarea.input{resize:vertical;min-height:60px;font-family:var(--font-body)}
245
245
  .kanban-card-desc{font-size:var(--text-xs);color:var(--text-secondary);margin:4px 0 2px;line-height:1.4;max-height:60px;overflow:hidden}
246
+ .kanban-card-actions{display:flex;justify-content:space-between;align-items:center;gap:6px;margin-top:6px}
247
+ .kanban-run{all:unset;cursor:pointer;font-size:var(--text-xs);background:var(--success);color:#fff;border-radius:var(--radius-sm);padding:3px 8px;transition:opacity .15s}
248
+ .kanban-run:hover{opacity:.85}
249
+ .kanban-run:disabled{opacity:.4;cursor:not-allowed}
250
+ .kanban-card.running{border:1px solid var(--success);box-shadow:0 0 8px rgba(59,203,137,.2)}
246
251
  .modal-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:8px}
247
252
 
248
253
 
@@ -5,10 +5,10 @@ const API={
5
5
  sessions:(l)=>fetchJSON(`/sessions?limit=${l}`),
6
6
  cost:()=>fetchJSON('/cost'),
7
7
  kanban:()=>fetchJSON('/kanban'),
8
- kanbanCreate:(body)=>fetchJSON('/kanban/task',{method:'POST',body:JSON.stringify(body),headers:{'Content-Type':'application/json'}}),
9
- kanbanUpdate:(body)=>fetchJSON('/kanban/task',{method:'PUT',body:JSON.stringify(body),headers:{'Content-Type':'application/json'}}),
10
- kanbanDelete:(id)=>fetchJSON(`/kanban/task?id=${id}`,{method:'DELETE'}),
11
- incidents:(l)=>fetchJSON(`/incidents?limit=${l}`),
8
+ kanbanCreate:(body)=>fetchJSON('/kanban/task',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)}),
9
+ kanbanUpdate:(body)=>fetchJSON('/kanban/task',{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)}),
10
+ kanbanDelete:(id)=>fetchJSON(`/kanban/task?id=${encodeURIComponent(id)}`,{method:'DELETE'}),
11
+ kanbanExecute:(id)=>fetchJSON('/kanban/execute',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id})}),
12
12
  metrics:()=>fetchJSON('/metrics'),
13
13
  config:()=>fetchJSON('/config'),
14
14
  memory:()=>fetchJSON('/memory'),
@@ -207,11 +207,14 @@ function renderKanban(){
207
207
  return `<div class="kanban-col" data-status="${status}" ondragover="onKanbanDragOver(event)" ondragleave="onKanbanDragLeave(event)" ondrop="onKanbanDrop(event)">
208
208
  <div class="kanban-header"><span>${KANBAN_LABELS[status]}</span><span class="kanban-count">${tasks.length}</span></div>
209
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}')">
210
+ tasks.length?tasks.map(t=>`<div class="kanban-card ${t.status==='in_progress'?'running':''}" draggable="true" ondragstart="onKanbanDragStart(event,'${t.id}')" ondblclick="openKanbanModal('${t.id}')">
211
211
  <div class="kanban-card-title">${escapeHtml(t.title)}</div>
212
212
  ${t.description?`<div class="kanban-card-desc">${escapeHtml(t.description)}</div>`:''}
213
213
  <div class="kanban-card-meta"><span>${escapeHtml(t.agent)}</span><span class="prio ${t.priority}">${t.priority}</span></div>
214
- <button class="kanban-del" onclick="deleteKanbanTask('${t.id}')" title="Delete">×</button>
214
+ <div class="kanban-card-actions">
215
+ <button class="kanban-run" onclick="runKanbanTask('${t.id}')" title="Run" ${t.status==='in_progress'?'disabled':''}>▶ Run</button>
216
+ <button class="kanban-del" onclick="deleteKanbanTask('${t.id}')" title="Delete">×</button>
217
+ </div>
215
218
  </div>`).join(''):'<div style="padding:20px;text-align:center;color:var(--text-tertiary);font-size:var(--text-xs)">No tasks</div>'
216
219
  }</div>
217
220
  </div>`
@@ -316,6 +319,33 @@ async function saveKanban(id){
316
319
  }catch(err){alert('Erreur: '+err.message)}
317
320
  }
318
321
 
322
+ async function runKanbanTask(id){
323
+ const task=findKanbanTask(id)
324
+ if(!task||task.status==='in_progress')return
325
+ if(!confirm(`Exécuter "${task.title}" avec ${task.agent||'Morpheus'} ?`))return
326
+ for(const s of KANBAN_STATUSES){
327
+ kanbanData.columns[s]=(kanbanData.columns[s]||[]).filter(t=>t.id!==id)
328
+ }
329
+ task.status='in_progress'
330
+ kanbanData.columns.in_progress=(kanbanData.columns.in_progress||[])
331
+ kanbanData.columns.in_progress.unshift(task)
332
+ renderKanban()
333
+ try{
334
+ const res=await API.kanbanExecute(id)
335
+ if(!res.ok)throw new Error(res.error||'execution failed')
336
+ for(const s of KANBAN_STATUSES){
337
+ kanbanData.columns[s]=(kanbanData.columns[s]||[]).filter(t=>t.id!==id)
338
+ }
339
+ task.status=res.status||'completed'
340
+ kanbanData.columns[task.status]=(kanbanData.columns[task.status]||[])
341
+ kanbanData.columns[task.status].unshift(task)
342
+ renderKanban()
343
+ }catch(err){
344
+ alert('Erreur: '+err.message)
345
+ await loadKanban()
346
+ }
347
+ }
348
+
319
349
  // ===== LOGS =====
320
350
  let logStream=null
321
351
  async function loadLogs(){
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.34",
368022
+ version: "0.3.36",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kl-c/matrixos",
3
- "version": "0.3.34",
3
+ "version": "0.3.36",
4
4
  "description": "MaTrixOS \u2014 Agentic OS for OpenCode. Personalizable, communicating, self-improving, resilient.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "dist/index.d.ts",