@kl-c/matrixos 0.2.1 → 0.2.5

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.2.1",
2166
+ version: "0.2.5",
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",
@@ -90353,11 +90353,22 @@ class TelegramAdapter {
90353
90353
  }
90354
90354
  const text = envelope.content.text ?? "";
90355
90355
  const result = await this.bot.api.sendMessage(chatId, text);
90356
- return String(result.message_id);
90356
+ const messageId = String(result.message_id);
90357
+ if (envelope.metadata?.onMessageId && typeof envelope.metadata.onMessageId === "function") {
90358
+ envelope.metadata.onMessageId(messageId);
90359
+ }
90360
+ return messageId;
90357
90361
  } catch (err) {
90358
90362
  throw new TelegramSendError(`Failed to send Telegram message: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
90359
90363
  }
90360
90364
  }
90365
+ async editMessage(recipientId, messageId, text) {
90366
+ try {
90367
+ await this.bot.api.editMessageText(recipientId, Number(messageId), text);
90368
+ } catch (err) {
90369
+ console.warn(`[telegram] editMessage failed: ${err instanceof Error ? err.message : String(err)}`);
90370
+ }
90371
+ }
90361
90372
  onMessage(handler) {
90362
90373
  this.messageHandler = handler;
90363
90374
  }
@@ -164418,6 +164429,351 @@ var require_picomatch2 = __commonJS((exports2, module2) => {
164418
164429
  module2.exports = picomatch;
164419
164430
  });
164420
164431
 
164432
+ // packages/omo-opencode/src/features/cron/store.ts
164433
+ function createCronStore() {
164434
+ const jobs = new Map;
164435
+ let counter = 0;
164436
+ return {
164437
+ add(input) {
164438
+ counter += 1;
164439
+ const now = new Date().toISOString();
164440
+ const job = {
164441
+ id: `cron-${counter}`,
164442
+ name: input.name,
164443
+ schedule: input.schedule,
164444
+ command: input.command,
164445
+ channel: input.channel,
164446
+ recipient: input.recipient,
164447
+ enabled: input.enabled ?? true,
164448
+ createdAt: now,
164449
+ updatedAt: now
164450
+ };
164451
+ CronJobSchema.parse(job);
164452
+ jobs.set(job.id, job);
164453
+ return job;
164454
+ },
164455
+ get(id) {
164456
+ return jobs.get(id);
164457
+ },
164458
+ list(filter) {
164459
+ const all = Array.from(jobs.values());
164460
+ return all.filter((j) => {
164461
+ if (filter?.enabled !== undefined && j.enabled !== filter.enabled)
164462
+ return false;
164463
+ if (filter?.channel && j.channel !== filter.channel)
164464
+ return false;
164465
+ return true;
164466
+ });
164467
+ },
164468
+ remove(id) {
164469
+ return jobs.delete(id);
164470
+ },
164471
+ size() {
164472
+ return jobs.size;
164473
+ }
164474
+ };
164475
+ }
164476
+ var CronJobSchema;
164477
+ var init_store = __esm(() => {
164478
+ init_zod();
164479
+ CronJobSchema = object({
164480
+ id: string2().min(1),
164481
+ name: string2().min(1).max(100),
164482
+ schedule: string2().min(1).max(100),
164483
+ command: string2().min(1),
164484
+ channel: _enum2(["telegram", "discord", "whatsapp"]).optional(),
164485
+ recipient: string2().optional(),
164486
+ enabled: boolean2().default(true),
164487
+ createdAt: string2(),
164488
+ updatedAt: string2()
164489
+ }).strict();
164490
+ });
164491
+
164492
+ // packages/task-ledger-core/src/schema.ts
164493
+ var TaskSourceSchema, TaskStatusSchema, TaskPrioritySchema, TaskSchema, TaskInsertSchema, TaskPatchSchema, TaskFilterSchema;
164494
+ var init_schema2 = __esm(() => {
164495
+ init_zod();
164496
+ TaskSourceSchema = _enum2(["webhook", "cron", "user", "kanban"]);
164497
+ TaskStatusSchema = _enum2([
164498
+ "pending",
164499
+ "running",
164500
+ "done",
164501
+ "failed",
164502
+ "cancelled"
164503
+ ]);
164504
+ TaskPrioritySchema = _enum2(["high", "medium", "low"]);
164505
+ TaskSchema = object({
164506
+ id: string2().min(1),
164507
+ source: TaskSourceSchema,
164508
+ context: string2().nullable(),
164509
+ status: TaskStatusSchema,
164510
+ priority: TaskPrioritySchema.nullable(),
164511
+ payload: string2(),
164512
+ agent_assigned: string2().nullable(),
164513
+ session_id: string2().nullable(),
164514
+ result: string2().nullable(),
164515
+ cost_tokens: number2().int().nonnegative().default(0),
164516
+ cost_usd: number2().nonnegative().default(0),
164517
+ created_at: number2().int(),
164518
+ started_at: number2().int().nullable(),
164519
+ completed_at: number2().int().nullable()
164520
+ }).strict();
164521
+ TaskInsertSchema = object({
164522
+ id: string2().min(1).optional(),
164523
+ source: TaskSourceSchema,
164524
+ context: string2().nullable().optional(),
164525
+ status: TaskStatusSchema.optional(),
164526
+ priority: TaskPrioritySchema.nullable().optional(),
164527
+ payload: string2(),
164528
+ agent_assigned: string2().nullable().optional(),
164529
+ session_id: string2().nullable().optional(),
164530
+ cost_tokens: number2().int().nonnegative().optional(),
164531
+ cost_usd: number2().nonnegative().optional()
164532
+ }).strict();
164533
+ TaskPatchSchema = object({
164534
+ status: TaskStatusSchema.optional(),
164535
+ priority: TaskPrioritySchema.nullable().optional(),
164536
+ agent_assigned: string2().nullable().optional(),
164537
+ session_id: string2().nullable().optional(),
164538
+ result: string2().nullable().optional(),
164539
+ cost_tokens: number2().int().nonnegative().optional(),
164540
+ cost_usd: number2().nonnegative().optional(),
164541
+ started_at: number2().int().nullable().optional(),
164542
+ completed_at: number2().int().nullable().optional()
164543
+ }).strict();
164544
+ TaskFilterSchema = object({
164545
+ source: TaskSourceSchema.optional(),
164546
+ context: string2().optional(),
164547
+ status: TaskStatusSchema.optional(),
164548
+ agent_assigned: string2().optional(),
164549
+ session_id: string2().optional(),
164550
+ priority: TaskPrioritySchema.optional()
164551
+ }).strict();
164552
+ });
164553
+
164554
+ // packages/task-ledger-core/src/ledger.ts
164555
+ import { randomUUID as randomUUID2 } from "crypto";
164556
+ function rowToTask(row) {
164557
+ return {
164558
+ id: row.id,
164559
+ source: row.source,
164560
+ context: row.context,
164561
+ status: row.status,
164562
+ priority: row.priority,
164563
+ payload: row.payload,
164564
+ agent_assigned: row.agent_assigned,
164565
+ session_id: row.session_id,
164566
+ result: row.result,
164567
+ cost_tokens: row.cost_tokens,
164568
+ cost_usd: row.cost_usd,
164569
+ created_at: row.created_at,
164570
+ started_at: row.started_at,
164571
+ completed_at: row.completed_at
164572
+ };
164573
+ }
164574
+ function createTaskLedger(db) {
164575
+ db.exec(CREATE_TABLE_SQL);
164576
+ db.exec(CREATE_INDEX_STATUS);
164577
+ db.exec(CREATE_INDEX_CONTEXT);
164578
+ db.exec(CREATE_INDEX_SOURCE);
164579
+ return {
164580
+ insert(input) {
164581
+ const now = Date.now();
164582
+ const task2 = TaskSchema.parse({
164583
+ id: input.id ?? randomUUID2(),
164584
+ source: input.source,
164585
+ context: input.context ?? null,
164586
+ status: input.status ?? "pending",
164587
+ priority: input.priority ?? null,
164588
+ payload: input.payload,
164589
+ agent_assigned: input.agent_assigned ?? null,
164590
+ session_id: input.session_id ?? null,
164591
+ result: null,
164592
+ cost_tokens: input.cost_tokens ?? 0,
164593
+ cost_usd: input.cost_usd ?? 0,
164594
+ created_at: now,
164595
+ started_at: null,
164596
+ completed_at: null
164597
+ });
164598
+ db.exec(INSERT_SQL, {
164599
+ $id: task2.id,
164600
+ $source: task2.source,
164601
+ $context: task2.context,
164602
+ $status: task2.status,
164603
+ $priority: task2.priority,
164604
+ $payload: task2.payload,
164605
+ $agent_assigned: task2.agent_assigned,
164606
+ $session_id: task2.session_id,
164607
+ $result: task2.result,
164608
+ $cost_tokens: task2.cost_tokens,
164609
+ $cost_usd: task2.cost_usd,
164610
+ $created_at: task2.created_at,
164611
+ $started_at: task2.started_at,
164612
+ $completed_at: task2.completed_at
164613
+ });
164614
+ return task2;
164615
+ },
164616
+ get(id) {
164617
+ const rows = db.query(SELECT_BY_ID_SQL, { $id: id });
164618
+ if (rows.length === 0)
164619
+ return null;
164620
+ return rowToTask(rows[0]);
164621
+ },
164622
+ list(filter) {
164623
+ const conditions = [];
164624
+ const params = {};
164625
+ if (filter?.source) {
164626
+ conditions.push("source = $source");
164627
+ params.$source = filter.source;
164628
+ }
164629
+ if (filter?.context) {
164630
+ conditions.push("context = $context");
164631
+ params.$context = filter.context;
164632
+ }
164633
+ if (filter?.status) {
164634
+ conditions.push("status = $status");
164635
+ params.$status = filter.status;
164636
+ }
164637
+ if (filter?.agent_assigned) {
164638
+ conditions.push("agent_assigned = $agent_assigned");
164639
+ params.$agent_assigned = filter.agent_assigned;
164640
+ }
164641
+ if (filter?.session_id) {
164642
+ conditions.push("session_id = $session_id");
164643
+ params.$session_id = filter.session_id;
164644
+ }
164645
+ if (filter?.priority) {
164646
+ conditions.push("priority = $priority");
164647
+ params.$priority = filter.priority;
164648
+ }
164649
+ const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
164650
+ const sql = `SELECT * FROM tasks${where} ORDER BY created_at DESC`;
164651
+ const rows = db.query(sql, params);
164652
+ return rows.map(rowToTask);
164653
+ },
164654
+ update(id, patch) {
164655
+ const existing = db.query(SELECT_BY_ID_SQL, { $id: id });
164656
+ if (existing.length === 0)
164657
+ return null;
164658
+ const params = { $id: id };
164659
+ if (patch.status !== undefined)
164660
+ params.$status = patch.status;
164661
+ if (patch.priority !== undefined)
164662
+ params.$priority = patch.priority;
164663
+ if (patch.agent_assigned !== undefined)
164664
+ params.$agent_assigned = patch.agent_assigned;
164665
+ if (patch.session_id !== undefined)
164666
+ params.$session_id = patch.session_id;
164667
+ if (patch.result !== undefined)
164668
+ params.$result = patch.result;
164669
+ if (patch.cost_tokens !== undefined)
164670
+ params.$cost_tokens = patch.cost_tokens;
164671
+ if (patch.cost_usd !== undefined)
164672
+ params.$cost_usd = patch.cost_usd;
164673
+ if (patch.started_at !== undefined)
164674
+ params.$started_at = patch.started_at;
164675
+ if (patch.completed_at !== undefined)
164676
+ params.$completed_at = patch.completed_at;
164677
+ db.exec(UPDATE_SQL, params);
164678
+ return this.get(id);
164679
+ },
164680
+ remove(id) {
164681
+ const before = db.query(SELECT_BY_ID_SQL, { $id: id });
164682
+ if (before.length === 0)
164683
+ return false;
164684
+ db.exec(DELETE_BY_ID_SQL, { $id: id });
164685
+ return true;
164686
+ },
164687
+ listPending() {
164688
+ const rows = db.query(`SELECT * FROM tasks WHERE status = 'pending' ORDER BY created_at ASC`);
164689
+ return rows.map(rowToTask);
164690
+ },
164691
+ listFailed() {
164692
+ const rows = db.query(`SELECT * FROM tasks WHERE status = 'failed' ORDER BY created_at ASC`);
164693
+ return rows.map(rowToTask);
164694
+ },
164695
+ listByContext(context) {
164696
+ const rows = db.query(`SELECT * FROM tasks WHERE context = $context ORDER BY created_at DESC`, { $context: context });
164697
+ return rows.map(rowToTask);
164698
+ },
164699
+ close() {
164700
+ db.close();
164701
+ }
164702
+ };
164703
+ }
164704
+ var CREATE_TABLE_SQL = `
164705
+ CREATE TABLE IF NOT EXISTS tasks (
164706
+ id TEXT PRIMARY KEY,
164707
+ source TEXT NOT NULL,
164708
+ context TEXT,
164709
+ status TEXT NOT NULL,
164710
+ priority TEXT,
164711
+ payload TEXT NOT NULL,
164712
+ agent_assigned TEXT,
164713
+ session_id TEXT,
164714
+ result TEXT,
164715
+ cost_tokens INTEGER DEFAULT 0,
164716
+ cost_usd REAL DEFAULT 0,
164717
+ created_at INTEGER NOT NULL,
164718
+ started_at INTEGER,
164719
+ completed_at INTEGER
164720
+ )
164721
+ `, CREATE_INDEX_STATUS = `CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)`, CREATE_INDEX_CONTEXT = `CREATE INDEX IF NOT EXISTS idx_tasks_context ON tasks(context)`, CREATE_INDEX_SOURCE = `CREATE INDEX IF NOT EXISTS idx_tasks_source ON tasks(source)`, INSERT_SQL = `
164722
+ INSERT INTO tasks (id, source, context, status, priority, payload, agent_assigned, session_id, result, cost_tokens, cost_usd, created_at, started_at, completed_at)
164723
+ VALUES ($id, $source, $context, $status, $priority, $payload, $agent_assigned, $session_id, $result, $cost_tokens, $cost_usd, $created_at, $started_at, $completed_at)
164724
+ `, SELECT_BY_ID_SQL = `SELECT * FROM tasks WHERE id = $id`, DELETE_BY_ID_SQL = `DELETE FROM tasks WHERE id = $id`, UPDATE_SQL = `
164725
+ UPDATE tasks SET
164726
+ status = COALESCE($status, status),
164727
+ priority = COALESCE($priority, priority),
164728
+ agent_assigned = COALESCE($agent_assigned, agent_assigned),
164729
+ session_id = COALESCE($session_id, session_id),
164730
+ result = COALESCE($result, result),
164731
+ cost_tokens = COALESCE($cost_tokens, cost_tokens),
164732
+ cost_usd = COALESCE($cost_usd, cost_usd),
164733
+ started_at = COALESCE($started_at, started_at),
164734
+ completed_at = COALESCE($completed_at, completed_at)
164735
+ WHERE id = $id
164736
+ `;
164737
+ var init_ledger = __esm(() => {
164738
+ init_schema2();
164739
+ });
164740
+
164741
+ // packages/task-ledger-core/src/sqlite.ts
164742
+ import { Database as Database2 } from "bun:sqlite";
164743
+ function createSqliteDatabase(dbPath) {
164744
+ const db = new Database2(dbPath);
164745
+ db.exec("PRAGMA journal_mode = WAL");
164746
+ db.exec("PRAGMA foreign_keys = ON");
164747
+ return {
164748
+ exec(sql, ...params) {
164749
+ if (params.length === 0) {
164750
+ db.run(sql);
164751
+ } else {
164752
+ const named = params[0];
164753
+ db.run(sql, named);
164754
+ }
164755
+ },
164756
+ query(sql, ...params) {
164757
+ if (params.length === 0) {
164758
+ return db.prepare(sql).all();
164759
+ }
164760
+ const named = params[0];
164761
+ return db.prepare(sql).all(named);
164762
+ },
164763
+ close() {
164764
+ db.close();
164765
+ }
164766
+ };
164767
+ }
164768
+ var init_sqlite = () => {};
164769
+
164770
+ // packages/task-ledger-core/src/index.ts
164771
+ var init_src6 = __esm(() => {
164772
+ init_schema2();
164773
+ init_ledger();
164774
+ init_sqlite();
164775
+ });
164776
+
164421
164777
  // packages/omo-opencode/src/cli/generate.ts
164422
164778
  var exports_generate = {};
164423
164779
  __export(exports_generate, {
@@ -165020,6 +165376,264 @@ var init_export = __esm(() => {
165020
165376
  };
165021
165377
  });
165022
165378
 
165379
+ // packages/omo-opencode/src/project/project-context.ts
165380
+ var exports_project_context = {};
165381
+ __export(exports_project_context, {
165382
+ unarchiveProject: () => unarchiveProject,
165383
+ switchProject: () => switchProject,
165384
+ saveState: () => saveState,
165385
+ saveProjectMeta: () => saveProjectMeta,
165386
+ loadState: () => loadState,
165387
+ loadProjectMeta: () => loadProjectMeta,
165388
+ listProjects: () => listProjects,
165389
+ initProjectFiles: () => initProjectFiles,
165390
+ getStatePath: () => getStatePath,
165391
+ getProjectsDir: () => getProjectsDir,
165392
+ getProjectDir: () => getProjectDir,
165393
+ getMatrixOsDir: () => getMatrixOsDir,
165394
+ getActiveProject: () => getActiveProject,
165395
+ deleteProject: () => deleteProject,
165396
+ createProject: () => createProject,
165397
+ archiveProject: () => archiveProject
165398
+ });
165399
+ import { existsSync as existsSync75, mkdirSync as mkdirSync27, readFileSync as readFileSync60, writeFileSync as writeFileSync27, rmSync as rmSync8 } from "fs";
165400
+ import { join as join81 } from "path";
165401
+ function getMatrixOsDir(cwd = process.cwd()) {
165402
+ return join81(cwd, ".matrixos");
165403
+ }
165404
+ function getProjectsDir(cwd) {
165405
+ return join81(getMatrixOsDir(cwd), "projects");
165406
+ }
165407
+ function getProjectDir(slug, cwd) {
165408
+ return join81(getProjectsDir(cwd), slug);
165409
+ }
165410
+ function getStatePath(cwd) {
165411
+ return join81(getMatrixOsDir(cwd), "state.json");
165412
+ }
165413
+ function loadState(cwd) {
165414
+ const path29 = getStatePath(cwd);
165415
+ if (!existsSync75(path29))
165416
+ return {};
165417
+ try {
165418
+ return JSON.parse(readFileSync60(path29, "utf-8"));
165419
+ } catch {
165420
+ return {};
165421
+ }
165422
+ }
165423
+ function saveState(state2, cwd) {
165424
+ const path29 = getStatePath(cwd);
165425
+ mkdirSync27(getMatrixOsDir(cwd), { recursive: true });
165426
+ writeFileSync27(path29, JSON.stringify(state2, null, 2) + `
165427
+ `);
165428
+ }
165429
+ function loadProjectMeta(slug, cwd) {
165430
+ const path29 = join81(getProjectDir(slug, cwd), "meta.json");
165431
+ if (!existsSync75(path29))
165432
+ return null;
165433
+ try {
165434
+ return JSON.parse(readFileSync60(path29, "utf-8"));
165435
+ } catch {
165436
+ return null;
165437
+ }
165438
+ }
165439
+ function saveProjectMeta(slug, meta3, cwd) {
165440
+ const dir = getProjectDir(slug, cwd);
165441
+ mkdirSync27(dir, { recursive: true });
165442
+ const path29 = join81(dir, "meta.json");
165443
+ writeFileSync27(path29, JSON.stringify(meta3, null, 2) + `
165444
+ `);
165445
+ }
165446
+ function initProjectFiles(slug, cwd) {
165447
+ const dir = getProjectDir(slug, cwd);
165448
+ mkdirSync27(join81(dir, "kb"), { recursive: true });
165449
+ const kanbanPath = join81(dir, "kanban.json");
165450
+ if (!existsSync75(kanbanPath)) {
165451
+ writeFileSync27(kanbanPath, JSON.stringify({ columns: ["todo", "in-progress", "review", "done"], tasks: [] }, null, 2) + `
165452
+ `);
165453
+ }
165454
+ }
165455
+ function createProject(slug, options = {}) {
165456
+ if (!/^[a-z0-9_-]+$/.test(slug)) {
165457
+ throw new Error(`Invalid project slug "${slug}": only lowercase letters, numbers, - and _ are allowed.`);
165458
+ }
165459
+ const dir = getProjectDir(slug, options.cwd);
165460
+ if (existsSync75(dir)) {
165461
+ throw new Error(`Project "${slug}" already exists.`);
165462
+ }
165463
+ const now = new Date().toISOString();
165464
+ const meta3 = {
165465
+ slug,
165466
+ name: options.name || slug,
165467
+ description: options.description,
165468
+ createdAt: now
165469
+ };
165470
+ saveProjectMeta(slug, meta3, options.cwd);
165471
+ initProjectFiles(slug, options.cwd);
165472
+ const state2 = loadState(options.cwd);
165473
+ if (!state2.activeProject) {
165474
+ saveState({ ...state2, activeProject: slug }, options.cwd);
165475
+ }
165476
+ return { slug, meta: meta3, active: state2.activeProject === slug || !state2.activeProject };
165477
+ }
165478
+ function listProjects(cwd) {
165479
+ const state2 = loadState(cwd);
165480
+ const root = getProjectsDir(cwd);
165481
+ if (!existsSync75(root))
165482
+ return [];
165483
+ const fs24 = __require("fs");
165484
+ const items = [];
165485
+ for (const slug of fs24.readdirSync(root, { withFileTypes: true })) {
165486
+ if (!slug.isDirectory())
165487
+ continue;
165488
+ const meta3 = loadProjectMeta(slug.name, cwd);
165489
+ if (!meta3)
165490
+ continue;
165491
+ items.push({ slug: slug.name, meta: meta3, active: state2.activeProject === slug.name });
165492
+ }
165493
+ return items.sort((a2, b2) => a2.slug.localeCompare(b2.slug));
165494
+ }
165495
+ function switchProject(slug, cwd) {
165496
+ const meta3 = loadProjectMeta(slug, cwd);
165497
+ if (!meta3)
165498
+ throw new Error(`Project "${slug}" does not exist.`);
165499
+ if (meta3.archived)
165500
+ throw new Error(`Project "${slug}" is archived. Unarchive it before switching.`);
165501
+ const state2 = loadState(cwd);
165502
+ saveState({ ...state2, activeProject: slug }, cwd);
165503
+ return { slug, meta: meta3, active: true };
165504
+ }
165505
+ function archiveProject(slug, cwd) {
165506
+ const meta3 = loadProjectMeta(slug, cwd);
165507
+ if (!meta3)
165508
+ throw new Error(`Project "${slug}" does not exist.`);
165509
+ const now = new Date().toISOString();
165510
+ const next = { ...meta3, archived: true, archivedAt: now };
165511
+ saveProjectMeta(slug, next, cwd);
165512
+ const state2 = loadState(cwd);
165513
+ if (state2.activeProject === slug) {
165514
+ saveState({ ...state2, activeProject: undefined }, cwd);
165515
+ }
165516
+ return { slug, meta: next, active: false };
165517
+ }
165518
+ function unarchiveProject(slug, cwd) {
165519
+ const meta3 = loadProjectMeta(slug, cwd);
165520
+ if (!meta3)
165521
+ throw new Error(`Project "${slug}" does not exist.`);
165522
+ const { archived: _a3, archivedAt: _b, ...rest } = meta3;
165523
+ const next = rest;
165524
+ saveProjectMeta(slug, next, cwd);
165525
+ return { slug, meta: next, active: loadState(cwd).activeProject === slug };
165526
+ }
165527
+ function deleteProject(slug, cwd) {
165528
+ const dir = getProjectDir(slug, cwd);
165529
+ if (!existsSync75(dir))
165530
+ throw new Error(`Project "${slug}" does not exist.`);
165531
+ rmSync8(dir, { recursive: true, force: true });
165532
+ const state2 = loadState(cwd);
165533
+ if (state2.activeProject === slug) {
165534
+ saveState({ ...state2, activeProject: undefined }, cwd);
165535
+ }
165536
+ }
165537
+ function getActiveProject(cwd) {
165538
+ const state2 = loadState(cwd);
165539
+ if (!state2.activeProject)
165540
+ return null;
165541
+ const meta3 = loadProjectMeta(state2.activeProject, cwd);
165542
+ if (!meta3) {
165543
+ saveState({ ...state2, activeProject: undefined }, cwd);
165544
+ return null;
165545
+ }
165546
+ return { slug: state2.activeProject, meta: meta3, active: true };
165547
+ }
165548
+ var init_project_context = () => {};
165549
+
165550
+ // packages/omo-opencode/src/project/project-memory.ts
165551
+ var exports_project_memory = {};
165552
+ __export(exports_project_memory, {
165553
+ tagWithProject: () => tagWithProject,
165554
+ searchProject: () => searchProject,
165555
+ searchKb: () => searchKb,
165556
+ listKbDocuments: () => listKbDocuments,
165557
+ isProjectEpisode: () => isProjectEpisode,
165558
+ addKbDocument: () => addKbDocument
165559
+ });
165560
+ import { existsSync as existsSync76, mkdirSync as mkdirSync28, readFileSync as readFileSync61, readdirSync as readdirSync16, writeFileSync as writeFileSync28 } from "fs";
165561
+ import { join as join82 } from "path";
165562
+ function tagWithProject(metadata = {}, projectSlug, cwd) {
165563
+ const active = projectSlug ?? getActiveProject(cwd)?.slug;
165564
+ if (!active)
165565
+ return metadata;
165566
+ return { ...metadata, project: active };
165567
+ }
165568
+ function isProjectEpisode(ep, projectSlug, cwd) {
165569
+ const target = projectSlug ?? getActiveProject(cwd)?.slug;
165570
+ if (!target)
165571
+ return true;
165572
+ return ep.metadata?.project === target;
165573
+ }
165574
+ function listKbDocuments(projectSlug, cwd) {
165575
+ const kbDir = join82(getProjectDir(projectSlug, cwd), "kb");
165576
+ if (!existsSync76(kbDir))
165577
+ return [];
165578
+ const docs = [];
165579
+ for (const entry of readdirSync16(kbDir, { withFileTypes: true })) {
165580
+ if (!entry.isFile())
165581
+ continue;
165582
+ const path29 = join82(kbDir, entry.name);
165583
+ try {
165584
+ docs.push({ path: path29, content: readFileSync61(path29, "utf-8") });
165585
+ } catch {}
165586
+ }
165587
+ return docs;
165588
+ }
165589
+ function searchKb(projectSlug, query, cwd) {
165590
+ const needle = query.toLowerCase();
165591
+ const docs = listKbDocuments(projectSlug, cwd);
165592
+ const results = [];
165593
+ for (const doc2 of docs) {
165594
+ const content = doc2.content.toLowerCase();
165595
+ const matches = content.split(needle).length - 1;
165596
+ if (matches > 0) {
165597
+ results.push({
165598
+ project: projectSlug,
165599
+ source: "kb",
165600
+ path: doc2.path,
165601
+ content: doc2.content.slice(0, 240),
165602
+ score: matches
165603
+ });
165604
+ }
165605
+ }
165606
+ return results.sort((a2, b2) => b2.score - a2.score);
165607
+ }
165608
+ async function searchProject(query, options = {}) {
165609
+ const projectSlug = options.projectSlug ?? getActiveProject(options.cwd)?.slug;
165610
+ if (!projectSlug)
165611
+ return [];
165612
+ const kbHits = searchKb(projectSlug, query, options.cwd);
165613
+ let memoryHits = [];
165614
+ if (options.memoryStore) {
165615
+ const episodes = options.memoryStore.searchEpisodes?.({ textContains: query, limit: 20 }) ?? [];
165616
+ memoryHits = episodes.filter((ep) => ep.metadata?.project === projectSlug).map((ep) => ({
165617
+ project: projectSlug,
165618
+ source: "episode",
165619
+ summary: ep.summary,
165620
+ score: 1
165621
+ }));
165622
+ }
165623
+ return [...kbHits, ...memoryHits].sort((a2, b2) => b2.score - a2.score);
165624
+ }
165625
+ function addKbDocument(projectSlug, filename, content, cwd) {
165626
+ const kbDir = join82(getProjectDir(projectSlug, cwd), "kb");
165627
+ mkdirSync28(kbDir, { recursive: true });
165628
+ const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_");
165629
+ const path29 = join82(kbDir, safeName);
165630
+ writeFileSync28(path29, content, "utf-8");
165631
+ return path29;
165632
+ }
165633
+ var init_project_memory = __esm(() => {
165634
+ init_project_context();
165635
+ });
165636
+
165023
165637
  // packages/omo-opencode/src/cli/adopt.ts
165024
165638
  var exports_adopt = {};
165025
165639
  __export(exports_adopt, {
@@ -165347,12 +165961,12 @@ __export(exports_gateway_start, {
165347
165961
  buildTelegramConfig: () => buildTelegramConfig,
165348
165962
  buildGatewayConfig: () => buildGatewayConfig
165349
165963
  });
165350
- import { readFileSync as readFileSync60, existsSync as existsSync75 } from "fs";
165964
+ import { readFileSync as readFileSync62, existsSync as existsSync77 } from "fs";
165351
165965
  import { resolve as resolve19 } from "path";
165352
165966
  function loadGatewayEnv(path29 = ENV_PATH) {
165353
- if (!existsSync75(path29))
165967
+ if (!existsSync77(path29))
165354
165968
  return {};
165355
- const text = readFileSync60(path29, "utf8");
165969
+ const text = readFileSync62(path29, "utf8");
165356
165970
  const out = {};
165357
165971
  for (const raw of text.split(/\r?\n/)) {
165358
165972
  const line = raw.trim();
@@ -165472,6 +166086,188 @@ var init_gateway_start = __esm(() => {
165472
166086
  ENV_PATH = resolve19(process.cwd(), ".klc-gateway.env");
165473
166087
  });
165474
166088
 
166089
+ // packages/omo-opencode/src/audit/self-audit.ts
166090
+ import { existsSync as existsSync78, mkdirSync as mkdirSync29, readdirSync as readdirSync17, readFileSync as readFileSync63, writeFileSync as writeFileSync29 } from "fs";
166091
+ import { join as join83 } from "path";
166092
+ function getAuditDir(cwd = process.cwd()) {
166093
+ return join83(cwd, ".matrixos", "audits");
166094
+ }
166095
+ function getWeekString(date5 = new Date) {
166096
+ const d = new Date(Date.UTC(date5.getFullYear(), date5.getMonth(), date5.getDate()));
166097
+ const dayNum = d.getUTCDay() || 7;
166098
+ d.setUTCDate(d.getUTCDate() + 4 - dayNum);
166099
+ const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
166100
+ const weekNo = Math.ceil(((+d - +yearStart) / 86400000 + 1) / 7);
166101
+ return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, "0")}`;
166102
+ }
166103
+ function parseWeekDateRange(weekStr) {
166104
+ const [year, week] = weekStr.split("-W").map(Number);
166105
+ const jan4 = new Date(Date.UTC(year, 0, 4));
166106
+ const monday = new Date(Date.UTC(year, 0, 4 - ((jan4.getUTCDay() || 7) - 1) + (week - 1) * 7));
166107
+ const sunday = new Date(+monday + 6 * 86400000);
166108
+ return { from: monday.toISOString().slice(0, 10), to: sunday.toISOString().slice(0, 10) };
166109
+ }
166110
+ function generateAuditReport(tasks, signals, weekStr) {
166111
+ const week = weekStr ?? getWeekString();
166112
+ const period = parseWeekDateRange(week);
166113
+ const summary = {
166114
+ total: tasks.length,
166115
+ done: tasks.filter((t2) => t2.status === "done").length,
166116
+ failed: tasks.filter((t2) => t2.status === "failed").length,
166117
+ inProgress: tasks.filter((t2) => t2.status === "in-progress").length,
166118
+ blocked: tasks.filter((t2) => t2.status === "blocked").length
166119
+ };
166120
+ const byProject = {};
166121
+ for (const t2 of tasks) {
166122
+ const p2 = t2.project || "default";
166123
+ byProject[p2] = byProject[p2] || { done: 0, failed: 0, blocked: 0 };
166124
+ if (t2.status === "done")
166125
+ byProject[p2].done += 1;
166126
+ if (t2.status === "failed")
166127
+ byProject[p2].failed += 1;
166128
+ if (t2.status === "blocked")
166129
+ byProject[p2].blocked += 1;
166130
+ }
166131
+ const errorCounts = new Map;
166132
+ for (const s of signals) {
166133
+ if (s.type !== "error")
166134
+ continue;
166135
+ const key = `${s.project || "global"}: ${s.message}`;
166136
+ errorCounts.set(key, (errorCounts.get(key) || 0) + (s.count || 1));
166137
+ }
166138
+ const topErrors = [...errorCounts.entries()].sort((a2, b2) => b2[1] - a2[1]).slice(0, 5).map(([message, count]) => ({ type: "error", message, count }));
166139
+ const recommendations = [];
166140
+ if (summary.failed > 0) {
166141
+ recommendations.push(`Analyser ${summary.failed} t\xE2che(s) en \xE9chec et cr\xE9er une skill/r\xE8gle par pattern r\xE9current.`);
166142
+ }
166143
+ if (summary.blocked > 0) {
166144
+ recommendations.push(`D\xE9bloquer ${summary.blocked} t\xE2che(s) bloqu\xE9es avant le prochain sprint.`);
166145
+ }
166146
+ if (topErrors.length > 0) {
166147
+ recommendations.push(`Top erreur : "${topErrors[0].message}" \u2014 prioriser un guard/automated fix.`);
166148
+ }
166149
+ if (recommendations.length === 0) {
166150
+ recommendations.push("Semaine propre. Poursuivre la veille et la documentation des d\xE9cisions.");
166151
+ }
166152
+ return { week, period, summary, byProject, topErrors, recommendations };
166153
+ }
166154
+ function formatAuditReport(report) {
166155
+ const lines = [
166156
+ `# Auto-audit hebdomadaire \u2014 ${report.week}`,
166157
+ "",
166158
+ `**P\xE9riode** : ${report.period.from} \u2192 ${report.period.to}`,
166159
+ "",
166160
+ "## R\xE9sum\xE9",
166161
+ "",
166162
+ `| M\xE9trique | Valeur |`,
166163
+ `|----------|--------|`,
166164
+ `| Total | ${report.summary.total} |`,
166165
+ `| Termin\xE9es | ${report.summary.done} |`,
166166
+ `| \xC9chou\xE9es | ${report.summary.failed} |`,
166167
+ `| En cours | ${report.summary.inProgress} |`,
166168
+ `| Bloqu\xE9es | ${report.summary.blocked} |`,
166169
+ "",
166170
+ "## Par projet",
166171
+ "",
166172
+ `| Projet | Termin\xE9es | \xC9chou\xE9es | Bloqu\xE9es |`,
166173
+ `|--------|-----------|----------|----------|`
166174
+ ];
166175
+ for (const [project, stats] of Object.entries(report.byProject).sort()) {
166176
+ lines.push(`| ${project} | ${stats.done} | ${stats.failed} | ${stats.blocked} |`);
166177
+ }
166178
+ lines.push("");
166179
+ lines.push("## Top erreurs");
166180
+ lines.push("");
166181
+ if (report.topErrors.length === 0) {
166182
+ lines.push("Aucune erreur significative cette semaine.");
166183
+ } else {
166184
+ for (const err of report.topErrors) {
166185
+ lines.push(`- **${err.count}\xD7** ${err.message}`);
166186
+ }
166187
+ }
166188
+ lines.push("");
166189
+ lines.push("## Recommandations");
166190
+ lines.push("");
166191
+ for (const rec of report.recommendations) {
166192
+ lines.push(`- ${rec}`);
166193
+ }
166194
+ lines.push("");
166195
+ return lines.join(`
166196
+ `);
166197
+ }
166198
+ function writeAuditReport(report, cwd) {
166199
+ const dir = getAuditDir(cwd);
166200
+ mkdirSync29(dir, { recursive: true });
166201
+ const path29 = join83(dir, `${report.week}.md`);
166202
+ writeFileSync29(path29, formatAuditReport(report), "utf-8");
166203
+ return path29;
166204
+ }
166205
+ var init_self_audit = () => {};
166206
+
166207
+ // packages/omo-opencode/src/cli/self-audit-command.ts
166208
+ var exports_self_audit_command = {};
166209
+ __export(exports_self_audit_command, {
166210
+ normalizeStatus: () => normalizeStatus,
166211
+ executeSelfAuditCommand: () => executeSelfAuditCommand
166212
+ });
166213
+ async function executeSelfAuditCommand(options = {}) {
166214
+ if (options.installCron) {
166215
+ const store4 = createCronStore();
166216
+ const job = store4.add({
166217
+ name: "Weekly self-audit",
166218
+ schedule: "0 22 * * 0",
166219
+ command: "matrixos self-audit",
166220
+ channel: undefined,
166221
+ recipient: undefined,
166222
+ enabled: true
166223
+ });
166224
+ return { ok: true, message: `Weekly self-audit cron job installed: ${job.id}` };
166225
+ }
166226
+ const dbPath = options.tasksDb ?? process.env.TASK_LEDGER_DB ?? "/root/.matrixos/tasks.db";
166227
+ let tasks = [];
166228
+ let signals = [];
166229
+ try {
166230
+ const rawLedger = createTaskLedger(createSqliteDatabase(dbPath));
166231
+ const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
166232
+ const allTasks = rawLedger.list?.() ?? [];
166233
+ tasks = allTasks.filter((t2) => !t2.created_at || String(t2.created_at) >= since);
166234
+ } catch (err) {
166235
+ const detail = err instanceof Error ? err.message : String(err);
166236
+ return {
166237
+ ok: false,
166238
+ message: `Could not read task ledger at ${dbPath}: ${detail}`
166239
+ };
166240
+ }
166241
+ const report = generateAuditReport(tasks.map((t2) => ({
166242
+ id: String(t2.id ?? t2.task_id ?? "unknown"),
166243
+ title: String(t2.title ?? t2.summary ?? "untitled"),
166244
+ status: normalizeStatus(t2.status),
166245
+ project: t2.project || t2.context?.project || undefined,
166246
+ errorCount: t2.error_count || t2.errorCount || 0
166247
+ })), signals, options.week);
166248
+ const path29 = writeAuditReport(report);
166249
+ return { ok: true, path: path29, message: `Self-audit written to ${path29}`, report };
166250
+ }
166251
+ function normalizeStatus(status2) {
166252
+ if (!status2)
166253
+ return "in-progress";
166254
+ const s = String(status2).toLowerCase();
166255
+ if (["done", "completed", "finished", "closed"].includes(s))
166256
+ return "done";
166257
+ if (["fail", "failed", "error"].includes(s))
166258
+ return "failed";
166259
+ if (["blocked", "stuck"].includes(s))
166260
+ return "blocked";
166261
+ if (["in-progress", "in_progress", "wip", "active"].includes(s))
166262
+ return "in-progress";
166263
+ return s;
166264
+ }
166265
+ var init_self_audit_command = __esm(() => {
166266
+ init_src6();
166267
+ init_store();
166268
+ init_self_audit();
166269
+ });
166270
+
165475
166271
  // packages/omo-opencode/src/cli/rgpd-command.ts
