@kl-c/matrixos 0.3.35 → 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.35",
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",
@@ -187308,6 +187308,44 @@ function createDataProvider(config5) {
187308
187308
  db.close();
187309
187309
  }
187310
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
+ },
187311
187349
  async deleteKanbanTask(id) {
187312
187350
  const db = getDbWrite();
187313
187351
  if (!db)
@@ -187663,6 +187701,17 @@ function createDashboardServer(dataProvider, config5) {
187663
187701
  }
187664
187702
  return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
187665
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
+ }
187666
187715
  case "/api/incidents": {
187667
187716
  const limit = parseInt(url3.searchParams.get("limit") ?? "50", 10);
187668
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.35",
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",
@@ -187363,6 +187363,44 @@ function createDataProvider(config5) {
187363
187363
  db.close();
187364
187364
  }
187365
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
+ },
187366
187404
  async deleteKanbanTask(id) {
187367
187405
  const db = getDbWrite();
187368
187406
  if (!db)
@@ -187718,6 +187756,17 @@ function createDashboardServer(dataProvider, config5) {
187718
187756
  }
187719
187757
  return new Response("Method Not Allowed", { status: 405, headers: corsHeaders });
187720
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
+ }
187721
187770
  case "/api/incidents": {
187722
187771
  const limit = parseInt(url3.searchParams.get("limit") ?? "50", 10);
187723
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.35",
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.35",
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",