@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.
@@ -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",
@@ -90408,11 +90408,22 @@ class TelegramAdapter {
90408
90408
  }
90409
90409
  const text = envelope.content.text ?? "";
90410
90410
  const result = await this.bot.api.sendMessage(chatId, text);
90411
- return String(result.message_id);
90411
+ const messageId = String(result.message_id);
90412
+ if (envelope.metadata?.onMessageId && typeof envelope.metadata.onMessageId === "function") {
90413
+ envelope.metadata.onMessageId(messageId);
90414
+ }
90415
+ return messageId;
90412
90416
  } catch (err) {
90413
90417
  throw new TelegramSendError(`Failed to send Telegram message: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
90414
90418
  }
90415
90419
  }
90420
+ async editMessage(recipientId, messageId, text) {
90421
+ try {
90422
+ await this.bot.api.editMessageText(recipientId, Number(messageId), text);
90423
+ } catch (err) {
90424
+ console.warn(`[telegram] editMessage failed: ${err instanceof Error ? err.message : String(err)}`);
90425
+ }
90426
+ }
90416
90427
  onMessage(handler) {
90417
90428
  this.messageHandler = handler;
90418
90429
  }
@@ -164473,6 +164484,351 @@ var require_picomatch2 = __commonJS((exports2, module2) => {
164473
164484
  module2.exports = picomatch;
164474
164485
  });
164475
164486
 
164487
+ // packages/omo-opencode/src/features/cron/store.ts
164488
+ function createCronStore() {
164489
+ const jobs = new Map;
164490
+ let counter = 0;
164491
+ return {
164492
+ add(input) {
164493
+ counter += 1;
164494
+ const now = new Date().toISOString();
164495
+ const job = {
164496
+ id: `cron-${counter}`,
164497
+ name: input.name,
164498
+ schedule: input.schedule,
164499
+ command: input.command,
164500
+ channel: input.channel,
164501
+ recipient: input.recipient,
164502
+ enabled: input.enabled ?? true,
164503
+ createdAt: now,
164504
+ updatedAt: now
164505
+ };
164506
+ CronJobSchema.parse(job);
164507
+ jobs.set(job.id, job);
164508
+ return job;
164509
+ },
164510
+ get(id) {
164511
+ return jobs.get(id);
164512
+ },
164513
+ list(filter) {
164514
+ const all = Array.from(jobs.values());
164515
+ return all.filter((j) => {
164516
+ if (filter?.enabled !== undefined && j.enabled !== filter.enabled)
164517
+ return false;
164518
+ if (filter?.channel && j.channel !== filter.channel)
164519
+ return false;
164520
+ return true;
164521
+ });
164522
+ },
164523
+ remove(id) {
164524
+ return jobs.delete(id);
164525
+ },
164526
+ size() {
164527
+ return jobs.size;
164528
+ }
164529
+ };
164530
+ }
164531
+ var CronJobSchema;
164532
+ var init_store = __esm(() => {
164533
+ init_zod();
164534
+ CronJobSchema = object({
164535
+ id: string2().min(1),
164536
+ name: string2().min(1).max(100),
164537
+ schedule: string2().min(1).max(100),
164538
+ command: string2().min(1),
164539
+ channel: _enum2(["telegram", "discord", "whatsapp"]).optional(),
164540
+ recipient: string2().optional(),
164541
+ enabled: boolean2().default(true),
164542
+ createdAt: string2(),
164543
+ updatedAt: string2()
164544
+ }).strict();
164545
+ });
164546
+
164547
+ // packages/task-ledger-core/src/schema.ts
164548
+ var TaskSourceSchema, TaskStatusSchema, TaskPrioritySchema, TaskSchema, TaskInsertSchema, TaskPatchSchema, TaskFilterSchema;
164549
+ var init_schema2 = __esm(() => {
164550
+ init_zod();
164551
+ TaskSourceSchema = _enum2(["webhook", "cron", "user", "kanban"]);
164552
+ TaskStatusSchema = _enum2([
164553
+ "pending",
164554
+ "running",
164555
+ "done",
164556
+ "failed",
164557
+ "cancelled"
164558
+ ]);
164559
+ TaskPrioritySchema = _enum2(["high", "medium", "low"]);
164560
+ TaskSchema = object({
164561
+ id: string2().min(1),
164562
+ source: TaskSourceSchema,
164563
+ context: string2().nullable(),
164564
+ status: TaskStatusSchema,
164565
+ priority: TaskPrioritySchema.nullable(),
164566
+ payload: string2(),
164567
+ agent_assigned: string2().nullable(),
164568
+ session_id: string2().nullable(),
164569
+ result: string2().nullable(),
164570
+ cost_tokens: number2().int().nonnegative().default(0),
164571
+ cost_usd: number2().nonnegative().default(0),
164572
+ created_at: number2().int(),
164573
+ started_at: number2().int().nullable(),
164574
+ completed_at: number2().int().nullable()
164575
+ }).strict();
164576
+ TaskInsertSchema = object({
164577
+ id: string2().min(1).optional(),
164578
+ source: TaskSourceSchema,
164579
+ context: string2().nullable().optional(),
164580
+ status: TaskStatusSchema.optional(),
164581
+ priority: TaskPrioritySchema.nullable().optional(),
164582
+ payload: string2(),
164583
+ agent_assigned: string2().nullable().optional(),
164584
+ session_id: string2().nullable().optional(),
164585
+ cost_tokens: number2().int().nonnegative().optional(),
164586
+ cost_usd: number2().nonnegative().optional()
164587
+ }).strict();
164588
+ TaskPatchSchema = object({
164589
+ status: TaskStatusSchema.optional(),
164590
+ priority: TaskPrioritySchema.nullable().optional(),
164591
+ agent_assigned: string2().nullable().optional(),
164592
+ session_id: string2().nullable().optional(),
164593
+ result: string2().nullable().optional(),
164594
+ cost_tokens: number2().int().nonnegative().optional(),
164595
+ cost_usd: number2().nonnegative().optional(),
164596
+ started_at: number2().int().nullable().optional(),
164597
+ completed_at: number2().int().nullable().optional()
164598
+ }).strict();
164599
+ TaskFilterSchema = object({
164600
+ source: TaskSourceSchema.optional(),
164601
+ context: string2().optional(),
164602
+ status: TaskStatusSchema.optional(),
164603
+ agent_assigned: string2().optional(),
164604
+ session_id: string2().optional(),
164605
+ priority: TaskPrioritySchema.optional()
164606
+ }).strict();
164607
+ });
164608
+
164609
+ // packages/task-ledger-core/src/ledger.ts
164610
+ import { randomUUID as randomUUID2 } from "crypto";
164611
+ function rowToTask(row) {
164612
+ return {
164613
+ id: row.id,
164614
+ source: row.source,
164615
+ context: row.context,
164616
+ status: row.status,
164617
+ priority: row.priority,
164618
+ payload: row.payload,
164619
+ agent_assigned: row.agent_assigned,
164620
+ session_id: row.session_id,
164621
+ result: row.result,
164622
+ cost_tokens: row.cost_tokens,
164623
+ cost_usd: row.cost_usd,
164624
+ created_at: row.created_at,
164625
+ started_at: row.started_at,
164626
+ completed_at: row.completed_at
164627
+ };
164628
+ }
164629
+ function createTaskLedger(db) {
164630
+ db.exec(CREATE_TABLE_SQL);
164631
+ db.exec(CREATE_INDEX_STATUS);
164632
+ db.exec(CREATE_INDEX_CONTEXT);
164633
+ db.exec(CREATE_INDEX_SOURCE);
164634
+ return {
164635
+ insert(input) {
164636
+ const now = Date.now();
164637
+ const task2 = TaskSchema.parse({
164638
+ id: input.id ?? randomUUID2(),
164639
+ source: input.source,
164640
+ context: input.context ?? null,
164641
+ status: input.status ?? "pending",
164642
+ priority: input.priority ?? null,
164643
+ payload: input.payload,
164644
+ agent_assigned: input.agent_assigned ?? null,
164645
+ session_id: input.session_id ?? null,
164646
+ result: null,
164647
+ cost_tokens: input.cost_tokens ?? 0,
164648
+ cost_usd: input.cost_usd ?? 0,
164649
+ created_at: now,
164650
+ started_at: null,
164651
+ completed_at: null
164652
+ });
164653
+ db.exec(INSERT_SQL, {
164654
+ $id: task2.id,
164655
+ $source: task2.source,
164656
+ $context: task2.context,
164657
+ $status: task2.status,
164658
+ $priority: task2.priority,
164659
+ $payload: task2.payload,
164660
+ $agent_assigned: task2.agent_assigned,
164661
+ $session_id: task2.session_id,
164662
+ $result: task2.result,
164663
+ $cost_tokens: task2.cost_tokens,
164664
+ $cost_usd: task2.cost_usd,
164665
+ $created_at: task2.created_at,
164666
+ $started_at: task2.started_at,
164667
+ $completed_at: task2.completed_at
164668
+ });
164669
+ return task2;
164670
+ },
164671
+ get(id) {
164672
+ const rows = db.query(SELECT_BY_ID_SQL, { $id: id });
164673
+ if (rows.length === 0)
164674
+ return null;
164675
+ return rowToTask(rows[0]);
164676
+ },
164677
+ list(filter) {
164678
+ const conditions = [];
164679
+ const params = {};
164680
+ if (filter?.source) {
164681
+ conditions.push("source = $source");
164682
+ params.$source = filter.source;
164683
+ }
164684
+ if (filter?.context) {
164685
+ conditions.push("context = $context");
164686
+ params.$context = filter.context;
164687
+ }
164688
+ if (filter?.status) {
164689
+ conditions.push("status = $status");
164690
+ params.$status = filter.status;
164691
+ }
164692
+ if (filter?.agent_assigned) {
164693
+ conditions.push("agent_assigned = $agent_assigned");
164694
+ params.$agent_assigned = filter.agent_assigned;
164695
+ }
164696
+ if (filter?.session_id) {
164697
+ conditions.push("session_id = $session_id");
164698
+ params.$session_id = filter.session_id;
164699
+ }
164700
+ if (filter?.priority) {
164701
+ conditions.push("priority = $priority");
164702
+ params.$priority = filter.priority;
164703
+ }
164704
+ const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
164705
+ const sql = `SELECT * FROM tasks${where} ORDER BY created_at DESC`;
164706
+ const rows = db.query(sql, params);
164707
+ return rows.map(rowToTask);
164708
+ },
164709
+ update(id, patch) {
164710
+ const existing = db.query(SELECT_BY_ID_SQL, { $id: id });
164711
+ if (existing.length === 0)
164712
+ return null;
164713
+ const params = { $id: id };
164714
+ if (patch.status !== undefined)
164715
+ params.$status = patch.status;
164716
+ if (patch.priority !== undefined)
164717
+ params.$priority = patch.priority;
164718
+ if (patch.agent_assigned !== undefined)
164719
+ params.$agent_assigned = patch.agent_assigned;
164720
+ if (patch.session_id !== undefined)
164721
+ params.$session_id = patch.session_id;
164722
+ if (patch.result !== undefined)
164723
+ params.$result = patch.result;
164724
+ if (patch.cost_tokens !== undefined)
164725
+ params.$cost_tokens = patch.cost_tokens;
164726
+ if (patch.cost_usd !== undefined)
164727
+ params.$cost_usd = patch.cost_usd;
164728
+ if (patch.started_at !== undefined)
164729
+ params.$started_at = patch.started_at;
164730
+ if (patch.completed_at !== undefined)
164731
+ params.$completed_at = patch.completed_at;
164732
+ db.exec(UPDATE_SQL, params);
164733
+ return this.get(id);
164734
+ },
164735
+ remove(id) {
164736
+ const before = db.query(SELECT_BY_ID_SQL, { $id: id });
164737
+ if (before.length === 0)
164738
+ return false;
164739
+ db.exec(DELETE_BY_ID_SQL, { $id: id });
164740
+ return true;
164741
+ },
164742
+ listPending() {
164743
+ const rows = db.query(`SELECT * FROM tasks WHERE status = 'pending' ORDER BY created_at ASC`);
164744
+ return rows.map(rowToTask);
164745
+ },
164746
+ listFailed() {
164747
+ const rows = db.query(`SELECT * FROM tasks WHERE status = 'failed' ORDER BY created_at ASC`);
164748
+ return rows.map(rowToTask);
164749
+ },
164750
+ listByContext(context) {
164751
+ const rows = db.query(`SELECT * FROM tasks WHERE context = $context ORDER BY created_at DESC`, { $context: context });
164752
+ return rows.map(rowToTask);
164753
+ },
164754
+ close() {
164755
+ db.close();
164756
+ }
164757
+ };
164758
+ }
164759
+ var CREATE_TABLE_SQL = `
164760
+ CREATE TABLE IF NOT EXISTS tasks (
164761
+ id TEXT PRIMARY KEY,
164762
+ source TEXT NOT NULL,
164763
+ context TEXT,
164764
+ status TEXT NOT NULL,
164765
+ priority TEXT,
164766
+ payload TEXT NOT NULL,
164767
+ agent_assigned TEXT,
164768
+ session_id TEXT,
164769
+ result TEXT,
164770
+ cost_tokens INTEGER DEFAULT 0,
164771
+ cost_usd REAL DEFAULT 0,
164772
+ created_at INTEGER NOT NULL,
164773
+ started_at INTEGER,
164774
+ completed_at INTEGER
164775
+ )
164776
+ `, 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 = `
164777
+ INSERT INTO tasks (id, source, context, status, priority, payload, agent_assigned, session_id, result, cost_tokens, cost_usd, created_at, started_at, completed_at)
164778
+ VALUES ($id, $source, $context, $status, $priority, $payload, $agent_assigned, $session_id, $result, $cost_tokens, $cost_usd, $created_at, $started_at, $completed_at)
164779
+ `, SELECT_BY_ID_SQL = `SELECT * FROM tasks WHERE id = $id`, DELETE_BY_ID_SQL = `DELETE FROM tasks WHERE id = $id`, UPDATE_SQL = `
164780
+ UPDATE tasks SET
164781
+ status = COALESCE($status, status),
164782
+ priority = COALESCE($priority, priority),
164783
+ agent_assigned = COALESCE($agent_assigned, agent_assigned),
164784
+ session_id = COALESCE($session_id, session_id),
164785
+ result = COALESCE($result, result),
164786
+ cost_tokens = COALESCE($cost_tokens, cost_tokens),
164787
+ cost_usd = COALESCE($cost_usd, cost_usd),
164788
+ started_at = COALESCE($started_at, started_at),
164789
+ completed_at = COALESCE($completed_at, completed_at)
164790
+ WHERE id = $id
164791
+ `;
164792
+ var init_ledger = __esm(() => {
164793
+ init_schema2();
164794
+ });
164795
+
164796
+ // packages/task-ledger-core/src/sqlite.ts
164797
+ import { Database as Database2 } from "bun:sqlite";
164798
+ function createSqliteDatabase(dbPath) {
164799
+ const db = new Database2(dbPath);
164800
+ db.exec("PRAGMA journal_mode = WAL");
164801
+ db.exec("PRAGMA foreign_keys = ON");
164802
+ return {
164803
+ exec(sql, ...params) {
164804
+ if (params.length === 0) {
164805
+ db.run(sql);
164806
+ } else {
164807
+ const named = params[0];
164808
+ db.run(sql, named);
164809
+ }
164810
+ },
164811
+ query(sql, ...params) {
164812
+ if (params.length === 0) {
164813
+ return db.prepare(sql).all();
164814
+ }
164815
+ const named = params[0];
164816
+ return db.prepare(sql).all(named);
164817
+ },
164818
+ close() {
164819
+ db.close();
164820
+ }
164821
+ };
164822
+ }
164823
+ var init_sqlite = () => {};
164824
+
164825
+ // packages/task-ledger-core/src/index.ts
164826
+ var init_src6 = __esm(() => {
164827
+ init_schema2();
164828
+ init_ledger();
164829
+ init_sqlite();
164830
+ });
164831
+
164476
164832
  // packages/omo-opencode/src/cli/generate.ts
164477
164833
  var exports_generate = {};
164478
164834
  __export(exports_generate, {
@@ -165075,6 +165431,264 @@ var init_export = __esm(() => {
165075
165431
  };
165076
165432
  });
165077
165433
 
165434
+ // packages/omo-opencode/src/project/project-context.ts
165435
+ var exports_project_context = {};
165436
+ __export(exports_project_context, {
165437
+ unarchiveProject: () => unarchiveProject,
165438
+ switchProject: () => switchProject,
165439
+ saveState: () => saveState,
165440
+ saveProjectMeta: () => saveProjectMeta,
165441
+ loadState: () => loadState,
165442
+ loadProjectMeta: () => loadProjectMeta,
165443
+ listProjects: () => listProjects,
165444
+ initProjectFiles: () => initProjectFiles,
165445
+ getStatePath: () => getStatePath,
165446
+ getProjectsDir: () => getProjectsDir,
165447
+ getProjectDir: () => getProjectDir,
165448
+ getMatrixOsDir: () => getMatrixOsDir,
165449
+ getActiveProject: () => getActiveProject,
165450
+ deleteProject: () => deleteProject,
165451
+ createProject: () => createProject,
165452
+ archiveProject: () => archiveProject
165453
+ });
165454
+ import { existsSync as existsSync75, mkdirSync as mkdirSync27, readFileSync as readFileSync60, writeFileSync as writeFileSync27, rmSync as rmSync8 } from "fs";
165455
+ import { join as join81 } from "path";
165456
+ function getMatrixOsDir(cwd = process.cwd()) {
165457
+ return join81(cwd, ".matrixos");
165458
+ }
165459
+ function getProjectsDir(cwd) {
165460
+ return join81(getMatrixOsDir(cwd), "projects");
165461
+ }
165462
+ function getProjectDir(slug, cwd) {
165463
+ return join81(getProjectsDir(cwd), slug);
165464
+ }
165465
+ function getStatePath(cwd) {
165466
+ return join81(getMatrixOsDir(cwd), "state.json");
165467
+ }
165468
+ function loadState(cwd) {
165469
+ const path29 = getStatePath(cwd);
165470
+ if (!existsSync75(path29))
165471
+ return {};
165472
+ try {
165473
+ return JSON.parse(readFileSync60(path29, "utf-8"));
165474
+ } catch {
165475
+ return {};
165476
+ }
165477
+ }
165478
+ function saveState(state2, cwd) {
165479
+ const path29 = getStatePath(cwd);
165480
+ mkdirSync27(getMatrixOsDir(cwd), { recursive: true });
165481
+ writeFileSync27(path29, JSON.stringify(state2, null, 2) + `
165482
+ `);
165483
+ }
165484
+ function loadProjectMeta(slug, cwd) {
165485
+ const path29 = join81(getProjectDir(slug, cwd), "meta.json");
165486
+ if (!existsSync75(path29))
165487
+ return null;
165488
+ try {
165489
+ return JSON.parse(readFileSync60(path29, "utf-8"));
165490
+ } catch {
165491
+ return null;
165492
+ }
165493
+ }
165494
+ function saveProjectMeta(slug, meta3, cwd) {
165495
+ const dir = getProjectDir(slug, cwd);
165496
+ mkdirSync27(dir, { recursive: true });
165497
+ const path29 = join81(dir, "meta.json");
165498
+ writeFileSync27(path29, JSON.stringify(meta3, null, 2) + `
165499
+ `);
165500
+ }
165501
+ function initProjectFiles(slug, cwd) {
165502
+ const dir = getProjectDir(slug, cwd);
165503
+ mkdirSync27(join81(dir, "kb"), { recursive: true });
165504
+ const kanbanPath = join81(dir, "kanban.json");
165505
+ if (!existsSync75(kanbanPath)) {
165506
+ writeFileSync27(kanbanPath, JSON.stringify({ columns: ["todo", "in-progress", "review", "done"], tasks: [] }, null, 2) + `
165507
+ `);
165508
+ }
165509
+ }
165510
+ function createProject(slug, options = {}) {
165511
+ if (!/^[a-z0-9_-]+$/.test(slug)) {
165512
+ throw new Error(`Invalid project slug "${slug}": only lowercase letters, numbers, - and _ are allowed.`);
165513
+ }
165514
+ const dir = getProjectDir(slug, options.cwd);
165515
+ if (existsSync75(dir)) {
165516
+ throw new Error(`Project "${slug}" already exists.`);
165517
+ }
165518
+ const now = new Date().toISOString();
165519
+ const meta3 = {
165520
+ slug,
165521
+ name: options.name || slug,
165522
+ description: options.description,
165523
+ createdAt: now
165524
+ };
165525
+ saveProjectMeta(slug, meta3, options.cwd);
165526
+ initProjectFiles(slug, options.cwd);
165527
+ const state2 = loadState(options.cwd);
165528
+ if (!state2.activeProject) {
165529
+ saveState({ ...state2, activeProject: slug }, options.cwd);
165530
+ }
165531
+ return { slug, meta: meta3, active: state2.activeProject === slug || !state2.activeProject };
165532
+ }
165533
+ function listProjects(cwd) {
165534
+ const state2 = loadState(cwd);
165535
+ const root = getProjectsDir(cwd);
165536
+ if (!existsSync75(root))
165537
+ return [];
165538
+ const fs24 = __require("fs");
165539
+ const items = [];
165540
+ for (const slug of fs24.readdirSync(root, { withFileTypes: true })) {
165541
+ if (!slug.isDirectory())
165542
+ continue;
165543
+ const meta3 = loadProjectMeta(slug.name, cwd);
165544
+ if (!meta3)
165545
+ continue;
165546
+ items.push({ slug: slug.name, meta: meta3, active: state2.activeProject === slug.name });
165547
+ }
165548
+ return items.sort((a2, b2) => a2.slug.localeCompare(b2.slug));
165549
+ }
165550
+ function switchProject(slug, cwd) {
165551
+ const meta3 = loadProjectMeta(slug, cwd);
165552
+ if (!meta3)
165553
+ throw new Error(`Project "${slug}" does not exist.`);
165554
+ if (meta3.archived)
165555
+ throw new Error(`Project "${slug}" is archived. Unarchive it before switching.`);
165556
+ const state2 = loadState(cwd);
165557
+ saveState({ ...state2, activeProject: slug }, cwd);
165558
+ return { slug, meta: meta3, active: true };
165559
+ }
165560
+ function archiveProject(slug, cwd) {
165561
+ const meta3 = loadProjectMeta(slug, cwd);
165562
+ if (!meta3)
165563
+ throw new Error(`Project "${slug}" does not exist.`);
165564
+ const now = new Date().toISOString();
165565
+ const next = { ...meta3, archived: true, archivedAt: now };
165566
+ saveProjectMeta(slug, next, cwd);
165567
+ const state2 = loadState(cwd);
165568
+ if (state2.activeProject === slug) {
165569
+ saveState({ ...state2, activeProject: undefined }, cwd);
165570
+ }
165571
+ return { slug, meta: next, active: false };
165572
+ }
165573
+ function unarchiveProject(slug, cwd) {
165574
+ const meta3 = loadProjectMeta(slug, cwd);
165575
+ if (!meta3)
165576
+ throw new Error(`Project "${slug}" does not exist.`);
165577
+ const { archived: _a3, archivedAt: _b, ...rest } = meta3;
165578
+ const next = rest;
165579
+ saveProjectMeta(slug, next, cwd);
165580
+ return { slug, meta: next, active: loadState(cwd).activeProject === slug };
165581
+ }
165582
+ function deleteProject(slug, cwd) {
165583
+ const dir = getProjectDir(slug, cwd);
165584
+ if (!existsSync75(dir))
165585
+ throw new Error(`Project "${slug}" does not exist.`);
165586
+ rmSync8(dir, { recursive: true, force: true });
165587
+ const state2 = loadState(cwd);
165588
+ if (state2.activeProject === slug) {
165589
+ saveState({ ...state2, activeProject: undefined }, cwd);
165590
+ }
165591
+ }
165592
+ function getActiveProject(cwd) {
165593
+ const state2 = loadState(cwd);
165594
+ if (!state2.activeProject)
165595
+ return null;
165596
+ const meta3 = loadProjectMeta(state2.activeProject, cwd);
165597
+ if (!meta3) {
165598
+ saveState({ ...state2, activeProject: undefined }, cwd);
165599
+ return null;
165600
+ }
165601
+ return { slug: state2.activeProject, meta: meta3, active: true };
165602
+ }
165603
+ var init_project_context = () => {};
165604
+
165605
+ // packages/omo-opencode/src/project/project-memory.ts
165606
+ var exports_project_memory = {};
165607
+ __export(exports_project_memory, {
165608
+ tagWithProject: () => tagWithProject,
165609
+ searchProject: () => searchProject,
165610
+ searchKb: () => searchKb,
165611
+ listKbDocuments: () => listKbDocuments,
165612
+ isProjectEpisode: () => isProjectEpisode,
165613
+ addKbDocument: () => addKbDocument
165614
+ });
165615
+ import { existsSync as existsSync76, mkdirSync as mkdirSync28, readFileSync as readFileSync61, readdirSync as readdirSync16, writeFileSync as writeFileSync28 } from "fs";
165616
+ import { join as join82 } from "path";
165617
+ function tagWithProject(metadata = {}, projectSlug, cwd) {
165618
+ const active = projectSlug ?? getActiveProject(cwd)?.slug;
165619
+ if (!active)
165620
+ return metadata;
165621
+ return { ...metadata, project: active };
165622
+ }
165623
+ function isProjectEpisode(ep, projectSlug, cwd) {
165624
+ const target = projectSlug ?? getActiveProject(cwd)?.slug;
165625
+ if (!target)
165626
+ return true;
165627
+ return ep.metadata?.project === target;
165628
+ }
165629
+ function listKbDocuments(projectSlug, cwd) {
165630
+ const kbDir = join82(getProjectDir(projectSlug, cwd), "kb");
165631
+ if (!existsSync76(kbDir))
165632
+ return [];
165633
+ const docs = [];
165634
+ for (const entry of readdirSync16(kbDir, { withFileTypes: true })) {
165635
+ if (!entry.isFile())
165636
+ continue;
165637
+ const path29 = join82(kbDir, entry.name);
165638
+ try {
165639
+ docs.push({ path: path29, content: readFileSync61(path29, "utf-8") });
165640
+ } catch {}
165641
+ }
165642
+ return docs;
165643
+ }
165644
+ function searchKb(projectSlug, query, cwd) {
165645
+ const needle = query.toLowerCase();
165646
+ const docs = listKbDocuments(projectSlug, cwd);
165647
+ const results = [];
165648
+ for (const doc2 of docs) {
165649
+ const content = doc2.content.toLowerCase();
165650
+ const matches = content.split(needle).length - 1;
165651
+ if (matches > 0) {
165652
+ results.push({
165653
+ project: projectSlug,
165654
+ source: "kb",
165655
+ path: doc2.path,
165656
+ content: doc2.content.slice(0, 240),
165657
+ score: matches
165658
+ });
165659
+ }
165660
+ }
165661
+ return results.sort((a2, b2) => b2.score - a2.score);
165662
+ }
165663
+ async function searchProject(query, options = {}) {
165664
+ const projectSlug = options.projectSlug ?? getActiveProject(options.cwd)?.slug;
165665
+ if (!projectSlug)
165666
+ return [];
165667
+ const kbHits = searchKb(projectSlug, query, options.cwd);
165668
+ let memoryHits = [];
165669
+ if (options.memoryStore) {
165670
+ const episodes = options.memoryStore.searchEpisodes?.({ textContains: query, limit: 20 }) ?? [];
165671
+ memoryHits = episodes.filter((ep) => ep.metadata?.project === projectSlug).map((ep) => ({
165672
+ project: projectSlug,
165673
+ source: "episode",
165674
+ summary: ep.summary,
165675
+ score: 1
165676
+ }));
165677
+ }
165678
+ return [...kbHits, ...memoryHits].sort((a2, b2) => b2.score - a2.score);
165679
+ }
165680
+ function addKbDocument(projectSlug, filename, content, cwd) {
165681
+ const kbDir = join82(getProjectDir(projectSlug, cwd), "kb");
165682
+ mkdirSync28(kbDir, { recursive: true });
165683
+ const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_");
165684
+ const path29 = join82(kbDir, safeName);
165685
+ writeFileSync28(path29, content, "utf-8");
165686
+ return path29;
165687
+ }
165688
+ var init_project_memory = __esm(() => {
165689
+ init_project_context();
165690
+ });
165691
+
165078
165692
  // packages/omo-opencode/src/cli/adopt.ts
165079
165693
  var exports_adopt = {};
165080
165694
  __export(exports_adopt, {
@@ -165402,12 +166016,12 @@ __export(exports_gateway_start, {
165402
166016
  buildTelegramConfig: () => buildTelegramConfig,
165403
166017
  buildGatewayConfig: () => buildGatewayConfig
165404
166018
  });
165405
- import { readFileSync as readFileSync60, existsSync as existsSync75 } from "fs";
166019
+ import { readFileSync as readFileSync62, existsSync as existsSync77 } from "fs";
165406
166020
  import { resolve as resolve19 } from "path";
165407
166021
  function loadGatewayEnv(path29 = ENV_PATH) {
165408
- if (!existsSync75(path29))
166022
+ if (!existsSync77(path29))
165409
166023
  return {};
165410
- const text = readFileSync60(path29, "utf8");
166024
+ const text = readFileSync62(path29, "utf8");
165411
166025
  const out = {};
165412
166026
  for (const raw of text.split(/\r?\n/)) {
165413
166027
  const line = raw.trim();
@@ -165527,6 +166141,188 @@ var init_gateway_start = __esm(() => {
165527
166141
  ENV_PATH = resolve19(process.cwd(), ".klc-gateway.env");
165528
166142
  });
165529
166143
 
166144
+ // packages/omo-opencode/src/audit/self-audit.ts
166145
+ import { existsSync as existsSync78, mkdirSync as mkdirSync29, readdirSync as readdirSync17, readFileSync as readFileSync63, writeFileSync as writeFileSync29 } from "fs";
166146
+ import { join as join83 } from "path";
166147
+ function getAuditDir(cwd = process.cwd()) {
166148
+ return join83(cwd, ".matrixos", "audits");
166149
+ }
166150
+ function getWeekString(date5 = new Date) {
166151
+ const d = new Date(Date.UTC(date5.getFullYear(), date5.getMonth(), date5.getDate()));
166152
+ const dayNum = d.getUTCDay() || 7;
166153
+ d.setUTCDate(d.getUTCDate() + 4 - dayNum);
166154
+ const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
166155
+ const weekNo = Math.ceil(((+d - +yearStart) / 86400000 + 1) / 7);
166156
+ return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, "0")}`;
166157
+ }
166158
+ function parseWeekDateRange(weekStr) {
166159
+ const [year, week] = weekStr.split("-W").map(Number);
166160
+ const jan4 = new Date(Date.UTC(year, 0, 4));
166161
+ const monday = new Date(Date.UTC(year, 0, 4 - ((jan4.getUTCDay() || 7) - 1) + (week - 1) * 7));
166162
+ const sunday = new Date(+monday + 6 * 86400000);
166163
+ return { from: monday.toISOString().slice(0, 10), to: sunday.toISOString().slice(0, 10) };
166164
+ }
166165
+ function generateAuditReport(tasks, signals, weekStr) {
166166
+ const week = weekStr ?? getWeekString();
166167
+ const period = parseWeekDateRange(week);
166168
+ const summary = {
166169
+ total: tasks.length,
166170
+ done: tasks.filter((t2) => t2.status === "done").length,
166171
+ failed: tasks.filter((t2) => t2.status === "failed").length,
166172
+ inProgress: tasks.filter((t2) => t2.status === "in-progress").length,
166173
+ blocked: tasks.filter((t2) => t2.status === "blocked").length
166174
+ };
166175
+ const byProject = {};
166176
+ for (const t2 of tasks) {
166177
+ const p2 = t2.project || "default";
166178
+ byProject[p2] = byProject[p2] || { done: 0, failed: 0, blocked: 0 };
166179
+ if (t2.status === "done")
166180
+ byProject[p2].done += 1;
166181
+ if (t2.status === "failed")
166182
+ byProject[p2].failed += 1;
166183
+ if (t2.status === "blocked")
166184
+ byProject[p2].blocked += 1;
166185
+ }
166186
+ const errorCounts = new Map;
166187
+ for (const s of signals) {
166188
+ if (s.type !== "error")
166189
+ continue;
166190
+ const key = `${s.project || "global"}: ${s.message}`;
166191
+ errorCounts.set(key, (errorCounts.get(key) || 0) + (s.count || 1));
166192
+ }
166193
+ const topErrors = [...errorCounts.entries()].sort((a2, b2) => b2[1] - a2[1]).slice(0, 5).map(([message, count]) => ({ type: "error", message, count }));
166194
+ const recommendations = [];
166195
+ if (summary.failed > 0) {
166196
+ recommendations.push(`Analyser ${summary.failed} t\xE2che(s) en \xE9chec et cr\xE9er une skill/r\xE8gle par pattern r\xE9current.`);
166197
+ }
166198
+ if (summary.blocked > 0) {
166199
+ recommendations.push(`D\xE9bloquer ${summary.blocked} t\xE2che(s) bloqu\xE9es avant le prochain sprint.`);
166200
+ }
166201
+ if (topErrors.length > 0) {
166202
+ recommendations.push(`Top erreur : "${topErrors[0].message}" \u2014 prioriser un guard/automated fix.`);
166203
+ }
166204
+ if (recommendations.length === 0) {
166205
+ recommendations.push("Semaine propre. Poursuivre la veille et la documentation des d\xE9cisions.");
166206
+ }
166207
+ return { week, period, summary, byProject, topErrors, recommendations };
166208
+ }
166209
+ function formatAuditReport(report) {
166210
+ const lines = [
166211
+ `# Auto-audit hebdomadaire \u2014 ${report.week}`,
166212
+ "",
166213
+ `**P\xE9riode** : ${report.period.from} \u2192 ${report.period.to}`,
166214
+ "",
166215
+ "## R\xE9sum\xE9",
166216
+ "",
166217
+ `| M\xE9trique | Valeur |`,
166218
+ `|----------|--------|`,
166219
+ `| Total | ${report.summary.total} |`,
166220
+ `| Termin\xE9es | ${report.summary.done} |`,
166221
+ `| \xC9chou\xE9es | ${report.summary.failed} |`,
166222
+ `| En cours | ${report.summary.inProgress} |`,
166223
+ `| Bloqu\xE9es | ${report.summary.blocked} |`,
166224
+ "",
166225
+ "## Par projet",
166226
+ "",
166227
+ `| Projet | Termin\xE9es | \xC9chou\xE9es | Bloqu\xE9es |`,
166228
+ `|--------|-----------|----------|----------|`
166229
+ ];
166230
+ for (const [project, stats] of Object.entries(report.byProject).sort()) {
166231
+ lines.push(`| ${project} | ${stats.done} | ${stats.failed} | ${stats.blocked} |`);
166232
+ }
166233
+ lines.push("");
166234
+ lines.push("## Top erreurs");
166235
+ lines.push("");
166236
+ if (report.topErrors.length === 0) {
166237
+ lines.push("Aucune erreur significative cette semaine.");
166238
+ } else {
166239
+ for (const err of report.topErrors) {
166240
+ lines.push(`- **${err.count}\xD7** ${err.message}`);
166241
+ }
166242
+ }
166243
+ lines.push("");
166244
+ lines.push("## Recommandations");
166245
+ lines.push("");
166246
+ for (const rec of report.recommendations) {
166247
+ lines.push(`- ${rec}`);
166248
+ }
166249
+ lines.push("");
166250
+ return lines.join(`
166251
+ `);
166252
+ }
166253
+ function writeAuditReport(report, cwd) {
166254
+ const dir = getAuditDir(cwd);
166255
+ mkdirSync29(dir, { recursive: true });
166256
+ const path29 = join83(dir, `${report.week}.md`);
166257
+ writeFileSync29(path29, formatAuditReport(report), "utf-8");
166258
+ return path29;
166259
+ }
166260
+ var init_self_audit = () => {};
166261
+
166262
+ // packages/omo-opencode/src/cli/self-audit-command.ts
166263
+ var exports_self_audit_command = {};
166264
+ __export(exports_self_audit_command, {
166265
+ normalizeStatus: () => normalizeStatus,
166266
+ executeSelfAuditCommand: () => executeSelfAuditCommand
166267
+ });
166268
+ async function executeSelfAuditCommand(options = {}) {
166269
+ if (options.installCron) {
166270
+ const store4 = createCronStore();
166271
+ const job = store4.add({
166272
+ name: "Weekly self-audit",
166273
+ schedule: "0 22 * * 0",
166274
+ command: "matrixos self-audit",
166275
+ channel: undefined,
166276
+ recipient: undefined,
166277
+ enabled: true
166278
+ });
166279
+ return { ok: true, message: `Weekly self-audit cron job installed: ${job.id}` };
166280
+ }
166281
+ const dbPath = options.tasksDb ?? process.env.TASK_LEDGER_DB ?? "/root/.matrixos/tasks.db";
166282
+ let tasks = [];
166283
+ let signals = [];
166284
+ try {
166285
+ const rawLedger = createTaskLedger(createSqliteDatabase(dbPath));
166286
+ const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
166287
+ const allTasks = rawLedger.list?.() ?? [];
166288
+ tasks = allTasks.filter((t2) => !t2.created_at || String(t2.created_at) >= since);
166289
+ } catch (err) {
166290
+ const detail = err instanceof Error ? err.message : String(err);
166291
+ return {
166292
+ ok: false,
166293
+ message: `Could not read task ledger at ${dbPath}: ${detail}`
166294
+ };
166295
+ }
166296
+ const report = generateAuditReport(tasks.map((t2) => ({
166297
+ id: String(t2.id ?? t2.task_id ?? "unknown"),
166298
+ title: String(t2.title ?? t2.summary ?? "untitled"),
166299
+ status: normalizeStatus(t2.status),
166300
+ project: t2.project || t2.context?.project || undefined,
166301
+ errorCount: t2.error_count || t2.errorCount || 0
166302
+ })), signals, options.week);
166303
+ const path29 = writeAuditReport(report);
166304
+ return { ok: true, path: path29, message: `Self-audit written to ${path29}`, report };
166305
+ }
166306
+ function normalizeStatus(status2) {
166307
+ if (!status2)
166308
+ return "in-progress";
166309
+ const s = String(status2).toLowerCase();
166310
+ if (["done", "completed", "finished", "closed"].includes(s))
166311
+ return "done";
166312
+ if (["fail", "failed", "error"].includes(s))
166313
+ return "failed";
166314
+ if (["blocked", "stuck"].includes(s))
166315
+ return "blocked";
166316
+ if (["in-progress", "in_progress", "wip", "active"].includes(s))
166317
+ return "in-progress";
166318
+ return s;
166319
+ }
166320
+ var init_self_audit_command = __esm(() => {
166321
+ init_src6();
166322
+ init_store();
166323
+ init_self_audit();
166324
+ });
166325
+
165530
166326
  // packages/omo-opencode/src/cli/rgpd-command.ts
165531
166327
  var exports_rgpd_command = {};
165532
166328
  __export(exports_rgpd_command, {
@@ -180251,64 +181047,8 @@ async function boulder(options) {
180251
181047
  `);
180252
181048
  return 0;
180253
181049
  }
180254
- // packages/omo-opencode/src/features/cron/store.ts
180255
- init_zod();
180256
- var CronJobSchema = object({
180257
- id: string2().min(1),
180258
- name: string2().min(1).max(100),
180259
- schedule: string2().min(1).max(100),
180260
- command: string2().min(1),
180261
- channel: _enum2(["telegram", "discord", "whatsapp"]).optional(),
180262
- recipient: string2().optional(),
180263
- enabled: boolean2().default(true),
180264
- createdAt: string2(),
180265
- updatedAt: string2()
180266
- }).strict();
180267
- function createCronStore() {
180268
- const jobs = new Map;
180269
- let counter = 0;
180270
- return {
180271
- add(input) {
180272
- counter += 1;
180273
- const now = new Date().toISOString();
180274
- const job = {
180275
- id: `cron-${counter}`,
180276
- name: input.name,
180277
- schedule: input.schedule,
180278
- command: input.command,
180279
- channel: input.channel,
180280
- recipient: input.recipient,
180281
- enabled: input.enabled ?? true,
180282
- createdAt: now,
180283
- updatedAt: now
180284
- };
180285
- CronJobSchema.parse(job);
180286
- jobs.set(job.id, job);
180287
- return job;
180288
- },
180289
- get(id) {
180290
- return jobs.get(id);
180291
- },
180292
- list(filter) {
180293
- const all = Array.from(jobs.values());
180294
- return all.filter((j) => {
180295
- if (filter?.enabled !== undefined && j.enabled !== filter.enabled)
180296
- return false;
180297
- if (filter?.channel && j.channel !== filter.channel)
180298
- return false;
180299
- return true;
180300
- });
180301
- },
180302
- remove(id) {
180303
- return jobs.delete(id);
180304
- },
180305
- size() {
180306
- return jobs.size;
180307
- }
180308
- };
180309
- }
180310
-
180311
181050
  // packages/omo-opencode/src/cli/cron.ts
181051
+ init_store();
180312
181052
  var store2 = createCronStore();
180313
181053
  function cronAdd(options) {
180314
181054
  const job = store2.add({
@@ -180461,289 +181201,12 @@ function createDailyBrief(opts) {
180461
181201
  };
180462
181202
  }
180463
181203
 
180464
- // packages/task-ledger-core/src/schema.ts
180465
- init_zod();
180466
- var TaskSourceSchema = _enum2(["webhook", "cron", "user", "kanban"]);
180467
- var TaskStatusSchema = _enum2([
180468
- "pending",
180469
- "running",
180470
- "done",
180471
- "failed",
180472
- "cancelled"
180473
- ]);
180474
- var TaskPrioritySchema = _enum2(["high", "medium", "low"]);
180475
- var TaskSchema = object({
180476
- id: string2().min(1),
180477
- source: TaskSourceSchema,
180478
- context: string2().nullable(),
180479
- status: TaskStatusSchema,
180480
- priority: TaskPrioritySchema.nullable(),
180481
- payload: string2(),
180482
- agent_assigned: string2().nullable(),
180483
- session_id: string2().nullable(),
180484
- result: string2().nullable(),
180485
- cost_tokens: number2().int().nonnegative().default(0),
180486
- cost_usd: number2().nonnegative().default(0),
180487
- created_at: number2().int(),
180488
- started_at: number2().int().nullable(),
180489
- completed_at: number2().int().nullable()
180490
- }).strict();
180491
- var TaskInsertSchema = object({
180492
- id: string2().min(1).optional(),
180493
- source: TaskSourceSchema,
180494
- context: string2().nullable().optional(),
180495
- status: TaskStatusSchema.optional(),
180496
- priority: TaskPrioritySchema.nullable().optional(),
180497
- payload: string2(),
180498
- agent_assigned: string2().nullable().optional(),
180499
- session_id: string2().nullable().optional(),
180500
- cost_tokens: number2().int().nonnegative().optional(),
180501
- cost_usd: number2().nonnegative().optional()
180502
- }).strict();
180503
- var TaskPatchSchema = object({
180504
- status: TaskStatusSchema.optional(),
180505
- priority: TaskPrioritySchema.nullable().optional(),
180506
- agent_assigned: string2().nullable().optional(),
180507
- session_id: string2().nullable().optional(),
180508
- result: string2().nullable().optional(),
180509
- cost_tokens: number2().int().nonnegative().optional(),
180510
- cost_usd: number2().nonnegative().optional(),
180511
- started_at: number2().int().nullable().optional(),
180512
- completed_at: number2().int().nullable().optional()
180513
- }).strict();
180514
- var TaskFilterSchema = object({
180515
- source: TaskSourceSchema.optional(),
180516
- context: string2().optional(),
180517
- status: TaskStatusSchema.optional(),
180518
- agent_assigned: string2().optional(),
180519
- session_id: string2().optional(),
180520
- priority: TaskPrioritySchema.optional()
180521
- }).strict();
180522
-
180523
- // packages/task-ledger-core/src/ledger.ts
180524
- import { randomUUID as randomUUID2 } from "crypto";
180525
- var CREATE_TABLE_SQL = `
180526
- CREATE TABLE IF NOT EXISTS tasks (
180527
- id TEXT PRIMARY KEY,
180528
- source TEXT NOT NULL,
180529
- context TEXT,
180530
- status TEXT NOT NULL,
180531
- priority TEXT,
180532
- payload TEXT NOT NULL,
180533
- agent_assigned TEXT,
180534
- session_id TEXT,
180535
- result TEXT,
180536
- cost_tokens INTEGER DEFAULT 0,
180537
- cost_usd REAL DEFAULT 0,
180538
- created_at INTEGER NOT NULL,
180539
- started_at INTEGER,
180540
- completed_at INTEGER
180541
- )
180542
- `;
180543
- var CREATE_INDEX_STATUS = `CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)`;
180544
- var CREATE_INDEX_CONTEXT = `CREATE INDEX IF NOT EXISTS idx_tasks_context ON tasks(context)`;
180545
- var CREATE_INDEX_SOURCE = `CREATE INDEX IF NOT EXISTS idx_tasks_source ON tasks(source)`;
180546
- var INSERT_SQL = `
180547
- INSERT INTO tasks (id, source, context, status, priority, payload, agent_assigned, session_id, result, cost_tokens, cost_usd, created_at, started_at, completed_at)
180548
- VALUES ($id, $source, $context, $status, $priority, $payload, $agent_assigned, $session_id, $result, $cost_tokens, $cost_usd, $created_at, $started_at, $completed_at)
180549
- `;
180550
- var SELECT_BY_ID_SQL = `SELECT * FROM tasks WHERE id = $id`;
180551
- var DELETE_BY_ID_SQL = `DELETE FROM tasks WHERE id = $id`;
180552
- var UPDATE_SQL = `
180553
- UPDATE tasks SET
180554
- status = COALESCE($status, status),
180555
- priority = COALESCE($priority, priority),
180556
- agent_assigned = COALESCE($agent_assigned, agent_assigned),
180557
- session_id = COALESCE($session_id, session_id),
180558
- result = COALESCE($result, result),
180559
- cost_tokens = COALESCE($cost_tokens, cost_tokens),
180560
- cost_usd = COALESCE($cost_usd, cost_usd),
180561
- started_at = COALESCE($started_at, started_at),
180562
- completed_at = COALESCE($completed_at, completed_at)
180563
- WHERE id = $id
180564
- `;
180565
- function rowToTask(row) {
180566
- return {
180567
- id: row.id,
180568
- source: row.source,
180569
- context: row.context,
180570
- status: row.status,
180571
- priority: row.priority,
180572
- payload: row.payload,
180573
- agent_assigned: row.agent_assigned,
180574
- session_id: row.session_id,
180575
- result: row.result,
180576
- cost_tokens: row.cost_tokens,
180577
- cost_usd: row.cost_usd,
180578
- created_at: row.created_at,
180579
- started_at: row.started_at,
180580
- completed_at: row.completed_at
180581
- };
180582
- }
180583
- function createTaskLedger(db) {
180584
- db.exec(CREATE_TABLE_SQL);
180585
- db.exec(CREATE_INDEX_STATUS);
180586
- db.exec(CREATE_INDEX_CONTEXT);
180587
- db.exec(CREATE_INDEX_SOURCE);
180588
- return {
180589
- insert(input) {
180590
- const now = Date.now();
180591
- const task2 = TaskSchema.parse({
180592
- id: input.id ?? randomUUID2(),
180593
- source: input.source,
180594
- context: input.context ?? null,
180595
- status: input.status ?? "pending",
180596
- priority: input.priority ?? null,
180597
- payload: input.payload,
180598
- agent_assigned: input.agent_assigned ?? null,
180599
- session_id: input.session_id ?? null,
180600
- result: null,
180601
- cost_tokens: input.cost_tokens ?? 0,
180602
- cost_usd: input.cost_usd ?? 0,
180603
- created_at: now,
180604
- started_at: null,
180605
- completed_at: null
180606
- });
180607
- db.exec(INSERT_SQL, {
180608
- $id: task2.id,
180609
- $source: task2.source,
180610
- $context: task2.context,
180611
- $status: task2.status,
180612
- $priority: task2.priority,
180613
- $payload: task2.payload,
180614
- $agent_assigned: task2.agent_assigned,
180615
- $session_id: task2.session_id,
180616
- $result: task2.result,
180617
- $cost_tokens: task2.cost_tokens,
180618
- $cost_usd: task2.cost_usd,
180619
- $created_at: task2.created_at,
180620
- $started_at: task2.started_at,
180621
- $completed_at: task2.completed_at
180622
- });
180623
- return task2;
180624
- },
180625
- get(id) {
180626
- const rows = db.query(SELECT_BY_ID_SQL, { $id: id });
180627
- if (rows.length === 0)
180628
- return null;
180629
- return rowToTask(rows[0]);
180630
- },
180631
- list(filter) {
180632
- const conditions = [];
180633
- const params = {};
180634
- if (filter?.source) {
180635
- conditions.push("source = $source");
180636
- params.$source = filter.source;
180637
- }
180638
- if (filter?.context) {
180639
- conditions.push("context = $context");
180640
- params.$context = filter.context;
180641
- }
180642
- if (filter?.status) {
180643
- conditions.push("status = $status");
180644
- params.$status = filter.status;
180645
- }
180646
- if (filter?.agent_assigned) {
180647
- conditions.push("agent_assigned = $agent_assigned");
180648
- params.$agent_assigned = filter.agent_assigned;
180649
- }
180650
- if (filter?.session_id) {
180651
- conditions.push("session_id = $session_id");
180652
- params.$session_id = filter.session_id;
180653
- }
180654
- if (filter?.priority) {
180655
- conditions.push("priority = $priority");
180656
- params.$priority = filter.priority;
180657
- }
180658
- const where = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
180659
- const sql = `SELECT * FROM tasks${where} ORDER BY created_at DESC`;
180660
- const rows = db.query(sql, params);
180661
- return rows.map(rowToTask);
180662
- },
180663
- update(id, patch) {
180664
- const existing = db.query(SELECT_BY_ID_SQL, { $id: id });
180665
- if (existing.length === 0)
180666
- return null;
180667
- const params = { $id: id };
180668
- if (patch.status !== undefined)
180669
- params.$status = patch.status;
180670
- if (patch.priority !== undefined)
180671
- params.$priority = patch.priority;
180672
- if (patch.agent_assigned !== undefined)
180673
- params.$agent_assigned = patch.agent_assigned;
180674
- if (patch.session_id !== undefined)
180675
- params.$session_id = patch.session_id;
180676
- if (patch.result !== undefined)
180677
- params.$result = patch.result;
180678
- if (patch.cost_tokens !== undefined)
180679
- params.$cost_tokens = patch.cost_tokens;
180680
- if (patch.cost_usd !== undefined)
180681
- params.$cost_usd = patch.cost_usd;
180682
- if (patch.started_at !== undefined)
180683
- params.$started_at = patch.started_at;
180684
- if (patch.completed_at !== undefined)
180685
- params.$completed_at = patch.completed_at;
180686
- db.exec(UPDATE_SQL, params);
180687
- return this.get(id);
180688
- },
180689
- remove(id) {
180690
- const before = db.query(SELECT_BY_ID_SQL, { $id: id });
180691
- if (before.length === 0)
180692
- return false;
180693
- db.exec(DELETE_BY_ID_SQL, { $id: id });
180694
- return true;
180695
- },
180696
- listPending() {
180697
- const rows = db.query(`SELECT * FROM tasks WHERE status = 'pending' ORDER BY created_at ASC`);
180698
- return rows.map(rowToTask);
180699
- },
180700
- listFailed() {
180701
- const rows = db.query(`SELECT * FROM tasks WHERE status = 'failed' ORDER BY created_at ASC`);
180702
- return rows.map(rowToTask);
180703
- },
180704
- listByContext(context) {
180705
- const rows = db.query(`SELECT * FROM tasks WHERE context = $context ORDER BY created_at DESC`, { $context: context });
180706
- return rows.map(rowToTask);
180707
- },
180708
- close() {
180709
- db.close();
180710
- }
180711
- };
180712
- }
180713
-
180714
- // packages/task-ledger-core/src/sqlite.ts
180715
- import { Database as Database2 } from "bun:sqlite";
180716
- function createSqliteDatabase(dbPath) {
180717
- const db = new Database2(dbPath);
180718
- db.exec("PRAGMA journal_mode = WAL");
180719
- db.exec("PRAGMA foreign_keys = ON");
180720
- return {
180721
- exec(sql, ...params) {
180722
- if (params.length === 0) {
180723
- db.run(sql);
180724
- } else {
180725
- const named = params[0];
180726
- db.run(sql, named);
180727
- }
180728
- },
180729
- query(sql, ...params) {
180730
- if (params.length === 0) {
180731
- return db.prepare(sql).all();
180732
- }
180733
- const named = params[0];
180734
- return db.prepare(sql).all(named);
180735
- },
180736
- close() {
180737
- db.close();
180738
- }
180739
- };
180740
- }
180741
-
180742
181204
  // packages/omo-opencode/src/cli/daily-brief.ts
181205
+ init_src6();
180743
181206
  async function dailyBriefSend(options) {
180744
181207
  try {
180745
181208
  const rawLedger = createTaskLedger(createSqliteDatabase(process.env.TASK_LEDGER_DB ?? "/root/.matrixos/tasks.db"));
180746
- const ledger = {
181209
+ const ledger2 = {
180747
181210
  listPending: () => rawLedger.listPending(),
180748
181211
  listFailed: () => rawLedger.list({ status: "failed" })
180749
181212
  };
@@ -180768,7 +181231,7 @@ async function dailyBriefSend(options) {
180768
181231
  recipient_id: recipient,
180769
181232
  channel
180770
181233
  }),
180771
- ledger,
181234
+ ledger: ledger2,
180772
181235
  sender,
180773
181236
  now: () => Date.now()
180774
181237
  });
@@ -186062,7 +186525,7 @@ function createDataProvider(config5) {
186062
186525
  } catch {}
186063
186526
  if (entries.length > 0)
186064
186527
  return entries;
186065
- const types15 = ["episodic", "semantic", "procedural", "reflection"];
186528
+ const types16 = ["episodic", "semantic", "procedural", "reflection"];
186066
186529
  const mockContent = [
186067
186530
  "User prefers concise responses with bullet points",
186068
186531
  "Project MaTrixOS uses Bun runtime and TypeScript strict mode",
@@ -186076,7 +186539,7 @@ function createDataProvider(config5) {
186076
186539
  entries.push({
186077
186540
  id: `mem_${randomBetween(1000, 9999)}`,
186078
186541
  content: randomChoice(mockContent),
186079
- type: randomChoice(types15),
186542
+ type: randomChoice(types16),
186080
186543
  confidence: Math.round(randomBetween(60, 99)),
186081
186544
  created_at: new Date(Date.now() - randomBetween(0, 604800000)).toISOString()
186082
186545
  });
@@ -186846,6 +187309,63 @@ program2.command("export [name]").description("Export a mini-OS profile as a sta
186846
187309
  process.exit(result.exitCode);
186847
187310
  });
186848
187311
  program2.addCommand(createMcpOAuthCommand());
187312
+ var project = program2.command("project").description("Manage MaTrixOS projects (active context, kanban, knowledge base)");
187313
+ 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) => {
187314
+ const { createProject: createProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187315
+ const info = createProject2(slug, { name: options.name, description: options.description });
187316
+ process.stdout.write(JSON.stringify(info, null, 2) + `
187317
+ `);
187318
+ });
187319
+ project.command("list").alias("ls").description("List all projects").action(async () => {
187320
+ const { listProjects: listProjects2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187321
+ const list = listProjects2();
187322
+ process.stdout.write(JSON.stringify(list, null, 2) + `
187323
+ `);
187324
+ });
187325
+ project.command("switch <slug>").description("Switch the active project").action(async (slug) => {
187326
+ const { switchProject: switchProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187327
+ const info = switchProject2(slug);
187328
+ process.stdout.write(JSON.stringify(info, null, 2) + `
187329
+ `);
187330
+ });
187331
+ project.command("active").description("Show the active project").action(async () => {
187332
+ const { getActiveProject: getActiveProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187333
+ const info = getActiveProject2();
187334
+ process.stdout.write(JSON.stringify(info ?? null, null, 2) + `
187335
+ `);
187336
+ });
187337
+ project.command("archive <slug>").description("Archive a project (removes it from the active list)").action(async (slug) => {
187338
+ const { archiveProject: archiveProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187339
+ const info = archiveProject2(slug);
187340
+ process.stdout.write(JSON.stringify(info, null, 2) + `
187341
+ `);
187342
+ });
187343
+ project.command("unarchive <slug>").description("Unarchive a project").action(async (slug) => {
187344
+ const { unarchiveProject: unarchiveProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187345
+ const info = unarchiveProject2(slug);
187346
+ process.stdout.write(JSON.stringify(info, null, 2) + `
187347
+ `);
187348
+ });
187349
+ project.command("delete <slug>").description("Permanently delete a project").action(async (slug) => {
187350
+ const { deleteProject: deleteProject2 } = await Promise.resolve().then(() => (init_project_context(), exports_project_context));
187351
+ deleteProject2(slug);
187352
+ process.stdout.write(JSON.stringify({ ok: true, deleted: slug }, null, 2) + `
187353
+ `);
187354
+ });
187355
+ 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) => {
187356
+ const { searchProject: searchProject2 } = await Promise.resolve().then(() => (init_project_memory(), exports_project_memory));
187357
+ const hits = await searchProject2(query, { projectSlug: options.project });
187358
+ process.stdout.write(JSON.stringify(hits, null, 2) + `
187359
+ `);
187360
+ });
187361
+ project.command("add-doc <slug> <file>").description("Copy a document into the project KB").action(async (slug, filePath) => {
187362
+ const { addKbDocument: addKbDocument2 } = await Promise.resolve().then(() => (init_project_memory(), exports_project_memory));
187363
+ const { readFileSync: readFileSync64 } = await import("fs");
187364
+ const content = readFileSync64(filePath, "utf-8");
187365
+ const dest = addKbDocument2(slug, filePath, content);
187366
+ process.stdout.write(JSON.stringify({ ok: true, dest }, null, 2) + `
187367
+ `);
187368
+ });
186849
187369
  var gateway2 = program2.command("gateway").description("Gateway configuration \u2014 bot token management");
186850
187370
  var gatewayAdopt = gateway2.command("adopt").description("Adopt a gateway channel (Telegram, Discord, WhatsApp)");
186851
187371
  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", `
@@ -186909,6 +187429,19 @@ gateway2.command("status").description("Check gateway status (best-effort, inspe
186909
187429
  }, null, 2) + `
186910
187430
  `);
186911
187431
  });
187432
+ 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) => {
187433
+ const { executeSelfAuditCommand: executeSelfAuditCommand2 } = await Promise.resolve().then(() => (init_self_audit_command(), exports_self_audit_command));
187434
+ const result = await executeSelfAuditCommand2(options);
187435
+ if (options.json) {
187436
+ process.stdout.write(JSON.stringify(result, null, 2) + `
187437
+ `);
187438
+ } else if (result.path) {
187439
+ console.log(`Self-audit written to ${result.path}`);
187440
+ } else {
187441
+ console.log(result.message);
187442
+ }
187443
+ process.exit(result.ok ? 0 : 1);
187444
+ });
186912
187445
  program2.command("adopt").description("Re-run the MaTrixOS adoption wizard (providers, channels, profile)").addHelpText("after", `
186913
187446
  Examples:
186914
187447
  $ matrixos adopt # interactive re-adoption (TUI)