165476
166272
  var exports_rgpd_command = {};
165477
166273
  __export(exports_rgpd_command, {
@@ -180196,64 +180992,8 @@ async function boulder(options) {
180196
180992
  `);
180197
180993
  return 0;
180198
180994
  }
180199
- // packages/omo-opencode/src/features/cron/store.ts
180200
- init_zod();
180201
- var CronJobSchema = object({
180202
- id: string2().min(1),
180203
- name: string2().min(1).max(100),
180204
- schedule: string2().min(1).max(100),
180205
- command: string2().min(1),
180206
- channel: _enum2(["telegram", "discord", "whatsapp"]).optional(),
180207
- recipient: string2().optional(),
180208
- enabled: boolean2().default(true),
180209
- createdAt: string2(),
180210
- updatedAt: string2()
180211
- }).strict();
180212
- function createCronStore() {
180213
- const jobs = new Map;
180214
- let counter = 0;
180215
- return {
180216
- add(input) {
180217
- counter += 1;
180218
- const now = new Date().toISOString();
180219
- const job = {
180220
- id: `cron-${counter}`,
180221
- name: input.name,
180222
- schedule: input.schedule,
180223
- command: input.command,
180224
- channel: input.channel,
180225
- recipient: input.recipient,
180226
- enabled: input.enabled ?? true,
180227
- createdAt: now,
180228
- updatedAt: now
180229
- };
180230
- CronJobSchema.parse(job);
180231
- jobs.set(job.id, job);
180232
- return job;
180233
- },
180234
- get(id) {
180235
- return jobs.get(id);
180236
- },
180237
- list(filter) {
180238
- const all = Array.from(jobs.values());
180239
- return all.filter((j) => {
180240
- if (filter?.enabled !== undefined && j.enabled !== filter.enabled)
180241
- return false;
180242
- if (filter?.channel && j.channel !== filter.channel)
180243
- return false;
180244
- return true;
180245
- });
180246
- },
180247
- remove(id) {
180248
- return jobs.delete(id);
180249
- },
180250
- size() {
180251
- return jobs.size;
180252
- }
180253
- };
180254
- }
180255
-
180256
180995
  // packages/omo-opencode/src/cli/cron.ts
180996
+ init_store();
180257
180997
  var store2 = createCronStore();
180258
180998
  function cronAdd(options) {
180259
180999
  const job = store2.add({
@@ -180406,289 +181146,12 @@ function createDailyBrief(opts) {
180406
181146
  };
180407
181147
  }
180408
181148
 
180409
- // packages/task-ledger-core/src/schema.ts
180410
- init_zod();
180411
- var TaskSourceSchema = _enum2(["webhook", "cron", "user", "kanban"]);
180412
- var TaskStatusSchema = _enum2([
180413
- "pending",
180414
- "running",
180415
- "done",
180416
- "failed",
180417
- "cancelled"
180418
- ]);
180419
- var TaskPrioritySchema = _enum2(["high", "medium", "low"]);
180420
- var TaskSchema = object({
180421
- id: string2().min(1),
180422
- source: TaskSourceSchema,
180423
- context: string2().nullable(),
180424
- status: TaskStatusSchema,
180425
- priority: TaskPrioritySchema.nullable(),
180426
- payload: string2(),
180427
- agent_assigned: string2().nullable(),
180428
- session_id: string2().nullable(),
180429
- result: string2().nullable(),
180430
- cost_tokens: number2().int().nonnegative().default(0),
180431
- cost_usd: number2().nonnegative().default(0),
180432
- created_at: number2().int(),
180433
- started_at: number2().int().nullable(),
180434
- completed_at: number2().int().nullable()
180435
- }).strict();
180436
- var TaskInsertSchema = object({
180437
- id: string2().min(1).optional(),
180438
- source: TaskSourceSchema,
180439
- context: string2().nullable().optional(),
180440
- status: TaskStatusSchema.optional(),
180441
- priority: TaskPrioritySchema.nullable().optional(),
180442
- payload: string2(),
180443
- agent_assigned: string2().nullable().optional(),
180444
- session_id: string2().nullable().optional(),
180445
- cost_tokens: number2().int().nonnegative().optional(),
180446
- cost_usd: number2().nonnegative().optional()
180447
- }).strict();
180448
- var TaskPatchSchema = object({
180449
- status: TaskStatusSchema.optional(),
180450
- priority: TaskPrioritySchema.nullable().optional(),
180451
- agent_assigned: string2().nullable().optional(),
180452
- session_id: string2().nullable().optional(),
180453
- result: string2().nullable().optional(),
180454
- cost_tokens: number2().int().nonnegative().optional(),
180455
- cost_usd: number2().nonnegative().optional(),
180456
- started_at: number2().int().nullable().optional(),
180457
- completed_at: number2().int().nullable().optional()
180458
- }).strict();
180459
- var TaskFilterSchema = object({
180460
- source: TaskSourceSchema.optional(),
180461
- context: string2().optional(),
180462
- status: TaskStatusSchema.optional(),
180463
- agent_assigned: string2().optional(),
180464
- session_id: string2().optional(),
180465
- priority: TaskPrioritySchema.optional()
180466
- }).strict();
180467
-
180468
- // packages/task-ledger-core/src/ledger.ts
180469
- import { randomUUID as randomUUID2 } from "crypto";
180470
- var CREATE_TABLE_SQL = `
180471
- CREATE TABLE IF NOT EXISTS tasks (
180472
- id TEXT PRIMARY KEY,
180473
- source TEXT NOT NULL,
180474
- context TEXT,
180475
- status TEXT NOT NULL,
180476
- priority TEXT,
180477
- payload TEXT NOT NULL,
180478
- agent_assigned TEXT,
180479
- session_id TEXT,
180480
- result TEXT,
180481
- cost_tokens INTEGER DEFAULT 0,
180482
- cost_usd REAL DEFAULT 0,
180483
- created_at INTEGER NOT NULL,
180484
- started_at INTEGER,
180485
- completed_at INTEGER
180486
- )
180487
- `;
180488
- var CREATE_INDEX_STATUS = `CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)`;
180489
- var CREATE_INDEX_CONTEXT = `CREATE INDEX IF NOT EXISTS idx_tasks_context ON tasks(context)`;
180490
- var CREATE_INDEX_SOURCE = `CREATE INDEX IF NOT EXISTS idx_tasks_source ON tasks(source)`;
180491
- var INSERT_SQL = `
180492
- INSERT INTO tasks (id, source, context, status, priority, payload, agent_assigned, session_id, result, cost_tokens, cost_usd, created_at, started_at, completed_at)
180493
- VALUES ($id, $source, $context, $status, $priority, $payload, $agent_assigned, $session_id, $result, $cost_tokens, $cost_usd, $created_at, $started_at, $completed_at)
180494
- `;
180495
- var SELECT_BY_ID_SQL = `SELECT * FROM tasks WHERE id = $id`;
180496
- var DELETE_BY_ID_SQL = `DELETE FROM tasks WHERE id = $id`;
180497
- var UPDATE_SQL = `
180498
- UPDATE tasks SET
180499
- status = COALESCE($status, status),
180500
- priority = COALESCE($priority, priority),
180501
- agent_assigned = COALESCE($agent_assigned, agent_assigned),
180502
- session_id = COALESCE($session_id, session_id),
180503
- result = COALESCE($result, result),
180504
- cost_tokens = COALESCE($cost_tokens, cost_tokens),
180505
- cost_usd = COALESCE($cost_usd, cost_usd),
180506
- started_at = COALESCE($started_at, started_at),
180507
- completed_at = COALESCE($completed_at, completed_at)
180508
- WHERE id = $id
180509
- `;
180510
- function rowToTask(row) {
180511
- return {
180512
- id: row.id,
180513
- source: row.source,
180514
- context: row.context,
180515
- status: row.status,
180516
- priority: row.priority,
180517
- payload: row.payload,
180518
- agent_assigned: row.agent_assigned,
180519
- session_id: row.session_id,
180520
- result: row.result,
180521
- cost_tokens: row.cost_tokens,
180522
- cost_usd: row.cost_usd,
180523
- created_at: row.created_at,
180524
- started_at: row.started_at,
180525
- completed_at: row.completed_at
180526
- };
180527
- }
180528
- function createTaskLedger(db) {
180529
- db.exec(CREATE_TABLE_SQL);
180530
- db.exec(CREATE_INDEX_STATUS);
180531
- db.exec(CREATE_INDEX_CONTEXT);
180532
- db.exec(CREATE_INDEX_SOURCE);
180533
- return {
180534
- insert(input) {
180535
- const now = Date.now();
180536
- const task2 = TaskSchema.parse({
180537
- id: input.id ?? randomUUID2(),
180538
- source: input.source,
180539
- context: input.context ?? null,
180540
- status: input.status ?? "pending",
180541
- priority: input.priority ?? null,
180542
- payload: input.payload,
180543
- agent_assigned: input.agent_assigned ?? null,
180544
- session_id: input.session_id ?? null,
180545
- result: null,
180546
- cost_tokens: input.cost_tokens ?? 0,
180547
- cost_usd: input.cost_usd ?? 0,
180548
- created_at: now,
180549
- started_at: null,
180550
- completed_at: null
180551
- });
180552
- db.exec(INSERT_SQL, {
180553
- $id: task2.id,
180554
- $source: task2.source,
180555
- $context: task2.context,
180556
- $status: task2.status,
180557
- $priority: task2.priority,
180558
- $payload: task2.payload,
180559
- $agent_assigned: task2.agent_assigned,
180560
- $session_id: task2.session_id,
180561
- $result: task2.result,
180562
- $cost_tokens: task2.cost_tokens,
180563
- $cost_usd: task2.cost_usd,
180564
- $created_at: task2.created_at,
180565
- $started_at: task2.started_at,
180566
- $completed_at: task2.completed_at
180567
- });
180568
- return task2;
180569
- },
180570
- get(id) {
180571
- const rows = db.query(SELECT_BY_ID_SQL, { $id: id });
180572
- if (rows.length === 0)
180573
- return null;
180574
- return rowToTask(rows[0]);
180575
- },
180576
- list(filter) {
180577
- const conditions = [];
180578
- const params = {};
180579
- if (filter?.source) {
180580
- conditions.push("source = $source");
180581
- params.$source = filter.source;
180582
- }
180583
- if (filter?.context) {
180584
- conditions.push("context = $context");
180585
- params.$context = filter.context;
180586
- }
180587
- if (filter?.status) {
180588
- conditions.push("status = $status");
180589
- params.$status = filter.status;
180590
- }
180591
- if (filter?.agent_assigned) {
180592
- conditions.push("agent_assigned = $agent_assigned");
180593
- params.$agent_assigned = filter.agent_assigned;
180594
- }
180595
- if (filter?.session_id) {
180596
- conditions.push("session_id = $session_id");
180597
- params.$session_id = filter.session_id;
180598
- }
180599
- if (filter?.priority) {
180600
- conditions.push("priority = $priority");
180601
- params.$priority = filter.priority;
180602
- }
180603
- const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
180604
- const sql = `SELECT * FROM tasks${where} ORDER BY created_at DESC`;
180605
- const rows = db.query(sql, params);
180606
- return rows.map(rowToTask);
180607
- },
180608
- update(id, patch) {
180609
- const existing = db.query(SELECT_BY_ID_SQL, { $id: id });
180610
- if (existing.length === 0)
180611
- return null;
180612
- const params = { $id: id };
180613
- if (patch.status !== undefined)
180614
- params.$status = patch.status;
180615
- if (patch.priority !== undefined)
180616
- params.$priority = patch.priority;
180617
- if (patch.agent_assigned !== undefined)
180618
- params.$agent_assigned = patch.agent_assigned;
180619
- if (patch.session_id !== undefined)
180620
- params.$session_id = patch.session_id;
180621
- if (patch.result !== undefined)
180622
- params.$result = patch.result;
180623
- if (patch.cost_tokens !== undefined)
180624
- params.$cost_tokens = patch.cost_tokens;
180625
- if (patch.cost_usd !== undefined)
180626
- params.$cost_usd = patch.cost_usd;
180627
- if (patch.started_at !== undefined)
180628
- params.$started_at = patch.started_at;
180629
- if (patch.completed_at !== undefined)
180630
- params.$completed_at = patch.completed_at;
180631
- db.exec(UPDATE_SQL, params);
180632
- return this.get(id);
180633
- },
180634
- remove(id) {
180635
- const before = db.query(SELECT_BY_ID_SQL, { $id: id });
180636
- if (before.length === 0)
180637
- return false;
180638
- db.exec(DELETE_BY_ID_SQL, { $id: id });
180639
- return true;
180640
- },
180641
- listPending() {
180642
- const rows = db.query(`SELECT * FROM tasks WHERE status = 'pending' ORDER BY created_at ASC`);
180643
- return rows.map(rowToTask);
180644
- },
180645
- listFailed() {
180646
- const rows = db.query(`SELECT * FROM tasks WHERE status = 'failed' ORDER BY created_at ASC`);
180647
- return rows.map(rowToTask);
180648
- },
180649
- listByContext(context) {
180650
- const rows = db.query(`SELECT * FROM tasks WHERE context = $context ORDER BY created_at DESC`, { $context: context });
180651
- return rows.map(rowToTask);
180652
- },
180653
- close() {
180654
- db.close();
180655
- }
180656
- };
180657
- }
180658
-
180659
- // packages/task-ledger-core/src/sqlite.ts
180660
- import { Database as Database2 } from "bun:sqlite";
180661
- function createSqliteDatabase(dbPath) {
180662
- const db = new Database2(dbPath);
180663
- db.exec("PRAGMA journal_mode = WAL");
180664
- db.exec("PRAGMA foreign_keys = ON");
180665
- return {
180666
- exec(sql, ...params) {
180667
- if (params.length === 0) {
180668
- db.run(sql);
180669
- } else {
180670
- const named = params[0];
180671
- db.run(sql, named);
180672
- }
180673
- },
180674
- query(sql, ...params) {
180675
- if (params.length === 0) {
180676
- return db.prepare(sql).all();
180677
- }
180678
- const named = params[0];
180679
- return db.prepare(sql).all(named);
180680
- },
180681
- close() {
180682
- db.close();
180683
- }
180684
- };
180685
- }
180686
-
180687
181149
  // packages/omo-opencode/src/cli/daily-brief.ts
181150
+ init_src6();
180688
181151
  async function dailyBriefSend(options) {
180689
181152
  try {
180690
181153
  const rawLedger = createTaskLedger(createSqliteDatabase(process.env.TASK_LEDGER_DB ?? "/root/.matrixos/tasks.db"));
180691
- const ledger = {
181154
+ const ledger2 = {
180692
181155
  listPending: () => rawLedger.listPending(),
180693
181156
  listFailed: () => rawLedger.list({ status: "failed" })
180694
181157
  };
@@ -180713,7 +181176,7 @@ async function dailyBriefSend(options) {
180713
181176
  recipient_id: recipient,
180714
181177
  channel
180715
181178
  }),
180716
- ledger,
181179
+ ledger: ledger2,
180717
181180
  sender,
180718
181181
  now: () => Date.now()
180719
181182
  });
@@ -186007,7 +186470,7 @@ function createDataProvider(config5) {
186007
186470
  } catch {}
186008
186471
  if (entries.length > 0)
186009
186472
  return entries;
186010
- const types15 = ["episodic", "semantic", "procedural", "reflection"];
186473
+ const types16 = ["episodic", "semantic", "procedural", "reflection"];
186011
186474
  const mockContent = [
186012
186475
  "User prefers concise responses with bullet points",
186013
186476
  "Project MaTrixOS uses Bun runtime and TypeScript strict mode",
@@ -186021,7 +186484,7 @@ function createDataProvider(config5) {
186021
186484
  entries.push({
186022
186485
  id: `mem_${randomBetween(1000, 9999)}`,
186023
186486
  content: randomChoice(mockContent),
186024
- type: randomChoice(types15),
186487
+ type: randomChoice(types16),
186025
186488
  confidence: Math.round(randomBetween(60, 99)),
186026
186489
  created_at: new Date(Date.now() - randomBetween(0, 604800000)).toISOString()
186027
186490
  });
@@ -186791,6 +187254,63 @@ program2.command("export [name]").description("Export a mini-OS profile as a sta
186791
187254
  process.exit(result.exitCode);
186792
187255
  });
186793
187256
  program2.addCommand(createMcpOAuthCommand());
187257
+ var project = program2.command("project").description("Manage MaTrixOS projects (active context, kanban, knowledge base)");
187258
+ project.command("create <slug>").description("Create a new project").option("-n, --name <name>", "Display name").option("-d, --description <text>", "Short description").action(async (slug, options) => {
187259
+ const { createProject: createProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187260
+ const info = createProject2(slug, { name: options.name, description: options.description });
187261
+ process.stdout.write(JSON.stringify(info, null, 2) + `
187262
+ `);
187263
+ });
187264
+ project.command("list").alias("ls").description("List all projects").action(async () => {
187265
+ const { listProjects: listProjects2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187266
+ const list = listProjects2();
187267
+ process.stdout.write(JSON.stringify(list, null, 2) + `
187268
+ `);
187269
+ });
187270
+ project.command("switch <slug>").description("Switch the active project").action(async (slug) => {
187271
+ const { switchProject: switchProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187272
+ const info = switchProject2(slug);
187273
+ process.stdout.write(JSON.stringify(info, null, 2) + `
187274
+ `);
187275
+ });
187276
+ project.command("active").description("Show the active project").action(async () => {
187277
+ const { getActiveProject: getActiveProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187278
+ const info = getActiveProject2();
187279
+ process.stdout.write(JSON.stringify(info ?? null, null, 2) + `
187280
+ `);
187281
+ });
187282
+ project.command("archive <slug>").description("Archive a project (removes it from the active list)").action(async (slug) => {
187283
+ const { archiveProject: archiveProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187284
+ const info = archiveProject2(slug);
187285
+ process.stdout.write(JSON.stringify(info, null, 2) + `
187286
+ `);
187287
+ });
187288
+ project.command("unarchive <slug>").description("Unarchive a project").action(async (slug) => {
187289
+ const { unarchiveProject: unarchiveProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187290
+ const info = unarchiveProject2(slug);
187291
+ process.stdout.write(JSON.stringify(info, null, 2) + `
187292
+ `);
187293
+ });
187294
+ project.command("delete <slug>").description("Permanently delete a project").action(async (slug) => {
187295
+ const { deleteProject: deleteProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187296
+ deleteProject2(slug);
187297
+ process.stdout.write(JSON.stringify({ ok: true, deleted: slug }, null, 2) + `
187298
+ `);
187299
+ });
187300
+ project.command("search <query>").description("Search the active project KB and memory").option("-p, --project <slug>", "Search a specific project instead of the active one").action(async (query, options) => {
187301
+ const { searchProject: searchProject2 } = await Promise.resolve().then(() => (init_project_memory(), exports_project_memory));
187302
+ const hits = await searchProject2(query, { projectSlug: options.project });
187303
+ process.stdout.write(JSON.stringify(hits, null, 2) + `
187304
+ `);
187305
+ });
187306
+ project.command("add-doc <slug> <file>").description("Copy a document into the project KB").action(async (slug, filePath) => {
187307
+ const { addKbDocument: addKbDocument2 } = await Promise.resolve().then(() => (init_project_memory(), exports_project_memory));
187308
+ const { readFileSync: readFileSync64 } = await import("fs");
187309
+ const content = readFileSync64(filePath, "utf-8");
187310
+ const dest = addKbDocument2(slug, filePath, content);
187311
+ process.stdout.write(JSON.stringify({ ok: true, dest }, null, 2) + `
187312
+ `);
187313
+ });
186794
187314
  var gateway2 = program2.command("gateway").description("Gateway configuration \u2014 bot token management");
186795
187315
  var gatewayAdopt = gateway2.command("adopt").description("Adopt a gateway channel (Telegram, Discord, WhatsApp)");
186796
187316
  var gatewayAdoptTelegram = gatewayAdopt.command("telegram").description("Set up the Telegram gateway: prompt for bot token, validate, write .klc-gateway.env").option("-t, --token <value>", "Bot token (non-interactive)").option("-c, --chat <id>", "Restrict to a single chat id").addHelpText("after", `
@@ -186854,6 +187374,19 @@ gateway2.command("status").description("Check gateway status (best-effort, inspe
186854
187374
  }, null, 2) + `
186855
187375
  `);
186856
187376
  });
187377
+ program2.command("self-audit").description("Generate the weekly self-audit report from task ledger and scanner signals").option("-w, --week <week>", "ISO week string, e.g. 2026-W30").option("-j, --json", "Output JSON instead of markdown").option("--tasks-db <path>", "Path to the task ledger SQLite DB").option("--install-cron", "Install the weekly cron job (Sunday 22:00)").action(async (options) => {
187378
+ const { executeSelfAuditCommand: executeSelfAuditCommand2 } = await Promise.resolve().then(() => (init_self_audit_command(), exports_self_audit_command));
187379
+ const result = await executeSelfAuditCommand2(options);
187380
+ if (options.json) {
187381
+ process.stdout.write(JSON.stringify(result, null, 2) + `
187382
+ `);
187383
+ } else if (result.path) {
187384
+ console.log(`Self-audit written to ${result.path}`);
187385
+ } else {
187386
+ console.log(result.message);
187387
+ }
187388
+ process.exit(result.ok ? 0 : 1);
187389
+ });
186857
187390
  program2.command("adopt").description("Re-run the MaTrixOS adoption wizard (providers, channels, profile)").addHelpText("after", `
186858
187391
  Examples:
186859
187392
  $ matrixos adopt # interactive re-adoption (TUI)