@sanity-labs/nuum 0.2.2 → 0.4.0

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/index.js CHANGED
@@ -4245,7 +4245,7 @@ var require_conditions = __commonJS((exports, module) => {
4245
4245
  isNotNull: () => isNotNull,
4246
4246
  isNull: () => isNull2,
4247
4247
  like: () => like2,
4248
- lt: () => lt,
4248
+ lt: () => lt2,
4249
4249
  lte: () => lte2,
4250
4250
  ne: () => ne,
4251
4251
  not: () => not,
@@ -4310,7 +4310,7 @@ var require_conditions = __commonJS((exports, module) => {
4310
4310
  var gte2 = (left, right) => {
4311
4311
  return import_sql4.sql`${left} >= ${bindIfParam2(right, left)}`;
4312
4312
  };
4313
- var lt = (left, right) => {
4313
+ var lt2 = (left, right) => {
4314
4314
  return import_sql4.sql`${left} < ${bindIfParam2(right, left)}`;
4315
4315
  };
4316
4316
  var lte2 = (left, right) => {
@@ -8968,6 +8968,76 @@ var require_bun_sqlite = __commonJS((exports, module) => {
8968
8968
  __reExport(bun_sqlite_exports, require_session2(), module.exports);
8969
8969
  });
8970
8970
 
8971
+ // node_modules/picocolors/picocolors.js
8972
+ var require_picocolors = __commonJS((exports, module) => {
8973
+ var p = process || {};
8974
+ var argv = p.argv || [];
8975
+ var env = p.env || {};
8976
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
8977
+ var formatter = (open, close, replace = open) => (input) => {
8978
+ let string = "" + input, index2 = string.indexOf(close, open.length);
8979
+ return ~index2 ? open + replaceClose(string, close, replace, index2) + close : open + string + close;
8980
+ };
8981
+ var replaceClose = (string, close, replace, index2) => {
8982
+ let result = "", cursor = 0;
8983
+ do {
8984
+ result += string.substring(cursor, index2) + replace;
8985
+ cursor = index2 + close.length;
8986
+ index2 = string.indexOf(close, cursor);
8987
+ } while (~index2);
8988
+ return result + string.substring(cursor);
8989
+ };
8990
+ var createColors = (enabled = isColorSupported) => {
8991
+ let f = enabled ? formatter : () => String;
8992
+ return {
8993
+ isColorSupported: enabled,
8994
+ reset: f("\x1B[0m", "\x1B[0m"),
8995
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
8996
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
8997
+ italic: f("\x1B[3m", "\x1B[23m"),
8998
+ underline: f("\x1B[4m", "\x1B[24m"),
8999
+ inverse: f("\x1B[7m", "\x1B[27m"),
9000
+ hidden: f("\x1B[8m", "\x1B[28m"),
9001
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
9002
+ black: f("\x1B[30m", "\x1B[39m"),
9003
+ red: f("\x1B[31m", "\x1B[39m"),
9004
+ green: f("\x1B[32m", "\x1B[39m"),
9005
+ yellow: f("\x1B[33m", "\x1B[39m"),
9006
+ blue: f("\x1B[34m", "\x1B[39m"),
9007
+ magenta: f("\x1B[35m", "\x1B[39m"),
9008
+ cyan: f("\x1B[36m", "\x1B[39m"),
9009
+ white: f("\x1B[37m", "\x1B[39m"),
9010
+ gray: f("\x1B[90m", "\x1B[39m"),
9011
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
9012
+ bgRed: f("\x1B[41m", "\x1B[49m"),
9013
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
9014
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
9015
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
9016
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
9017
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
9018
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
9019
+ blackBright: f("\x1B[90m", "\x1B[39m"),
9020
+ redBright: f("\x1B[91m", "\x1B[39m"),
9021
+ greenBright: f("\x1B[92m", "\x1B[39m"),
9022
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
9023
+ blueBright: f("\x1B[94m", "\x1B[39m"),
9024
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
9025
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
9026
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
9027
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
9028
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
9029
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
9030
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
9031
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
9032
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
9033
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
9034
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
9035
+ };
9036
+ };
9037
+ module.exports = createColors();
9038
+ module.exports.createColors = createColors;
9039
+ });
9040
+
8971
9041
  // node_modules/secure-json-parse/index.js
8972
9042
  var require_secure_json_parse = __commonJS((exports, module) => {
8973
9043
  var hasBuffer = typeof Buffer !== "undefined";
@@ -17401,7 +17471,10 @@ __export(exports_schema, {
17401
17471
  sessionConfig: () => sessionConfig,
17402
17472
  presentState: () => presentState,
17403
17473
  ltmEntries: () => ltmEntries,
17404
- backgroundReports: () => backgroundReports
17474
+ backgroundTasks: () => backgroundTasks,
17475
+ backgroundTaskQueue: () => backgroundTaskQueue,
17476
+ backgroundReports: () => backgroundReports,
17477
+ alarms: () => alarms
17405
17478
  });
17406
17479
 
17407
17480
  // node_modules/drizzle-orm/entity.js
@@ -18575,6 +18648,9 @@ function and(...unfilteredConditions) {
18575
18648
  var gte = (left, right) => {
18576
18649
  return sql`${left} >= ${bindIfParam(right, left)}`;
18577
18650
  };
18651
+ var lt = (left, right) => {
18652
+ return sql`${left} < ${bindIfParam(right, left)}`;
18653
+ };
18578
18654
  var lte = (left, right) => {
18579
18655
  return sql`${left} <= ${bindIfParam(right, left)}`;
18580
18656
  };
@@ -18643,9 +18719,7 @@ var temporalMessages = sqliteTable("temporal_messages", {
18643
18719
  content: text("content").notNull(),
18644
18720
  tokenEstimate: integer("token_estimate").notNull(),
18645
18721
  createdAt: text("created_at").notNull()
18646
- }, (table) => [
18647
- index("idx_temporal_messages_created").on(table.id)
18648
- ]);
18722
+ }, (table) => [index("idx_temporal_messages_created").on(table.id)]);
18649
18723
  var temporalSummaries = sqliteTable("temporal_summaries", {
18650
18724
  id: text("id").primaryKey(),
18651
18725
  orderNum: integer("order_num").notNull(),
@@ -18701,9 +18775,29 @@ var backgroundReports = sqliteTable("background_reports", {
18701
18775
  subsystem: text("subsystem").notNull(),
18702
18776
  report: text("report").notNull(),
18703
18777
  surfacedAt: text("surfaced_at")
18704
- }, (table) => [
18705
- index("idx_background_reports_unsurfaced").on(table.surfacedAt)
18706
- ]);
18778
+ }, (table) => [index("idx_background_reports_unsurfaced").on(table.surfacedAt)]);
18779
+ var backgroundTasks = sqliteTable("background_tasks", {
18780
+ id: text("id").primaryKey(),
18781
+ type: text("type").notNull(),
18782
+ description: text("description").notNull(),
18783
+ status: text("status").notNull(),
18784
+ createdAt: text("created_at").notNull(),
18785
+ completedAt: text("completed_at"),
18786
+ result: text("result"),
18787
+ error: text("error")
18788
+ }, (table) => [index("idx_background_tasks_status").on(table.status)]);
18789
+ var backgroundTaskQueue = sqliteTable("background_task_queue", {
18790
+ id: text("id").primaryKey(),
18791
+ taskId: text("task_id").notNull(),
18792
+ createdAt: text("created_at").notNull(),
18793
+ content: text("content").notNull()
18794
+ }, (table) => [index("idx_background_task_queue_created").on(table.createdAt)]);
18795
+ var alarms = sqliteTable("alarms", {
18796
+ id: text("id").primaryKey(),
18797
+ firesAt: text("fires_at").notNull(),
18798
+ note: text("note").notNull(),
18799
+ fired: integer("fired").notNull().default(0)
18800
+ }, (table) => [index("idx_alarms_fires_at").on(table.firesAt)]);
18707
18801
 
18708
18802
  // src/storage/db.ts
18709
18803
  var isBun = typeof globalThis.Bun !== "undefined";
@@ -22705,6 +22799,7 @@ var coerce = {
22705
22799
  };
22706
22800
  var NEVER = INVALID;
22707
22801
  // src/util/log.ts
22802
+ var import_picocolors = __toESM(require_picocolors(), 1);
22708
22803
  var Log;
22709
22804
  ((Log) => {
22710
22805
  Log.Level = exports_external.enum(["DEBUG", "INFO", "WARN", "ERROR"]);
@@ -22714,7 +22809,13 @@ var Log;
22714
22809
  WARN: 2,
22715
22810
  ERROR: 3
22716
22811
  };
22717
- let level = "INFO";
22812
+ const levelColors = {
22813
+ DEBUG: import_picocolors.default.gray,
22814
+ INFO: import_picocolors.default.blue,
22815
+ WARN: (s) => import_picocolors.default.bold(import_picocolors.default.yellow(s)),
22816
+ ERROR: (s) => import_picocolors.default.bold(import_picocolors.default.red(s))
22817
+ };
22818
+ let level = "WARN";
22718
22819
  function shouldLog(input) {
22719
22820
  return levelPriority[input] >= levelPriority[level];
22720
22821
  }
@@ -22751,43 +22852,46 @@ var Log;
22751
22852
  return cached;
22752
22853
  }
22753
22854
  }
22754
- function build(message, extra) {
22855
+ function build(logLevel, message, extra) {
22755
22856
  const prefix = Object.entries({
22756
22857
  ...tags,
22757
22858
  ...extra
22758
22859
  }).filter(([_, value]) => value !== undefined && value !== null).map(([key, value]) => {
22759
- const prefix2 = `${key}=`;
22860
+ const keyStr = import_picocolors.default.dim(key + "=");
22760
22861
  if (value instanceof Error)
22761
- return prefix2 + formatError(value);
22862
+ return keyStr + import_picocolors.default.red(formatError(value));
22762
22863
  if (typeof value === "object")
22763
- return prefix2 + JSON.stringify(value);
22764
- return prefix2 + value;
22864
+ return keyStr + import_picocolors.default.cyan(JSON.stringify(value));
22865
+ return keyStr + value;
22765
22866
  }).join(" ");
22766
22867
  const next = new Date;
22767
22868
  const diff = next.getTime() - last;
22768
22869
  last = next.getTime();
22769
- return [next.toISOString().split(".")[0], "+" + diff + "ms", prefix, message].filter(Boolean).join(" ") + `
22870
+ const timestamp = import_picocolors.default.dim(next.toISOString().split(".")[0]);
22871
+ const duration = import_picocolors.default.dim("+" + diff + "ms");
22872
+ const levelStr = levelColors[logLevel](logLevel.padEnd(5));
22873
+ return [levelStr, timestamp, duration, prefix, message].filter(Boolean).join(" ") + `
22770
22874
  `;
22771
22875
  }
22772
22876
  const result = {
22773
22877
  debug(message, extra) {
22774
22878
  if (shouldLog("DEBUG")) {
22775
- write("DEBUG " + build(message, extra));
22879
+ write(build("DEBUG", message, extra));
22776
22880
  }
22777
22881
  },
22778
22882
  info(message, extra) {
22779
22883
  if (shouldLog("INFO")) {
22780
- write("INFO " + build(message, extra));
22884
+ write(build("INFO", message, extra));
22781
22885
  }
22782
22886
  },
22783
22887
  error(message, extra) {
22784
22888
  if (shouldLog("ERROR")) {
22785
- write("ERROR " + build(message, extra));
22889
+ write(build("ERROR", message, extra));
22786
22890
  }
22787
22891
  },
22788
22892
  warn(message, extra) {
22789
22893
  if (shouldLog("WARN")) {
22790
- write("WARN " + build(message, extra));
22894
+ write(build("WARN", message, extra));
22791
22895
  }
22792
22896
  },
22793
22897
  tag(key, value) {
@@ -22911,7 +23015,10 @@ function rebuildFTSIndexes(db) {
22911
23015
  db.exec(`INSERT INTO ${tableName}(${tableName}) VALUES('rebuild')`);
22912
23016
  log.debug("rebuilt FTS index", { table: tableName });
22913
23017
  } catch (error) {
22914
- log.debug("skipped FTS rebuild", { table: tableName, reason: String(error) });
23018
+ log.debug("skipped FTS rebuild", {
23019
+ table: tableName,
23020
+ reason: String(error)
23021
+ });
22915
23022
  }
22916
23023
  }
22917
23024
  } catch (error) {
@@ -23468,6 +23575,9 @@ var Identifier;
23468
23575
  entry: "ent",
23469
23576
  worker: "wrk",
23470
23577
  report: "rpt",
23578
+ bgtask: "bgt",
23579
+ queue: "que",
23580
+ alarm: "alm",
23471
23581
  session: "ses",
23472
23582
  toolcall: "tcl"
23473
23583
  };
@@ -23612,6 +23722,159 @@ function createBackgroundStorage(db) {
23612
23722
  };
23613
23723
  }
23614
23724
 
23725
+ // src/storage/tasks.ts
23726
+ function createTasksStorage(db) {
23727
+ return {
23728
+ async createTask(input) {
23729
+ const id = Identifier.ascending("bgtask");
23730
+ const now = new Date().toISOString();
23731
+ await db.insert(backgroundTasks).values({
23732
+ id,
23733
+ type: input.type,
23734
+ description: input.description,
23735
+ status: "running",
23736
+ createdAt: now
23737
+ });
23738
+ return id;
23739
+ },
23740
+ async getTask(id) {
23741
+ const rows = await db.select().from(backgroundTasks).where(eq(backgroundTasks.id, id)).limit(1);
23742
+ if (rows.length === 0)
23743
+ return null;
23744
+ const row = rows[0];
23745
+ return {
23746
+ id: row.id,
23747
+ type: row.type,
23748
+ description: row.description,
23749
+ status: row.status,
23750
+ createdAt: row.createdAt,
23751
+ completedAt: row.completedAt,
23752
+ result: row.result ? JSON.parse(row.result) : null,
23753
+ error: row.error
23754
+ };
23755
+ },
23756
+ async listTasks(options) {
23757
+ const limit = options?.limit ?? 50;
23758
+ let query = db.select().from(backgroundTasks);
23759
+ if (options?.status) {
23760
+ query = query.where(eq(backgroundTasks.status, options.status));
23761
+ }
23762
+ const rows = await query.orderBy(backgroundTasks.createdAt).limit(limit);
23763
+ return rows.map((row) => ({
23764
+ id: row.id,
23765
+ type: row.type,
23766
+ description: row.description,
23767
+ status: row.status,
23768
+ createdAt: row.createdAt,
23769
+ completedAt: row.completedAt,
23770
+ result: row.result ? JSON.parse(row.result) : null,
23771
+ error: row.error
23772
+ }));
23773
+ },
23774
+ async completeTask(id, result) {
23775
+ const now = new Date().toISOString();
23776
+ await db.update(backgroundTasks).set({
23777
+ status: "completed",
23778
+ completedAt: now,
23779
+ result: JSON.stringify(result)
23780
+ }).where(eq(backgroundTasks.id, id));
23781
+ },
23782
+ async failTask(id, error) {
23783
+ const now = new Date().toISOString();
23784
+ await db.update(backgroundTasks).set({
23785
+ status: "failed",
23786
+ completedAt: now,
23787
+ error
23788
+ }).where(eq(backgroundTasks.id, id));
23789
+ },
23790
+ async recoverKilledTasks() {
23791
+ const runningTasks = await db.select().from(backgroundTasks).where(eq(backgroundTasks.status, "running"));
23792
+ if (runningTasks.length > 0) {
23793
+ const now = new Date().toISOString();
23794
+ await db.update(backgroundTasks).set({
23795
+ status: "killed",
23796
+ completedAt: now
23797
+ }).where(eq(backgroundTasks.status, "running"));
23798
+ }
23799
+ return runningTasks.map((row) => ({
23800
+ id: row.id,
23801
+ type: row.type,
23802
+ description: row.description,
23803
+ status: "killed",
23804
+ createdAt: row.createdAt,
23805
+ completedAt: row.completedAt,
23806
+ result: null,
23807
+ error: null
23808
+ }));
23809
+ },
23810
+ async queueResult(taskId, content) {
23811
+ const id = Identifier.ascending("bgtask");
23812
+ const now = new Date().toISOString();
23813
+ await db.insert(backgroundTaskQueue).values({
23814
+ id,
23815
+ taskId,
23816
+ createdAt: now,
23817
+ content
23818
+ });
23819
+ },
23820
+ async drainQueue() {
23821
+ const rows = await db.select().from(backgroundTaskQueue).orderBy(backgroundTaskQueue.createdAt);
23822
+ if (rows.length === 0)
23823
+ return [];
23824
+ const ids = rows.map((r) => r.id);
23825
+ for (const id of ids) {
23826
+ await db.delete(backgroundTaskQueue).where(eq(backgroundTaskQueue.id, id));
23827
+ }
23828
+ return rows.map((row) => ({
23829
+ id: row.id,
23830
+ taskId: row.taskId,
23831
+ createdAt: row.createdAt,
23832
+ content: row.content
23833
+ }));
23834
+ },
23835
+ async hasQueuedResults() {
23836
+ const rows = await db.select({ id: backgroundTaskQueue.id }).from(backgroundTaskQueue).limit(1);
23837
+ return rows.length > 0;
23838
+ },
23839
+ async createAlarm(input) {
23840
+ const id = Identifier.ascending("bgtask");
23841
+ await db.insert(alarms).values({
23842
+ id,
23843
+ firesAt: input.firesAt,
23844
+ note: input.note,
23845
+ fired: 0
23846
+ });
23847
+ return id;
23848
+ },
23849
+ async getDueAlarms() {
23850
+ const now = new Date().toISOString();
23851
+ const rows = await db.select().from(alarms).where(and(eq(alarms.fired, 0), lt(alarms.firesAt, now))).orderBy(alarms.firesAt);
23852
+ return rows.map((row) => ({
23853
+ id: row.id,
23854
+ firesAt: row.firesAt,
23855
+ note: row.note,
23856
+ fired: row.fired === 1
23857
+ }));
23858
+ },
23859
+ async markAlarmFired(id) {
23860
+ await db.update(alarms).set({ fired: 1 }).where(eq(alarms.id, id));
23861
+ },
23862
+ async listAlarms(options) {
23863
+ let query = db.select().from(alarms);
23864
+ if (!options?.includeFired) {
23865
+ query = query.where(eq(alarms.fired, 0));
23866
+ }
23867
+ const rows = await query.orderBy(alarms.firesAt);
23868
+ return rows.map((row) => ({
23869
+ id: row.id,
23870
+ firesAt: row.firesAt,
23871
+ note: row.note,
23872
+ fired: row.fired === 1
23873
+ }));
23874
+ }
23875
+ };
23876
+ }
23877
+
23615
23878
  // src/storage/index.ts
23616
23879
  function createStorage(dbPath, options) {
23617
23880
  const { mkdirSync } = __require("fs");
@@ -23631,6 +23894,7 @@ function createStorageFromDb(db) {
23631
23894
  workers: createWorkerStorage(db),
23632
23895
  session: createSessionStorage(db),
23633
23896
  background: createBackgroundStorage(db),
23897
+ tasks: createTasksStorage(db),
23634
23898
  _db: db
23635
23899
  };
23636
23900
  }
@@ -31800,7 +32064,10 @@ Please check the tool's parameter schema and try again with correct arguments.`;
31800
32064
  });
31801
32065
  }
31802
32066
  function createToolCallRepairFunction() {
31803
- return async ({ toolCall, error }) => {
32067
+ return async ({
32068
+ toolCall,
32069
+ error
32070
+ }) => {
31804
32071
  const errorMessage = error.message || String(error);
31805
32072
  log3.warn("invalid tool call - redirecting to error tool", {
31806
32073
  toolName: toolCall.toolName,
@@ -31996,7 +32263,9 @@ var Shell;
31996
32263
  return;
31997
32264
  if (process.platform === "win32") {
31998
32265
  await new Promise((resolve2) => {
31999
- const killer = spawn("taskkill", ["/pid", String(pid), "/f", "/t"], { stdio: "ignore" });
32266
+ const killer = spawn("taskkill", ["/pid", String(pid), "/f", "/t"], {
32267
+ stdio: "ignore"
32268
+ });
32000
32269
  killer.once("exit", () => resolve2());
32001
32270
  killer.once("error", () => resolve2());
32002
32271
  });
@@ -34293,63 +34562,246 @@ QUESTION: ${question}`
34293
34562
  };
34294
34563
  }
34295
34564
  });
34296
- // src/util/activity-log.ts
34565
+ // src/cli/renderer.ts
34566
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
34567
+ var lastEventType = "none";
34568
+ var replContext = null;
34569
+ function resetRenderer() {
34570
+ lastEventType = "none";
34571
+ }
34572
+ function setReplContext(rl, prompt) {
34573
+ replContext = { rl, prompt, isRunning: false };
34574
+ }
34575
+ function clearReplContext() {
34576
+ replContext = null;
34577
+ }
34578
+ function setReplRunning(running) {
34579
+ if (replContext) {
34580
+ replContext.isRunning = running;
34581
+ }
34582
+ }
34583
+ var DEFAULT_WIDTH = 80;
34584
+ var BULLET = import_picocolors2.default.blue("\u23FA");
34585
+ var CONTINUATION_INDENT = " ";
34586
+ function getTerminalWidth() {
34587
+ return process.stdout.columns || DEFAULT_WIDTH;
34588
+ }
34589
+ function stripAnsi(str) {
34590
+ return str.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "");
34591
+ }
34592
+ function displayWidth(str) {
34593
+ const stripped = stripAnsi(str);
34594
+ let width = 0;
34595
+ for (const char of stripped) {
34596
+ const code = char.codePointAt(0) || 0;
34597
+ if (code >= 127744 && code <= 129535 || code >= 9728 && code <= 9983 || code >= 9984 && code <= 10175 || code >= 128512 && code <= 128591 || code >= 128640 && code <= 128767) {
34598
+ width += 2;
34599
+ } else {
34600
+ width += 1;
34601
+ }
34602
+ }
34603
+ return width;
34604
+ }
34605
+ function wrapLine(text3, maxWidth) {
34606
+ const tokens = text3.split(/(\s+)/);
34607
+ const lines = [];
34608
+ let currentLine = "";
34609
+ let currentWidth = 0;
34610
+ for (const token of tokens) {
34611
+ if (!token)
34612
+ continue;
34613
+ if (!currentLine && /^\s+$/.test(token))
34614
+ continue;
34615
+ const isWhitespace = /^\s+$/.test(token);
34616
+ const tokenWidth = displayWidth(token);
34617
+ if (currentWidth + tokenWidth <= maxWidth) {
34618
+ currentLine += token;
34619
+ currentWidth += tokenWidth;
34620
+ } else if (isWhitespace) {
34621
+ continue;
34622
+ } else if (!currentLine) {
34623
+ currentLine = token;
34624
+ currentWidth = tokenWidth;
34625
+ } else {
34626
+ lines.push(currentLine);
34627
+ currentLine = token;
34628
+ currentWidth = tokenWidth;
34629
+ }
34630
+ }
34631
+ if (currentLine)
34632
+ lines.push(currentLine);
34633
+ return lines.length > 0 ? lines : [""];
34634
+ }
34635
+ function formatWithBullet(text3) {
34636
+ const termWidth = getTerminalWidth();
34637
+ const bulletPrefix = `${BULLET} `;
34638
+ const bulletLen = displayWidth(bulletPrefix);
34639
+ const maxFirstLine = termWidth - bulletLen;
34640
+ const maxContLine = termWidth - CONTINUATION_INDENT.length;
34641
+ const inputLines = text3.split(`
34642
+ `);
34643
+ const result = [];
34644
+ let isFirstOutputLine = true;
34645
+ for (const inputLine of inputLines) {
34646
+ if (inputLine === "") {
34647
+ result.push(isFirstOutputLine ? bulletPrefix : CONTINUATION_INDENT);
34648
+ isFirstOutputLine = false;
34649
+ continue;
34650
+ }
34651
+ const maxWidth = isFirstOutputLine ? maxFirstLine : maxContLine;
34652
+ const wrapped = wrapLine(inputLine, maxWidth);
34653
+ for (const line of wrapped) {
34654
+ if (isFirstOutputLine) {
34655
+ result.push(bulletPrefix + line);
34656
+ isFirstOutputLine = false;
34657
+ } else {
34658
+ result.push(CONTINUATION_INDENT + line);
34659
+ }
34660
+ }
34661
+ }
34662
+ return result.join(`
34663
+ `);
34664
+ }
34297
34665
  var ICONS = {
34298
- tool_call: "\uD83D\uDD27",
34299
- tool_result: "\u2713",
34300
- tool_error: "\u2717",
34301
- search: "\uD83D\uDD0D",
34302
- create: "\uD83D\uDCDD",
34303
- update: "\uD83D\uDCDD",
34304
- delete: "\uD83D\uDDD1\uFE0F",
34305
- start: "\u25B6",
34306
- complete: "\u2713",
34307
- skip: "\u2298",
34308
- thinking: "\uD83D\uDCAD",
34309
- info: "\u2139",
34310
- warn: "\u26A0",
34311
- error: "\u2717"
34666
+ success: import_picocolors2.default.green("\u2713"),
34667
+ error: import_picocolors2.default.red("\u2717"),
34668
+ start: import_picocolors2.default.blue("\u25B6"),
34669
+ complete: import_picocolors2.default.green("\u2713"),
34670
+ skip: import_picocolors2.default.dim("\u2298"),
34671
+ info: import_picocolors2.default.blue("\u2139"),
34672
+ warn: import_picocolors2.default.yellow("\u26A0")
34312
34673
  };
34313
- function formatWorker(worker) {
34314
- return `[${worker}]`;
34315
- }
34316
- function truncate(str, maxLen = 100) {
34674
+ function truncate(str, maxLen = 60) {
34317
34675
  if (str.length <= maxLen)
34318
34676
  return str;
34319
34677
  const half = Math.floor((maxLen - 5) / 2);
34320
34678
  return str.slice(0, half) + " ... " + str.slice(-half);
34321
34679
  }
34322
- function formatSize(bytes, lines) {
34323
- const parts = [];
34324
- if (lines !== undefined)
34325
- parts.push(`${lines} lines`);
34326
- if (bytes !== undefined) {
34327
- if (bytes < 1024)
34328
- parts.push(`${bytes}b`);
34329
- else
34330
- parts.push(`${(bytes / 1024).toFixed(1)}kb`);
34331
- }
34332
- return parts.join(", ");
34333
- }
34334
- function formatArgs(args) {
34680
+ function formatToolArgs(args) {
34335
34681
  const parts = [];
34336
34682
  for (const [key, value] of Object.entries(args)) {
34337
34683
  if (value === undefined || value === null)
34338
34684
  continue;
34685
+ let display;
34339
34686
  if (typeof value === "string") {
34340
- parts.push(`${key}=${truncate(value, 60)}`);
34687
+ display = truncate(value, 50);
34341
34688
  } else if (typeof value === "number" || typeof value === "boolean") {
34342
- parts.push(`${key}=${value}`);
34689
+ display = String(value);
34343
34690
  } else {
34344
- parts.push(`${key}=${truncate(JSON.stringify(value), 40)}`);
34691
+ display = truncate(JSON.stringify(value), 40);
34692
+ }
34693
+ parts.push(`${import_picocolors2.default.dim(key + "=")}${import_picocolors2.default.cyan(display)}`);
34694
+ }
34695
+ return parts.length > 0 ? `${import_picocolors2.default.dim("(")}${parts.join(import_picocolors2.default.dim(", "))}${import_picocolors2.default.dim(")")}` : "";
34696
+ }
34697
+ function formatEvent(event) {
34698
+ switch (event.type) {
34699
+ case "tool_start": {
34700
+ const args = formatToolArgs(event.args);
34701
+ return formatWithBullet(`${import_picocolors2.default.magenta(event.tool)}${args}`);
34702
+ }
34703
+ case "tool_result": {
34704
+ return formatWithBullet(`${ICONS.success} ${import_picocolors2.default.magenta(event.tool)}${import_picocolors2.default.dim(":")} ${event.summary}`);
34705
+ }
34706
+ case "tool_error": {
34707
+ return formatWithBullet(`${ICONS.error} ${import_picocolors2.default.magenta(event.tool)}${import_picocolors2.default.dim(":")} ${import_picocolors2.default.red(truncate(event.error, 100))}`);
34708
+ }
34709
+ case "thinking": {
34710
+ const msg = event.message || "processing...";
34711
+ return formatWithBullet(import_picocolors2.default.dim(msg));
34712
+ }
34713
+ case "text": {
34714
+ return formatWithBullet(event.text);
34715
+ }
34716
+ case "lifecycle": {
34717
+ const icon = event.action === "start" ? ICONS.start : event.action === "complete" ? ICONS.complete : ICONS.skip;
34718
+ const detail = event.detail ? import_picocolors2.default.dim(` (${formatDetailArgs(event.detail)})`) : "";
34719
+ return formatWithBullet(`${icon} ${event.message}${detail}`);
34720
+ }
34721
+ case "info": {
34722
+ const icon = event.level === "error" ? ICONS.error : event.level === "warn" ? ICONS.warn : ICONS.info;
34723
+ const msg = event.level === "error" ? import_picocolors2.default.red(event.message) : event.level === "warn" ? import_picocolors2.default.yellow(event.message) : event.message;
34724
+ return formatWithBullet(`${icon} ${msg}`);
34345
34725
  }
34346
34726
  }
34727
+ }
34728
+ function formatDetailArgs(detail) {
34729
+ const parts = [];
34730
+ for (const [key, value] of Object.entries(detail)) {
34731
+ if (value === undefined || value === null)
34732
+ continue;
34733
+ parts.push(`${key}=${String(value)}`);
34734
+ }
34347
34735
  return parts.join(", ");
34348
34736
  }
34349
- function write(line) {
34350
- process.stderr.write(line + `
34737
+ function needsBlankLineBefore(event) {
34738
+ if (lastEventType === "none")
34739
+ return false;
34740
+ if (event.type === "text" && lastEventType !== "text")
34741
+ return true;
34742
+ if (event.type === "thinking" && lastEventType === "tool_result")
34743
+ return true;
34744
+ if (event.type !== "text" && lastEventType === "text")
34745
+ return true;
34746
+ return false;
34747
+ }
34748
+ function writeStderr(text3) {
34749
+ if (replContext && !replContext.isRunning) {
34750
+ process.stdout.write("\r\x1B[K");
34751
+ process.stderr.write(text3);
34752
+ replContext.rl.prompt(true);
34753
+ } else {
34754
+ process.stderr.write(text3);
34755
+ }
34756
+ }
34757
+ function writeStdout(text3) {
34758
+ process.stdout.write(text3);
34759
+ }
34760
+ function render(event) {
34761
+ if (needsBlankLineBefore(event)) {
34762
+ if (event.type === "text") {
34763
+ writeStdout(`
34764
+ `);
34765
+ } else {
34766
+ writeStderr(`
34767
+ `);
34768
+ }
34769
+ }
34770
+ const formatted = formatEvent(event);
34771
+ if (event.type === "text") {
34772
+ writeStdout(formatted + `
34773
+ `);
34774
+ } else {
34775
+ writeStderr(formatted + `
34776
+ `);
34777
+ }
34778
+ lastEventType = event.type;
34779
+ }
34780
+ function renderEnd() {
34781
+ writeStdout(`
34782
+
34351
34783
  `);
34352
34784
  }
34785
+ function renderRaw(text3) {
34786
+ writeStdout(text3);
34787
+ }
34788
+ function renderRawStderr(text3) {
34789
+ writeStderr(text3);
34790
+ }
34791
+
34792
+ // src/util/activity-log.ts
34793
+ function formatSize(bytes, lines) {
34794
+ const parts = [];
34795
+ if (lines !== undefined)
34796
+ parts.push(`${lines} lines`);
34797
+ if (bytes !== undefined) {
34798
+ if (bytes < 1024)
34799
+ parts.push(`${bytes}b`);
34800
+ else
34801
+ parts.push(`${(bytes / 1024).toFixed(1)}kb`);
34802
+ }
34803
+ return parts.join(", ");
34804
+ }
34353
34805
 
34354
34806
  class ActivityLog {
34355
34807
  worker;
@@ -34357,53 +34809,118 @@ class ActivityLog {
34357
34809
  this.worker = worker;
34358
34810
  }
34359
34811
  toolCall(name17, args) {
34360
- const argsStr = formatArgs(args);
34361
- write(`${formatWorker(this.worker)} ${ICONS.tool_call} ${name17}(${argsStr})`);
34812
+ render({
34813
+ type: "tool_start",
34814
+ worker: this.worker,
34815
+ tool: name17,
34816
+ args
34817
+ });
34362
34818
  }
34363
34819
  toolResult(name17, summary) {
34364
- write(`${formatWorker(this.worker)} ${ICONS.tool_result} ${name17}: ${summary}`);
34820
+ render({
34821
+ type: "tool_result",
34822
+ worker: this.worker,
34823
+ tool: name17,
34824
+ summary
34825
+ });
34365
34826
  }
34366
34827
  toolError(name17, error) {
34367
- write(`${formatWorker(this.worker)} ${ICONS.tool_error} ${name17}: ${truncate(error, 100)}`);
34828
+ render({
34829
+ type: "tool_error",
34830
+ worker: this.worker,
34831
+ tool: name17,
34832
+ error
34833
+ });
34368
34834
  }
34369
34835
  fileRead(path8, lines, bytes) {
34370
- write(`${formatWorker(this.worker)} ${ICONS.tool_result} read: ${formatSize(bytes, lines)}`);
34836
+ render({
34837
+ type: "tool_result",
34838
+ worker: this.worker,
34839
+ tool: "read",
34840
+ summary: formatSize(bytes, lines)
34841
+ });
34371
34842
  }
34372
- searchResult(type, count, query) {
34373
- const queryStr = query ? ` "${truncate(query, 30)}"` : "";
34374
- write(`${formatWorker(this.worker)} ${ICONS.search} ${type}${queryStr} \u2192 ${count} results`);
34843
+ searchResult(type, count, _query) {
34844
+ render({
34845
+ type: "tool_result",
34846
+ worker: this.worker,
34847
+ tool: type,
34848
+ summary: `${count} matches`
34849
+ });
34375
34850
  }
34376
34851
  ltmOperation(op, slug, detail) {
34377
- const icon = op === "archive" ? ICONS.delete : ICONS.update;
34378
- const detailStr = detail ? ` - ${detail}` : "";
34379
- write(`${formatWorker(this.worker)} ${icon} ltm_${op}("${slug}")${detailStr}`);
34852
+ render({
34853
+ type: "tool_result",
34854
+ worker: this.worker,
34855
+ tool: `ltm_${op}`,
34856
+ summary: `"${slug}"${detail ? ` - ${detail}` : ""}`
34857
+ });
34380
34858
  }
34381
34859
  start(description, detail) {
34382
- const detailStr = detail ? ` (${formatArgs(detail)})` : "";
34383
- write(`${formatWorker(this.worker)} ${ICONS.start} ${description}${detailStr}`);
34860
+ render({
34861
+ type: "lifecycle",
34862
+ worker: this.worker,
34863
+ action: "start",
34864
+ message: description,
34865
+ detail
34866
+ });
34384
34867
  }
34385
34868
  complete(summary) {
34386
- write(`${formatWorker(this.worker)} ${ICONS.complete} ${summary}`);
34869
+ render({
34870
+ type: "lifecycle",
34871
+ worker: this.worker,
34872
+ action: "complete",
34873
+ message: summary
34874
+ });
34387
34875
  }
34388
34876
  skip(reason) {
34389
- write(`${formatWorker(this.worker)} ${ICONS.skip} Skipped: ${reason}`);
34877
+ render({
34878
+ type: "lifecycle",
34879
+ worker: this.worker,
34880
+ action: "skip",
34881
+ message: `Skipped: ${reason}`
34882
+ });
34390
34883
  }
34391
34884
  thinking(thought) {
34392
- write(`${formatWorker(this.worker)} ${ICONS.thinking} ${truncate(thought, 150)}`);
34885
+ render({
34886
+ type: "thinking",
34887
+ worker: this.worker,
34888
+ message: thought
34889
+ });
34393
34890
  }
34394
34891
  info(message) {
34395
- write(`${formatWorker(this.worker)} ${ICONS.info} ${message}`);
34892
+ render({
34893
+ type: "info",
34894
+ worker: this.worker,
34895
+ level: "info",
34896
+ message
34897
+ });
34396
34898
  }
34397
34899
  warn(message) {
34398
- write(`${formatWorker(this.worker)} ${ICONS.warn} ${message}`);
34900
+ render({
34901
+ type: "info",
34902
+ worker: this.worker,
34903
+ level: "warn",
34904
+ message
34905
+ });
34399
34906
  }
34400
34907
  error(message) {
34401
- write(`${formatWorker(this.worker)} ${ICONS.error} ${message}`);
34908
+ render({
34909
+ type: "info",
34910
+ worker: this.worker,
34911
+ level: "error",
34912
+ message
34913
+ });
34402
34914
  }
34403
34915
  tokens(before, after, detail) {
34404
34916
  const reduction = Math.round((1 - after / before) * 100);
34405
- const detailStr = detail ? `, ${detail}` : "";
34406
- write(`${formatWorker(this.worker)} ${ICONS.info} ${before.toLocaleString()} \u2192 ${after.toLocaleString()} tokens (${reduction}% reduction${detailStr})`);
34917
+ const msg = `${before.toLocaleString()} \u2192 ${after.toLocaleString()} tokens (${reduction}% reduction${detail ? `, ${detail}` : ""})`;
34918
+ render({
34919
+ type: "info",
34920
+ worker: this.worker,
34921
+ level: "info",
34922
+ message: msg
34923
+ });
34407
34924
  }
34408
34925
  }
34409
34926
  var activity = {
@@ -34772,7 +35289,10 @@ function processMessageForTurn(message, allMessages, currentIdx) {
34772
35289
  const turns = [];
34773
35290
  switch (message.type) {
34774
35291
  case "user":
34775
- turns.push({ role: "user", content: formatWithId(message.id, message.createdAt, message.content) });
35292
+ turns.push({
35293
+ role: "user",
35294
+ content: formatWithId(message.id, message.createdAt, message.content)
35295
+ });
34776
35296
  return { turns, nextIdx: currentIdx + 1 };
34777
35297
  case "assistant": {
34778
35298
  const toolCalls = [];
@@ -34816,7 +35336,10 @@ function processMessageForTurn(message, allMessages, currentIdx) {
34816
35336
  const assistantContent = [];
34817
35337
  const idPrefix = formatIdRange(message.id, lastMessageId, message.createdAt);
34818
35338
  if (message.content) {
34819
- assistantContent.push({ type: "text", text: `${idPrefix} ${message.content}` });
35339
+ assistantContent.push({
35340
+ type: "text",
35341
+ text: `${idPrefix} ${message.content}`
35342
+ });
34820
35343
  } else {
34821
35344
  assistantContent.push({ type: "text", text: idPrefix });
34822
35345
  }
@@ -34833,7 +35356,10 @@ function processMessageForTurn(message, allMessages, currentIdx) {
34833
35356
  };
34834
35357
  turns.push(toolMsg);
34835
35358
  } else {
34836
- turns.push({ role: "assistant", content: formatWithId(message.id, message.createdAt, message.content) });
35359
+ turns.push({
35360
+ role: "assistant",
35361
+ content: formatWithId(message.id, message.createdAt, message.content)
35362
+ });
34837
35363
  }
34838
35364
  return { turns, nextIdx };
34839
35365
  }
@@ -34878,10 +35404,7 @@ function processMessageForTurn(message, allMessages, currentIdx) {
34878
35404
  }
34879
35405
  if (toolCalls.length > 0) {
34880
35406
  const idPrefix = formatIdRange(firstMessageId, lastMessageId, message.createdAt);
34881
- const assistantContent = [
34882
- { type: "text", text: idPrefix },
34883
- ...toolCalls
34884
- ];
35407
+ const assistantContent = [{ type: "text", text: idPrefix }, ...toolCalls];
34885
35408
  const assistantMsg = {
34886
35409
  role: "assistant",
34887
35410
  content: assistantContent
@@ -34983,7 +35506,8 @@ async function runAgentLoop(options) {
34983
35506
  onToolResult,
34984
35507
  onText,
34985
35508
  onToolCall,
34986
- onBeforeTurn
35509
+ onBeforeTurn,
35510
+ onThinking
34987
35511
  } = options;
34988
35512
  if (abortSignal?.aborted) {
34989
35513
  throw new AgentLoopCancelledError;
@@ -35005,9 +35529,14 @@ async function runAgentLoop(options) {
35005
35529
  role: "user",
35006
35530
  content: injectedContent
35007
35531
  });
35008
- log5.info("injected mid-turn user message", { contentLength: injectedContent.length });
35532
+ log5.info("injected mid-turn user message", {
35533
+ contentLength: injectedContent.length
35534
+ });
35009
35535
  }
35010
35536
  turnsUsed++;
35537
+ if (turn > 0) {
35538
+ onThinking?.();
35539
+ }
35011
35540
  const messagesWithCache = addCacheMarkers(messages);
35012
35541
  const response = await Provider.generate({
35013
35542
  model,
@@ -35583,7 +36112,11 @@ function buildGetMessageTool(ctx) {
35583
36112
  contextAfter: exports_external.number().optional().describe("Number of messages to include after (default: 0)")
35584
36113
  }),
35585
36114
  execute: async ({ id, contextBefore, contextAfter }) => {
35586
- activity.reflection.toolCall("get_message", { id, contextBefore, contextAfter });
36115
+ activity.reflection.toolCall("get_message", {
36116
+ id,
36117
+ contextBefore,
36118
+ contextAfter
36119
+ });
35587
36120
  const messages = await storage.temporal.getMessageWithContext({
35588
36121
  id,
35589
36122
  contextBefore: contextBefore ?? 0,
@@ -35683,7 +36216,9 @@ I'll search my memory now. Once I have enough information, I MUST call finish_re
35683
36216
  `;
35684
36217
  }
35685
36218
  async function runReflection(storage, question) {
35686
- activity.reflection.start("Memory research", { question: question.slice(0, 50) });
36219
+ activity.reflection.start("Memory research", {
36220
+ question: question.slice(0, 50)
36221
+ });
35687
36222
  const { tools, getAnswer } = buildReflectionTools({ storage });
35688
36223
  const result = await runSubAgent(storage, {
35689
36224
  name: "reflection",
@@ -35996,7 +36531,11 @@ ${marker17}${m.content}`;
35996
36531
  report: exports_external.string().describe("Your research report. Include: 1) Summary of what you learned, 2) LTM entries created/updated with [[slug]] references, 3) Key sources consulted.")
35997
36532
  }),
35998
36533
  execute: async ({ report }, { toolCallId }) => {
35999
- results.set(toolCallId, { output: "Research complete.", done: true, report });
36534
+ results.set(toolCallId, {
36535
+ output: "Research complete.",
36536
+ done: true,
36537
+ report
36538
+ });
36000
36539
  return "Research complete.";
36001
36540
  }
36002
36541
  });
@@ -44317,8 +44856,8 @@ var Mcp;
44317
44856
  parse: (data) => Mcp.ConfigSchema.parse(data),
44318
44857
  safeParse: (data) => Mcp.ConfigSchema.safeParse(data)
44319
44858
  };
44320
- const CONFIG_FILE_PATH = path8.join(os2.homedir(), ".config", "miriad", "code.json");
44321
- const CONFIG_ENV_VAR = "MIRIAD_MCP_CONFIG";
44859
+ const CONFIG_FILE_PATH = path8.join(os2.homedir(), ".config", "nuum", "mcp.json");
44860
+ const CONFIG_ENV_VAR = "NUUM_MCP_CONFIG";
44322
44861
  async function loadConfig() {
44323
44862
  const envConfig = process.env[CONFIG_ENV_VAR];
44324
44863
  if (envConfig) {
@@ -44384,7 +44923,7 @@ var Mcp;
44384
44923
  status: "disabled"
44385
44924
  };
44386
44925
  }
44387
- const client = new Client({ name: "miriad-code", version: "0.1.0" }, { capabilities: {} });
44926
+ const client = new Client({ name: "nuum", version: "0.1.0" }, { capabilities: {} });
44388
44927
  try {
44389
44928
  const transport = this.createTransport(config2);
44390
44929
  if (transport instanceof StdioClientTransport && transport.stderr) {
@@ -44751,7 +45290,10 @@ Returns: [{ slug, title, path, snippet }, ...] ranked by relevance`,
44751
45290
  const { query, path: path9, limit } = args;
44752
45291
  const results = await ltm.search(query, path9);
44753
45292
  const limited = results.slice(0, limit ?? 10);
44754
- ctx.metadata({ title: `ltm_search("${query}")`, metadata: { operation: "search" } });
45293
+ ctx.metadata({
45294
+ title: `ltm_search("${query}")`,
45295
+ metadata: { operation: "search" }
45296
+ });
44755
45297
  if (limited.length === 0) {
44756
45298
  return {
44757
45299
  title: `ltm_search("${query}")`,
@@ -44789,7 +45331,10 @@ Knowledge entries may contain [[slug]] cross-references - follow these to explor
44789
45331
  const { ltm } = ctx.extra;
44790
45332
  const { slug } = args;
44791
45333
  const entry = await ltm.read(slug);
44792
- ctx.metadata({ title: `ltm_read("${slug}")`, metadata: { entrySlug: slug, operation: "read" } });
45334
+ ctx.metadata({
45335
+ title: `ltm_read("${slug}")`,
45336
+ metadata: { entrySlug: slug, operation: "read" }
45337
+ });
44793
45338
  if (!entry) {
44794
45339
  return {
44795
45340
  title: `ltm_read("${slug}")`,
@@ -44832,7 +45377,10 @@ Example: ltm_create({
44832
45377
  async execute(args, ctx) {
44833
45378
  const { ltm, agentType } = ctx.extra;
44834
45379
  const { slug, parentSlug, title, body, links } = args;
44835
- ctx.metadata({ title: `ltm_create("${slug}")`, metadata: { entrySlug: slug, operation: "create" } });
45380
+ ctx.metadata({
45381
+ title: `ltm_create("${slug}")`,
45382
+ metadata: { entrySlug: slug, operation: "create" }
45383
+ });
44836
45384
  try {
44837
45385
  await ltm.create({
44838
45386
  slug,
@@ -44876,7 +45424,10 @@ On version conflict: Error shows current version. Re-read and retry.`,
44876
45424
  async execute(args, ctx) {
44877
45425
  const { ltm, agentType } = ctx.extra;
44878
45426
  const { slug, newBody, expectedVersion } = args;
44879
- ctx.metadata({ title: `ltm_update("${slug}")`, metadata: { entrySlug: slug, operation: "update" } });
45427
+ ctx.metadata({
45428
+ title: `ltm_update("${slug}")`,
45429
+ metadata: { entrySlug: slug, operation: "update" }
45430
+ });
44880
45431
  try {
44881
45432
  await ltm.update(slug, newBody, expectedVersion, agentType);
44882
45433
  return {
@@ -44926,7 +45477,10 @@ On version conflict: Error shows current version - re-read and retry.`,
44926
45477
  async execute(args, ctx) {
44927
45478
  const { ltm, agentType } = ctx.extra;
44928
45479
  const { slug, oldString, newString, expectedVersion } = args;
44929
- ctx.metadata({ title: `ltm_edit("${slug}")`, metadata: { entrySlug: slug, operation: "edit" } });
45480
+ ctx.metadata({
45481
+ title: `ltm_edit("${slug}")`,
45482
+ metadata: { entrySlug: slug, operation: "edit" }
45483
+ });
44930
45484
  try {
44931
45485
  await ltm.edit(slug, oldString, newString, expectedVersion, agentType);
44932
45486
  return {
@@ -44973,7 +45527,10 @@ Updates path for this entry and all descendants.`,
44973
45527
  async execute(args, ctx) {
44974
45528
  const { ltm, agentType } = ctx.extra;
44975
45529
  const { slug, newParentSlug, expectedVersion } = args;
44976
- ctx.metadata({ title: `ltm_reparent("${slug}")`, metadata: { entrySlug: slug, operation: "reparent" } });
45530
+ ctx.metadata({
45531
+ title: `ltm_reparent("${slug}")`,
45532
+ metadata: { entrySlug: slug, operation: "reparent" }
45533
+ });
44977
45534
  try {
44978
45535
  const updated = await ltm.reparent(slug, newParentSlug, expectedVersion, agentType);
44979
45536
  return {
@@ -45020,7 +45577,10 @@ Updates all paths. Children keep their relative position.`,
45020
45577
  async execute(args, ctx) {
45021
45578
  const { ltm, agentType } = ctx.extra;
45022
45579
  const { slug, newSlug, expectedVersion } = args;
45023
- ctx.metadata({ title: `ltm_rename("${slug}")`, metadata: { entrySlug: slug, operation: "rename" } });
45580
+ ctx.metadata({
45581
+ title: `ltm_rename("${slug}")`,
45582
+ metadata: { entrySlug: slug, operation: "rename" }
45583
+ });
45024
45584
  try {
45025
45585
  const updated = await ltm.rename(slug, newSlug, expectedVersion, agentType);
45026
45586
  return {
@@ -45061,7 +45621,10 @@ Example: ltm_archive({
45061
45621
  async execute(args, ctx) {
45062
45622
  const { ltm } = ctx.extra;
45063
45623
  const { slug, expectedVersion } = args;
45064
- ctx.metadata({ title: `ltm_archive("${slug}")`, metadata: { entrySlug: slug, operation: "archive" } });
45624
+ ctx.metadata({
45625
+ title: `ltm_archive("${slug}")`,
45626
+ metadata: { entrySlug: slug, operation: "archive" }
45627
+ });
45065
45628
  try {
45066
45629
  await ltm.archive(slug, expectedVersion);
45067
45630
  return {
@@ -45105,6 +45668,494 @@ var LTMTools = {
45105
45668
  ...LTMReadOnlyTools,
45106
45669
  ...LTMWriteTools
45107
45670
  };
45671
+ // src/tool/list-tasks.ts
45672
+ function formatElapsed(startTime) {
45673
+ const start = new Date(startTime).getTime();
45674
+ const now2 = Date.now();
45675
+ const elapsed = Math.floor((now2 - start) / 1000);
45676
+ if (elapsed < 60)
45677
+ return `${elapsed}s`;
45678
+ if (elapsed < 3600)
45679
+ return `${Math.floor(elapsed / 60)}m ${elapsed % 60}s`;
45680
+ const hours = Math.floor(elapsed / 3600);
45681
+ const mins = Math.floor(elapsed % 3600 / 60);
45682
+ return `${hours}h ${mins}m`;
45683
+ }
45684
+ function formatTimeUntil(firesAt) {
45685
+ const fires = new Date(firesAt).getTime();
45686
+ const now2 = Date.now();
45687
+ const remaining = Math.floor((fires - now2) / 1000);
45688
+ if (remaining <= 0)
45689
+ return "due now";
45690
+ if (remaining < 60)
45691
+ return `in ${remaining}s`;
45692
+ if (remaining < 3600)
45693
+ return `in ${Math.floor(remaining / 60)}m`;
45694
+ const hours = Math.floor(remaining / 3600);
45695
+ const mins = Math.floor(remaining % 3600 / 60);
45696
+ return `in ${hours}h ${mins}m`;
45697
+ }
45698
+ function formatTask(task) {
45699
+ const elapsed = formatElapsed(task.createdAt);
45700
+ const statusIcon = {
45701
+ running: "\uD83D\uDD04",
45702
+ completed: "\u2705",
45703
+ failed: "\u274C",
45704
+ killed: "\uD83D\uDC80"
45705
+ }[task.status];
45706
+ let line = `${statusIcon} #${task.id.slice(-8)} ${task.type}: "${task.description}" (${task.status}, ${elapsed})`;
45707
+ if (task.error) {
45708
+ line += `
45709
+ Error: ${task.error}`;
45710
+ }
45711
+ return line;
45712
+ }
45713
+ function formatAlarm(alarm) {
45714
+ const timeUntil = formatTimeUntil(alarm.firesAt);
45715
+ return `\u23F0 #${alarm.id.slice(-8)}: "${alarm.note}" (${timeUntil})`;
45716
+ }
45717
+ var DESCRIPTION5 = `List background tasks and alarms.
45718
+
45719
+ Shows:
45720
+ - Running background tasks (research, reflect)
45721
+ - Scheduled alarms (notes to self)
45722
+ - Recent completed/failed tasks (if includeCompleted=true)
45723
+
45724
+ Use this to see what's in progress or scheduled.`;
45725
+ var parameters6 = exports_external.object({
45726
+ includeCompleted: exports_external.boolean().optional().describe("Include completed/failed tasks (default: false, only shows running)")
45727
+ });
45728
+ var ListTasksTool = Tool.define("list_tasks", {
45729
+ description: DESCRIPTION5,
45730
+ parameters: parameters6,
45731
+ async execute({ includeCompleted }, ctx) {
45732
+ const tasksStorage = ctx.extra?.tasks;
45733
+ if (!tasksStorage) {
45734
+ return {
45735
+ output: "Error: Tasks storage not available",
45736
+ title: "List tasks failed",
45737
+ metadata: {
45738
+ runningCount: 0,
45739
+ alarmCount: 0,
45740
+ completedCount: 0
45741
+ }
45742
+ };
45743
+ }
45744
+ const allTasks = await tasksStorage.listTasks({ limit: 20 });
45745
+ const runningTasks = allTasks.filter((t) => t.status === "running");
45746
+ const completedTasks = allTasks.filter((t) => t.status !== "running");
45747
+ const alarms2 = await tasksStorage.listAlarms();
45748
+ const lines = [];
45749
+ if (runningTasks.length > 0) {
45750
+ lines.push("**Running Tasks:**");
45751
+ for (const task of runningTasks) {
45752
+ lines.push(formatTask(task));
45753
+ }
45754
+ }
45755
+ if (alarms2.length > 0) {
45756
+ if (lines.length > 0)
45757
+ lines.push("");
45758
+ lines.push("**Scheduled Alarms:**");
45759
+ for (const alarm of alarms2) {
45760
+ lines.push(formatAlarm(alarm));
45761
+ }
45762
+ }
45763
+ if (includeCompleted && completedTasks.length > 0) {
45764
+ if (lines.length > 0)
45765
+ lines.push("");
45766
+ lines.push("**Recent Completed/Failed:**");
45767
+ for (const task of completedTasks.slice(0, 10)) {
45768
+ lines.push(formatTask(task));
45769
+ }
45770
+ }
45771
+ if (lines.length === 0) {
45772
+ return {
45773
+ output: "No background tasks or alarms.",
45774
+ title: "No tasks",
45775
+ metadata: {
45776
+ runningCount: 0,
45777
+ alarmCount: 0,
45778
+ completedCount: 0
45779
+ }
45780
+ };
45781
+ }
45782
+ return {
45783
+ output: lines.join(`
45784
+ `),
45785
+ title: `${runningTasks.length} running, ${alarms2.length} alarms`,
45786
+ metadata: {
45787
+ runningCount: runningTasks.length,
45788
+ alarmCount: alarms2.length,
45789
+ completedCount: completedTasks.length
45790
+ }
45791
+ };
45792
+ }
45793
+ });
45794
+ // src/tool/set-alarm.ts
45795
+ function parseDelay(delay2) {
45796
+ const match = delay2.match(/^(\d+(?:\.\d+)?)\s*(s|sec|second|seconds|m|min|minute|minutes|h|hr|hour|hours)$/i);
45797
+ if (!match)
45798
+ return null;
45799
+ const value = parseFloat(match[1]);
45800
+ const unit = match[2].toLowerCase();
45801
+ switch (unit) {
45802
+ case "s":
45803
+ case "sec":
45804
+ case "second":
45805
+ case "seconds":
45806
+ return value * 1000;
45807
+ case "m":
45808
+ case "min":
45809
+ case "minute":
45810
+ case "minutes":
45811
+ return value * 60 * 1000;
45812
+ case "h":
45813
+ case "hr":
45814
+ case "hour":
45815
+ case "hours":
45816
+ return value * 60 * 60 * 1000;
45817
+ default:
45818
+ return null;
45819
+ }
45820
+ }
45821
+ var DESCRIPTION6 = `Schedule a future reminder (alarm).
45822
+
45823
+ When the alarm fires, you'll receive a message with your note.
45824
+ Use this to:
45825
+ - Check back on something later ("check if deploy succeeded")
45826
+ - Set a reminder for a task
45827
+ - Schedule periodic check-ins
45828
+
45829
+ Examples:
45830
+ - set_alarm({ delay: "5m", note: "check deployment status" })
45831
+ - set_alarm({ delay: "1h", note: "follow up on PR review" })
45832
+ - set_alarm({ delay: "30s", note: "verify test results" })`;
45833
+ var parameters7 = exports_external.object({
45834
+ delay: exports_external.string().describe('How long until the alarm fires (e.g., "5m", "1h", "30s")'),
45835
+ note: exports_external.string().describe("The reminder message you'll receive when the alarm fires")
45836
+ });
45837
+ var SetAlarmTool = Tool.define("set_alarm", {
45838
+ description: DESCRIPTION6,
45839
+ parameters: parameters7,
45840
+ async execute({ delay: delay2, note }, ctx) {
45841
+ const tasksStorage = ctx.extra?.tasks;
45842
+ if (!tasksStorage) {
45843
+ return {
45844
+ output: "Error: Tasks storage not available",
45845
+ title: "Set alarm failed",
45846
+ metadata: {
45847
+ alarmId: "",
45848
+ firesAt: "",
45849
+ delayMs: 0
45850
+ }
45851
+ };
45852
+ }
45853
+ const delayMs = parseDelay(delay2);
45854
+ if (delayMs === null) {
45855
+ return {
45856
+ output: `Invalid delay format: "${delay2}". Use formats like "5m", "1h", "30s".`,
45857
+ title: "Invalid delay",
45858
+ metadata: {
45859
+ alarmId: "",
45860
+ firesAt: "",
45861
+ delayMs: 0
45862
+ }
45863
+ };
45864
+ }
45865
+ const firesAt = new Date(Date.now() + delayMs).toISOString();
45866
+ const alarmId = await tasksStorage.createAlarm({
45867
+ firesAt,
45868
+ note
45869
+ });
45870
+ const displayDelay = delayMs >= 3600000 ? `${Math.round(delayMs / 3600000 * 10) / 10}h` : delayMs >= 60000 ? `${Math.round(delayMs / 60000)}m` : `${Math.round(delayMs / 1000)}s`;
45871
+ return {
45872
+ output: `\u23F0 Alarm set for ${displayDelay} from now.
45873
+ Note: "${note}"
45874
+ Fires at: ${firesAt}`,
45875
+ title: `Alarm in ${displayDelay}`,
45876
+ metadata: {
45877
+ alarmId,
45878
+ firesAt,
45879
+ delayMs
45880
+ }
45881
+ };
45882
+ }
45883
+ });
45884
+ // src/tool/background-research.ts
45885
+ var log9 = Log.create({ service: "background-research" });
45886
+ var DESCRIPTION7 = `Start a research task in the background.
45887
+
45888
+ This spawns a research sub-agent that runs asynchronously while you continue working.
45889
+ When the research completes, you'll receive the results automatically.
45890
+
45891
+ Use this when:
45892
+ - You want to research something without blocking your current work
45893
+ - The research might take a while and you have other things to do
45894
+ - You want to parallelize multiple research tasks
45895
+
45896
+ The research agent can:
45897
+ - Search and update your long-term knowledge base
45898
+ - Search the web and fetch documentation
45899
+ - Search your conversation history
45900
+ - Read files in the codebase
45901
+
45902
+ Example: background_research({ topic: "How does Stripe's payment intent API work?" })`;
45903
+ var parameters8 = exports_external.object({
45904
+ topic: exports_external.string().describe("The topic to research. Be specific about what you want to learn.")
45905
+ });
45906
+ var BackgroundResearchTool = Tool.define("background_research", {
45907
+ description: DESCRIPTION7,
45908
+ parameters: parameters8,
45909
+ async execute({ topic }, ctx) {
45910
+ const storage = ctx.extra?.storage;
45911
+ if (!storage) {
45912
+ return {
45913
+ output: "Error: Storage not available for background research",
45914
+ title: "Background research failed",
45915
+ metadata: {
45916
+ taskId: "",
45917
+ topic
45918
+ }
45919
+ };
45920
+ }
45921
+ const MAX_CONCURRENT_TASKS = 3;
45922
+ const runningTasks = await storage.tasks.listTasks({ status: "running" });
45923
+ if (runningTasks.length >= MAX_CONCURRENT_TASKS) {
45924
+ return {
45925
+ output: `Too many background tasks running (${runningTasks.length}/${MAX_CONCURRENT_TASKS}). Wait for some to complete or cancel them with cancel_task.`,
45926
+ title: "Too many tasks",
45927
+ metadata: {
45928
+ taskId: "",
45929
+ topic
45930
+ }
45931
+ };
45932
+ }
45933
+ const taskId = await storage.tasks.createTask({
45934
+ type: "research",
45935
+ description: topic.slice(0, 100) + (topic.length > 100 ? "..." : "")
45936
+ });
45937
+ log9.info("spawning background research", {
45938
+ taskId,
45939
+ topic: topic.slice(0, 50)
45940
+ });
45941
+ runBackgroundResearch(storage, taskId, topic).catch((error2) => {
45942
+ log9.error("background research failed", { taskId, error: error2 });
45943
+ });
45944
+ return {
45945
+ output: `\uD83D\uDD2C Research started in background.
45946
+ Task ID: ${taskId}
45947
+ Topic: "${topic}"
45948
+
45949
+ You'll receive the results when the research completes. Use list_tasks to check status.`,
45950
+ title: `Research started: ${topic.slice(0, 30)}...`,
45951
+ metadata: {
45952
+ taskId,
45953
+ topic
45954
+ }
45955
+ };
45956
+ }
45957
+ });
45958
+ async function runBackgroundResearch(storage, taskId, topic) {
45959
+ try {
45960
+ const result = await runResearch(storage, topic);
45961
+ const entriesCreated = result.entriesCreated.length;
45962
+ const entriesUpdated = result.entriesUpdated.length;
45963
+ const report = [
45964
+ `## Research Complete: ${topic}`,
45965
+ "",
45966
+ result.report,
45967
+ "",
45968
+ `---`,
45969
+ `*Research used ${result.turnsUsed} turns, ${result.usage.inputTokens} input / ${result.usage.outputTokens} output tokens*`,
45970
+ entriesCreated > 0 ? `*Created ${entriesCreated} LTM entries: ${result.entriesCreated.join(", ")}*` : "",
45971
+ entriesUpdated > 0 ? `*Updated ${entriesUpdated} LTM entries: ${result.entriesUpdated.join(", ")}*` : ""
45972
+ ].filter(Boolean).join(`
45973
+ `);
45974
+ await storage.tasks.completeTask(taskId, {
45975
+ report: result.report,
45976
+ entriesCreated: result.entriesCreated,
45977
+ entriesUpdated: result.entriesUpdated,
45978
+ turnsUsed: result.turnsUsed,
45979
+ usage: result.usage
45980
+ });
45981
+ await storage.tasks.queueResult(taskId, report);
45982
+ log9.info("background research completed", {
45983
+ taskId,
45984
+ turnsUsed: result.turnsUsed,
45985
+ entriesCreated,
45986
+ entriesUpdated
45987
+ });
45988
+ } catch (error2) {
45989
+ const errorMsg = error2 instanceof Error ? error2.message : String(error2);
45990
+ await storage.tasks.failTask(taskId, errorMsg);
45991
+ await storage.tasks.queueResult(taskId, `## Research Failed: ${topic}
45992
+
45993
+ Error: ${errorMsg}`);
45994
+ log9.error("background research failed", { taskId, error: errorMsg });
45995
+ }
45996
+ }
45997
+ // src/tool/background-reflect.ts
45998
+ var log10 = Log.create({ service: "background-reflect" });
45999
+ var DESCRIPTION8 = `Start a reflection task in the background.
46000
+
46001
+ This spawns a reflection sub-agent that runs asynchronously while you continue working.
46002
+ When the reflection completes, you'll receive the answer automatically.
46003
+
46004
+ Use this when:
46005
+ - You want to search your memory without blocking your current work
46006
+ - The question might require extensive searching
46007
+ - You want to parallelize multiple reflection tasks
46008
+
46009
+ The reflection agent can:
46010
+ - Search your conversation history with full-text search
46011
+ - Retrieve specific messages with surrounding context
46012
+ - Search and read your long-term knowledge base
46013
+
46014
+ Example: background_reflect({ question: "What did we decide about the API authentication approach?" })`;
46015
+ var parameters9 = exports_external.object({
46016
+ question: exports_external.string().describe("The question to answer or research task to complete. Be specific about what you're looking for.")
46017
+ });
46018
+ var BackgroundReflectTool = Tool.define("background_reflect", {
46019
+ description: DESCRIPTION8,
46020
+ parameters: parameters9,
46021
+ async execute({ question }, ctx) {
46022
+ const storage = ctx.extra?.storage;
46023
+ if (!storage) {
46024
+ return {
46025
+ output: "Error: Storage not available for background reflection",
46026
+ title: "Background reflection failed",
46027
+ metadata: {
46028
+ taskId: "",
46029
+ question
46030
+ }
46031
+ };
46032
+ }
46033
+ const MAX_CONCURRENT_TASKS = 3;
46034
+ const runningTasks = await storage.tasks.listTasks({ status: "running" });
46035
+ if (runningTasks.length >= MAX_CONCURRENT_TASKS) {
46036
+ return {
46037
+ output: `Too many background tasks running (${runningTasks.length}/${MAX_CONCURRENT_TASKS}). Wait for some to complete or cancel them with cancel_task.`,
46038
+ title: "Too many tasks",
46039
+ metadata: {
46040
+ taskId: "",
46041
+ question
46042
+ }
46043
+ };
46044
+ }
46045
+ const taskId = await storage.tasks.createTask({
46046
+ type: "reflect",
46047
+ description: question.slice(0, 100) + (question.length > 100 ? "..." : "")
46048
+ });
46049
+ log10.info("spawning background reflection", {
46050
+ taskId,
46051
+ question: question.slice(0, 50)
46052
+ });
46053
+ runBackgroundReflection(storage, taskId, question).catch((error2) => {
46054
+ log10.error("background reflection failed", { taskId, error: error2 });
46055
+ });
46056
+ return {
46057
+ output: `\uD83D\uDD0D Reflection started in background.
46058
+ Task ID: ${taskId}
46059
+ Question: "${question}"
46060
+
46061
+ You'll receive the answer when the reflection completes. Use list_tasks to check status.`,
46062
+ title: `Reflection started: ${question.slice(0, 30)}...`,
46063
+ metadata: {
46064
+ taskId,
46065
+ question
46066
+ }
46067
+ };
46068
+ }
46069
+ });
46070
+ async function runBackgroundReflection(storage, taskId, question) {
46071
+ try {
46072
+ const result = await runReflection(storage, question);
46073
+ const report = [
46074
+ `## Reflection Complete: ${question}`,
46075
+ "",
46076
+ result.answer,
46077
+ "",
46078
+ `---`,
46079
+ `*Reflection used ${result.turnsUsed} turns, ${result.usage.inputTokens} input / ${result.usage.outputTokens} output tokens*`
46080
+ ].join(`
46081
+ `);
46082
+ await storage.tasks.completeTask(taskId, {
46083
+ answer: result.answer,
46084
+ turnsUsed: result.turnsUsed,
46085
+ usage: result.usage
46086
+ });
46087
+ await storage.tasks.queueResult(taskId, report);
46088
+ log10.info("background reflection completed", {
46089
+ taskId,
46090
+ turnsUsed: result.turnsUsed
46091
+ });
46092
+ } catch (error2) {
46093
+ const errorMsg = error2 instanceof Error ? error2.message : String(error2);
46094
+ await storage.tasks.failTask(taskId, errorMsg);
46095
+ await storage.tasks.queueResult(taskId, `## Reflection Failed: ${question}
46096
+
46097
+ Error: ${errorMsg}`);
46098
+ log10.error("background reflection failed", { taskId, error: errorMsg });
46099
+ }
46100
+ }
46101
+ // src/tool/cancel-task.ts
46102
+ var DESCRIPTION9 = `Cancel a running background task.
46103
+
46104
+ Note: This marks the task as cancelled, but cannot stop work already in progress.
46105
+ The task may still complete, but its results will be discarded.
46106
+
46107
+ Use list_tasks to see running tasks and their IDs.`;
46108
+ var parameters10 = exports_external.object({
46109
+ taskId: exports_external.string().describe("The task ID to cancel (from list_tasks)")
46110
+ });
46111
+ var CancelTaskTool = Tool.define("cancel_task", {
46112
+ description: DESCRIPTION9,
46113
+ parameters: parameters10,
46114
+ async execute({ taskId }, ctx) {
46115
+ const tasksStorage = ctx.extra?.tasks;
46116
+ if (!tasksStorage) {
46117
+ return {
46118
+ output: "Error: Tasks storage not available",
46119
+ title: "Cancel task failed",
46120
+ metadata: {
46121
+ taskId,
46122
+ success: false
46123
+ }
46124
+ };
46125
+ }
46126
+ const task = await tasksStorage.getTask(taskId);
46127
+ if (!task) {
46128
+ return {
46129
+ output: `Task not found: ${taskId}`,
46130
+ title: "Task not found",
46131
+ metadata: {
46132
+ taskId,
46133
+ success: false
46134
+ }
46135
+ };
46136
+ }
46137
+ if (task.status !== "running") {
46138
+ return {
46139
+ output: `Task ${taskId} is not running (status: ${task.status})`,
46140
+ title: "Cannot cancel",
46141
+ metadata: {
46142
+ taskId,
46143
+ success: false
46144
+ }
46145
+ };
46146
+ }
46147
+ await tasksStorage.failTask(taskId, "Cancelled by user");
46148
+ return {
46149
+ output: `Task ${taskId} marked as cancelled.
46150
+ Note: The task may still complete in the background, but results will be discarded.`,
46151
+ title: "Task cancelled",
46152
+ metadata: {
46153
+ taskId,
46154
+ success: true
46155
+ }
46156
+ };
46157
+ }
46158
+ });
45108
46159
  // src/ltm/tools.ts
45109
46160
  var AGENT_TYPE2 = "ltm-consolidate";
45110
46161
  function buildConsolidationTools(storage) {
@@ -45134,7 +46185,10 @@ function buildConsolidationTools(storage) {
45134
46185
  parameters: LTMReadTool.definition.parameters,
45135
46186
  execute: async (args, { toolCallId }) => {
45136
46187
  const toolResult = await LTMReadTool.definition.execute(args, createLTMContext2(toolCallId));
45137
- const result = { output: toolResult.output, done: false };
46188
+ const result = {
46189
+ output: toolResult.output,
46190
+ done: false
46191
+ };
45138
46192
  results.set(toolCallId, result);
45139
46193
  return result.output;
45140
46194
  }
@@ -45144,7 +46198,10 @@ function buildConsolidationTools(storage) {
45144
46198
  parameters: LTMGlobTool.definition.parameters,
45145
46199
  execute: async (args, { toolCallId }) => {
45146
46200
  const toolResult = await LTMGlobTool.definition.execute(args, createLTMContext2(toolCallId));
45147
- const result = { output: toolResult.output, done: false };
46201
+ const result = {
46202
+ output: toolResult.output,
46203
+ done: false
46204
+ };
45148
46205
  results.set(toolCallId, result);
45149
46206
  return result.output;
45150
46207
  }
@@ -45156,7 +46213,10 @@ function buildConsolidationTools(storage) {
45156
46213
  const toolResult = await LTMSearchTool.definition.execute(args, createLTMContext2(toolCallId));
45157
46214
  const matchCount = (toolResult.output.match(/^- \*\*/gm) || []).length;
45158
46215
  activity.ltmCurator.searchResult("ltm_search", matchCount, args.query);
45159
- const result = { output: toolResult.output, done: false };
46216
+ const result = {
46217
+ output: toolResult.output,
46218
+ done: false
46219
+ };
45160
46220
  results.set(toolCallId, result);
45161
46221
  return result.output;
45162
46222
  }
@@ -45281,7 +46341,10 @@ function buildConsolidationTools(storage) {
45281
46341
  parameters: ReadTool.definition.parameters,
45282
46342
  execute: async (args, { toolCallId }) => {
45283
46343
  const toolResult = await ReadTool.definition.execute(args, createBaseContext(toolCallId));
45284
- const result = { output: toolResult.output, done: false };
46344
+ const result = {
46345
+ output: toolResult.output,
46346
+ done: false
46347
+ };
45285
46348
  results.set(toolCallId, result);
45286
46349
  return result.output;
45287
46350
  }
@@ -45291,7 +46354,10 @@ function buildConsolidationTools(storage) {
45291
46354
  parameters: GlobTool.definition.parameters,
45292
46355
  execute: async (args, { toolCallId }) => {
45293
46356
  const toolResult = await GlobTool.definition.execute(args, createBaseContext(toolCallId));
45294
- const result = { output: toolResult.output, done: false };
46357
+ const result = {
46358
+ output: toolResult.output,
46359
+ done: false
46360
+ };
45295
46361
  results.set(toolCallId, result);
45296
46362
  return result.output;
45297
46363
  }
@@ -45301,7 +46367,10 @@ function buildConsolidationTools(storage) {
45301
46367
  parameters: GrepTool.definition.parameters,
45302
46368
  execute: async (args, { toolCallId }) => {
45303
46369
  const toolResult = await GrepTool.definition.execute(args, createBaseContext(toolCallId));
45304
- const result = { output: toolResult.output, done: false };
46370
+ const result = {
46371
+ output: toolResult.output,
46372
+ done: false
46373
+ };
45305
46374
  results.set(toolCallId, result);
45306
46375
  return result.output;
45307
46376
  }
@@ -45311,7 +46380,10 @@ function buildConsolidationTools(storage) {
45311
46380
  parameters: WebSearchTool.definition.parameters,
45312
46381
  execute: async (args, { toolCallId }) => {
45313
46382
  const toolResult = await WebSearchTool.definition.execute(args, createBaseContext(toolCallId));
45314
- const result = { output: toolResult.output, done: false };
46383
+ const result = {
46384
+ output: toolResult.output,
46385
+ done: false
46386
+ };
45315
46387
  results.set(toolCallId, result);
45316
46388
  return result.output;
45317
46389
  }
@@ -45321,7 +46393,10 @@ function buildConsolidationTools(storage) {
45321
46393
  parameters: WebFetchTool.definition.parameters,
45322
46394
  execute: async (args, { toolCallId }) => {
45323
46395
  const toolResult = await WebFetchTool.definition.execute(args, createBaseContext(toolCallId));
45324
- const result = { output: toolResult.output, done: false };
46396
+ const result = {
46397
+ output: toolResult.output,
46398
+ done: false
46399
+ };
45325
46400
  results.set(toolCallId, result);
45326
46401
  return result.output;
45327
46402
  }
@@ -45332,7 +46407,11 @@ function buildConsolidationTools(storage) {
45332
46407
  summary: exports_external.string().describe("A note to your future self: what did you capture and why does it matter? Reference entries with [[slug]] syntax. Example: 'Captured the bloom filter insights in [[bloom-filter-overview]]. Archived X system workarounds since it's decommissioned.'")
45333
46408
  }),
45334
46409
  execute: async ({ summary }, { toolCallId }) => {
45335
- const result = { output: "Curation complete", done: true, summary };
46410
+ const result = {
46411
+ output: "Curation complete",
46412
+ done: true,
46413
+ summary
46414
+ };
45336
46415
  results.set(toolCallId, result);
45337
46416
  return result.output;
45338
46417
  }
@@ -45344,7 +46423,7 @@ function buildConsolidationTools(storage) {
45344
46423
  }
45345
46424
 
45346
46425
  // src/ltm/consolidation.ts
45347
- var log9 = Log.create({ service: "consolidation-agent" });
46426
+ var log11 = Log.create({ service: "consolidation-agent" });
45348
46427
  var MAX_CONSOLIDATION_TURNS = 20;
45349
46428
  function isConversationNoteworthy(messages) {
45350
46429
  if (messages.length < 5) {
@@ -45499,14 +46578,14 @@ async function runConsolidation(storage, messages) {
45499
46578
  usage: { inputTokens: 0, outputTokens: 0 }
45500
46579
  };
45501
46580
  if (!isConversationNoteworthy(messages)) {
45502
- log9.info("skipping consolidation - conversation not noteworthy", {
46581
+ log11.info("skipping consolidation - conversation not noteworthy", {
45503
46582
  messageCount: messages.length
45504
46583
  });
45505
46584
  result.summary = "Skipped - conversation not noteworthy";
45506
46585
  return result;
45507
46586
  }
45508
46587
  result.ran = true;
45509
- log9.info("starting consolidation", { messageCount: messages.length });
46588
+ log11.info("starting consolidation", { messageCount: messages.length });
45510
46589
  const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000).toISOString();
45511
46590
  const allEntries = await storage.ltm.glob("/**");
45512
46591
  const recentlyUpdated = allEntries.filter((e) => e.updatedAt > oneHourAgo && e.slug !== "identity" && e.slug !== "behavior");
@@ -45554,7 +46633,7 @@ async function runConsolidation(storage, messages) {
45554
46633
  if (!result.summary) {
45555
46634
  result.summary = "Consolidation ended without explicit finish";
45556
46635
  }
45557
- log9.info("consolidation complete", {
46636
+ log11.info("consolidation complete", {
45558
46637
  entriesCreated: result.entriesCreated,
45559
46638
  entriesUpdated: result.entriesUpdated,
45560
46639
  entriesArchived: result.entriesArchived,
@@ -45673,13 +46752,13 @@ async function runDistillation(storage, threshold, target, force) {
45673
46752
  }
45674
46753
 
45675
46754
  // src/agent/index.ts
45676
- var log10 = Log.create({ service: "agent" });
46755
+ var log12 = Log.create({ service: "agent" });
45677
46756
  var MAX_TURNS = 200;
45678
46757
  async function surfaceBackgroundReports(storage) {
45679
46758
  const reports = await storage.background.getUnsurfaced();
45680
46759
  if (reports.length === 0)
45681
46760
  return;
45682
- log10.info("surfacing background reports", { count: reports.length });
46761
+ log12.info("surfacing background reports", { count: reports.length });
45683
46762
  for (const report of reports) {
45684
46763
  const toolCallId = Identifier.ascending("toolcall");
45685
46764
  await storage.temporal.appendMessage({
@@ -45849,6 +46928,16 @@ function createToolContextFactory(storage, sessionId, messageId, abortSignal) {
45849
46928
  storage
45850
46929
  };
45851
46930
  return ctx;
46931
+ },
46932
+ createListTasksContext(callId) {
46933
+ const ctx = Tool.createContext({
46934
+ ...baseContext,
46935
+ callID: callId
46936
+ });
46937
+ ctx.extra = {
46938
+ tasks: storage.tasks
46939
+ };
46940
+ return ctx;
45852
46941
  }
45853
46942
  };
45854
46943
  }
@@ -45961,15 +47050,30 @@ function buildTools(storage, sessionId, messageId, abortSignal) {
45961
47050
  parameters: LTMReadTool.definition.parameters,
45962
47051
  execute: async (args, { toolCallId }) => safeExecute("ltm_read", () => LTMReadTool.definition.execute(args, factory.createLTMContext(toolCallId)))
45963
47052
  });
45964
- tools.reflect = tool({
45965
- description: ReflectTool.definition.description,
45966
- parameters: ReflectTool.definition.parameters,
45967
- execute: async (args, { toolCallId }) => safeExecute("reflect", () => ReflectTool.definition.execute(args, factory.createReflectContext(toolCallId)))
47053
+ tools.list_tasks = tool({
47054
+ description: ListTasksTool.definition.description,
47055
+ parameters: ListTasksTool.definition.parameters,
47056
+ execute: async (args, { toolCallId }) => safeExecute("list_tasks", () => ListTasksTool.definition.execute(args, factory.createListTasksContext(toolCallId)))
47057
+ });
47058
+ tools.set_alarm = tool({
47059
+ description: SetAlarmTool.definition.description,
47060
+ parameters: SetAlarmTool.definition.parameters,
47061
+ execute: async (args, { toolCallId }) => safeExecute("set_alarm", () => SetAlarmTool.definition.execute(args, factory.createListTasksContext(toolCallId)))
45968
47062
  });
45969
- tools.research = tool({
45970
- description: ResearchTool.definition.description,
45971
- parameters: ResearchTool.definition.parameters,
45972
- execute: async (args, { toolCallId }) => safeExecute("research", () => ResearchTool.definition.execute(args, factory.createResearchContext(toolCallId)))
47063
+ tools.background_research = tool({
47064
+ description: BackgroundResearchTool.definition.description,
47065
+ parameters: BackgroundResearchTool.definition.parameters,
47066
+ execute: async (args, { toolCallId }) => safeExecute("background_research", () => BackgroundResearchTool.definition.execute(args, factory.createResearchContext(toolCallId)))
47067
+ });
47068
+ tools.background_reflect = tool({
47069
+ description: BackgroundReflectTool.definition.description,
47070
+ parameters: BackgroundReflectTool.definition.parameters,
47071
+ execute: async (args, { toolCallId }) => safeExecute("background_reflect", () => BackgroundReflectTool.definition.execute(args, factory.createReflectContext(toolCallId)))
47072
+ });
47073
+ tools.cancel_task = tool({
47074
+ description: CancelTaskTool.definition.description,
47075
+ parameters: CancelTaskTool.definition.parameters,
47076
+ execute: async (args, { toolCallId }) => safeExecute("cancel_task", () => CancelTaskTool.definition.execute(args, factory.createListTasksContext(toolCallId)))
45973
47077
  });
45974
47078
  return tools;
45975
47079
  }
@@ -45979,14 +47083,14 @@ async function initializeMcp() {
45979
47083
  if (didInitialize) {
45980
47084
  const status = Mcp.getStatus();
45981
47085
  if (status.length > 0) {
45982
- log10.info("MCP servers connected", {
47086
+ log12.info("MCP servers connected", {
45983
47087
  servers: status.map((s) => `${s.name} (${s.toolCount} tools)`)
45984
47088
  });
45985
47089
  }
45986
47090
  }
45987
47091
  return didInitialize;
45988
47092
  } catch (error2) {
45989
- log10.error("Failed to initialize MCP", { error: error2 });
47093
+ log12.error("Failed to initialize MCP", { error: error2 });
45990
47094
  return false;
45991
47095
  }
45992
47096
  }
@@ -46000,11 +47104,14 @@ async function runAgent(prompt, options) {
46000
47104
  const hardLimit = config2.tokenBudgets.compactionHardLimit;
46001
47105
  const tokensBefore = await getEffectiveViewTokens(storage.temporal);
46002
47106
  if (tokensBefore > hardLimit) {
46003
- log10.error("context overflow - refusing turn", { tokens: tokensBefore, hardLimit });
46004
- throw new Error(`Context overflow: ${tokensBefore} tokens exceeds hard limit of ${hardLimit}. ` + `Run 'miriad-code --compact' to reduce context size before continuing.`);
47107
+ log12.error("context overflow - refusing turn", {
47108
+ tokens: tokensBefore,
47109
+ hardLimit
47110
+ });
47111
+ throw new Error(`Context overflow: ${tokensBefore} tokens exceeds hard limit of ${hardLimit}. ` + `Run 'nuum --compact' to reduce context size before continuing.`);
46005
47112
  }
46006
47113
  if (tokensBefore > softLimit) {
46007
- log10.warn("approaching token limit, running compaction before turn", {
47114
+ log12.warn("approaching token limit, running compaction before turn", {
46008
47115
  tokens: tokensBefore,
46009
47116
  softLimit,
46010
47117
  target: config2.tokenBudgets.compactionTarget
@@ -46012,13 +47119,16 @@ async function runAgent(prompt, options) {
46012
47119
  await runMemoryCuration(storage, { force: true });
46013
47120
  const tokensAfter = await getEffectiveViewTokens(storage.temporal);
46014
47121
  if (tokensAfter > softLimit) {
46015
- log10.warn("compaction didn't reduce tokens below soft limit", {
47122
+ log12.warn("compaction didn't reduce tokens below soft limit", {
46016
47123
  before: tokensBefore,
46017
47124
  after: tokensAfter,
46018
47125
  softLimit
46019
47126
  });
46020
47127
  } else {
46021
- log10.info("pre-turn compaction successful", { before: tokensBefore, after: tokensAfter });
47128
+ log12.info("pre-turn compaction successful", {
47129
+ before: tokensBefore,
47130
+ after: tokensAfter
47131
+ });
46022
47132
  }
46023
47133
  }
46024
47134
  const model = Provider.getModelForTier("reasoning");
@@ -46033,7 +47143,7 @@ async function runAgent(prompt, options) {
46033
47143
  createdAt: new Date().toISOString()
46034
47144
  });
46035
47145
  } catch (error2) {
46036
- log10.error("failed to persist user message", {
47146
+ log12.error("failed to persist user message", {
46037
47147
  messageId: userMessageId,
46038
47148
  error: error2 instanceof Error ? error2.message : String(error2)
46039
47149
  });
@@ -46067,7 +47177,7 @@ async function runAgent(prompt, options) {
46067
47177
  });
46068
47178
  lastLoggedText = text3;
46069
47179
  } catch (error2) {
46070
- log10.error("failed to persist assistant message", {
47180
+ log12.error("failed to persist assistant message", {
46071
47181
  messageId: assistantMessageId,
46072
47182
  error: error2 instanceof Error ? error2.message : String(error2)
46073
47183
  });
@@ -46088,7 +47198,7 @@ async function runAgent(prompt, options) {
46088
47198
  createdAt: new Date().toISOString()
46089
47199
  });
46090
47200
  } catch (error2) {
46091
- log10.error("failed to persist tool call", {
47201
+ log12.error("failed to persist tool call", {
46092
47202
  messageId: toolCallMsgId,
46093
47203
  toolName,
46094
47204
  toolCallId,
@@ -46117,7 +47227,7 @@ async function runAgent(prompt, options) {
46117
47227
  createdAt: new Date().toISOString()
46118
47228
  });
46119
47229
  } catch (error2) {
46120
- log10.error("failed to persist tool result", {
47230
+ log12.error("failed to persist tool result", {
46121
47231
  messageId: toolResultMsgId,
46122
47232
  toolName,
46123
47233
  toolCallId,
@@ -46145,7 +47255,7 @@ async function runAgent(prompt, options) {
46145
47255
  createdAt: new Date().toISOString()
46146
47256
  });
46147
47257
  } catch (error2) {
46148
- log10.error("failed to persist injected user message", {
47258
+ log12.error("failed to persist injected user message", {
46149
47259
  messageId: injectedMsgId,
46150
47260
  error: error2 instanceof Error ? error2.message : String(error2)
46151
47261
  });
@@ -46155,6 +47265,9 @@ async function runAgent(prompt, options) {
46155
47265
  return content;
46156
47266
  }
46157
47267
  return null;
47268
+ },
47269
+ onThinking: () => {
47270
+ activity.mainAgent.thinking("processing tool results...");
46158
47271
  }
46159
47272
  });
46160
47273
  onEvent?.({ type: "done", content: result.finalText });
@@ -46177,7 +47290,9 @@ async function runAgent(prompt, options) {
46177
47290
  }
46178
47291
  }
46179
47292
  }).catch((error2) => {
46180
- log10.error("background memory curation failed", { error: error2 instanceof Error ? error2.message : String(error2) });
47293
+ log12.error("background memory curation failed", {
47294
+ error: error2 instanceof Error ? error2.message : String(error2)
47295
+ });
46181
47296
  });
46182
47297
  return {
46183
47298
  response: result.finalText,
@@ -46188,11 +47303,56 @@ async function runAgent(prompt, options) {
46188
47303
  };
46189
47304
  }
46190
47305
 
47306
+ // src/util/colors.ts
47307
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
47308
+ var styles = {
47309
+ header: (s) => import_picocolors3.default.bold(import_picocolors3.default.cyan(s)),
47310
+ subheader: (s) => import_picocolors3.default.cyan(s),
47311
+ label: (s) => import_picocolors3.default.dim(s),
47312
+ separator: (s) => import_picocolors3.default.dim(import_picocolors3.default.gray(s)),
47313
+ success: (s) => import_picocolors3.default.green(s),
47314
+ warning: (s) => import_picocolors3.default.yellow(s),
47315
+ error: (s) => import_picocolors3.default.red(s),
47316
+ code: (s) => import_picocolors3.default.yellowBright(s),
47317
+ path: (s) => import_picocolors3.default.redBright(s),
47318
+ command: (s) => import_picocolors3.default.yellow(s),
47319
+ tool: (s) => import_picocolors3.default.whiteBright(s),
47320
+ user: (s) => import_picocolors3.default.blue(s),
47321
+ assistant: (s) => import_picocolors3.default.green(s),
47322
+ timestamp: (s) => import_picocolors3.default.gray(s),
47323
+ number: (s) => import_picocolors3.default.yellow(s),
47324
+ arrow: (s) => import_picocolors3.default.dim(s)
47325
+ };
47326
+ function colorPercent(value, total) {
47327
+ const pct = value / total * 100;
47328
+ const formatted = pct.toFixed(1) + "%";
47329
+ if (pct < 50)
47330
+ return import_picocolors3.default.green(formatted);
47331
+ if (pct < 80)
47332
+ return import_picocolors3.default.yellow(formatted);
47333
+ return import_picocolors3.default.red(formatted);
47334
+ }
47335
+ function progressBar(complete, total, width = 20) {
47336
+ const filled = Math.round(complete / total * width);
47337
+ const empty = width - filled;
47338
+ return import_picocolors3.default.green("\u2588".repeat(filled)) + import_picocolors3.default.dim("\u2591".repeat(empty));
47339
+ }
47340
+
46191
47341
  // src/cli/verbose.ts
46192
- var SEPARATOR = "\u2500".repeat(70);
47342
+ var SEPARATOR_WIDTH = 70;
46193
47343
  function formatTimestamp2() {
46194
47344
  return new Date().toISOString().slice(11, 23);
46195
47345
  }
47346
+ function separator(title) {
47347
+ const line = styles.separator("\u2500".repeat(SEPARATOR_WIDTH));
47348
+ if (title) {
47349
+ return `
47350
+ ${line}
47351
+ ${styles.header(title)}
47352
+ ${line}`;
47353
+ }
47354
+ return line;
47355
+ }
46196
47356
 
46197
47357
  class VerboseOutput {
46198
47358
  enabled;
@@ -46207,130 +47367,153 @@ class VerboseOutput {
46207
47367
  }
46208
47368
  }
46209
47369
  separator(title) {
46210
- if (title) {
46211
- this.log(`
46212
- ${SEPARATOR}
46213
- ${title}
46214
- ${SEPARATOR}`);
46215
- } else {
46216
- this.log(SEPARATOR);
46217
- }
47370
+ this.log(separator(title));
46218
47371
  }
46219
47372
  memoryStateBefore(stats, present) {
46220
47373
  this.separator("MEMORY STATE (before prompt)");
46221
- this.log(`Present:`);
46222
- this.log(` Mission: ${present.mission ?? "(none)"}`);
46223
- this.log(` Status: ${present.status ?? "(none)"}`);
47374
+ this.log(styles.subheader(`
47375
+ Present:`));
47376
+ this.log(` ${styles.label("Mission:")} ${present.mission ?? import_picocolors3.default.dim("(none)")}`);
47377
+ this.log(` ${styles.label("Status:")} ${present.status ?? import_picocolors3.default.dim("(none)")}`);
46224
47378
  const completed = present.tasks.filter((t) => t.status === "completed").length;
46225
47379
  const total = present.tasks.length;
46226
47380
  if (total > 0) {
46227
- const bar = "\u2588".repeat(completed) + "\u2591".repeat(total - completed);
46228
- this.log(` Tasks: [${completed}/${total} complete] ${bar}`);
47381
+ const bar = progressBar(completed, total, total);
47382
+ this.log(` ${styles.label("Tasks:")} [${styles.number(String(completed))}/${styles.number(String(total))} complete] ${bar}`);
46229
47383
  } else {
46230
- this.log(` Tasks: (none)`);
47384
+ this.log(` ${styles.label("Tasks:")} ${import_picocolors3.default.dim("(none)")}`);
46231
47385
  }
46232
- this.log(`
46233
- Temporal:`);
46234
- this.log(` Total messages: ${stats.totalMessages} (${stats.totalMessageTokens.toLocaleString()} tokens)`);
47386
+ this.log(styles.subheader(`
47387
+ Temporal:`));
47388
+ this.log(` ${styles.label("Total messages:")} ${styles.number(String(stats.totalMessages))} (${styles.number(stats.totalMessageTokens.toLocaleString())} tokens)`);
46235
47389
  if (stats.summariesByOrder.length > 0) {
46236
47390
  const maxOrder = Math.max(...stats.summariesByOrder.map((s) => s.order));
46237
- this.log(` Summaries: ${stats.totalSummaries} (orders 1-${maxOrder})`);
47391
+ this.log(` ${styles.label("Summaries:")} ${styles.number(String(stats.totalSummaries))} (orders 1-${maxOrder})`);
46238
47392
  for (const orderStats of stats.summariesByOrder) {
46239
- const coverage = orderStats.order === 1 ? orderStats.coveringMessages ? `covering ${orderStats.coveringMessages} messages` : "" : orderStats.coveringSummaries ? `covering ${orderStats.coveringSummaries} order-${orderStats.order - 1}` : "";
46240
- this.log(` Order ${orderStats.order}: ${orderStats.count} summaries (${orderStats.totalTokens.toLocaleString()} tokens${coverage ? ", " + coverage : ""})`);
47393
+ const coverage = orderStats.order === 1 ? orderStats.coveringMessages ? import_picocolors3.default.dim(`covering ${orderStats.coveringMessages} messages`) : "" : orderStats.coveringSummaries ? import_picocolors3.default.dim(`covering ${orderStats.coveringSummaries} order-${orderStats.order - 1}`) : "";
47394
+ this.log(` ${styles.label(`Order ${orderStats.order}:`)} ${styles.number(String(orderStats.count))} summaries (${styles.number(orderStats.totalTokens.toLocaleString())} tokens${coverage ? ", " + coverage : ""})`);
46241
47395
  }
46242
47396
  } else {
46243
- this.log(` Summaries: ${stats.totalSummaries}`);
47397
+ this.log(` ${styles.label("Summaries:")} ${styles.number(String(stats.totalSummaries))}`);
46244
47398
  }
46245
47399
  const needsCompaction = stats.effectiveViewTokens > stats.compactionThreshold;
46246
- this.log(` Effective view: ${stats.effectiveViewTokens.toLocaleString()} / ${stats.compactionThreshold.toLocaleString()} tokens${needsCompaction ? " (compaction needed)" : ""}`);
46247
- this.log(`
46248
- LTM:`);
46249
- this.log(` Entries: ${stats.ltmEntries}`);
46250
- this.log(` /identity: ${stats.identityTokens.toLocaleString()} tokens`);
46251
- this.log(` /behavior: ${stats.behaviorTokens.toLocaleString()} tokens`);
47400
+ const viewStatus = needsCompaction ? styles.warning(" (compaction needed)") : "";
47401
+ this.log(` ${styles.label("Effective view:")} ${styles.number(stats.effectiveViewTokens.toLocaleString())} / ${styles.number(stats.compactionThreshold.toLocaleString())} tokens${viewStatus}`);
47402
+ this.log(styles.subheader(`
47403
+ LTM:`));
47404
+ this.log(` ${styles.label("Entries:")} ${styles.number(String(stats.ltmEntries))}`);
47405
+ this.log(` ${styles.label("/identity:")} ${styles.number(stats.identityTokens.toLocaleString())} tokens`);
47406
+ this.log(` ${styles.label("/behavior:")} ${styles.number(stats.behaviorTokens.toLocaleString())} tokens`);
46252
47407
  }
46253
47408
  tokenBudget(budget) {
46254
47409
  this.separator("TOKEN BUDGET");
46255
- const pct = (n) => (n / budget.total * 100).toFixed(1);
46256
- this.log(`Component Tokens % of ${(budget.total / 1000).toFixed(0)}k`);
46257
- this.log("\u2500".repeat(41));
46258
- this.log(`System prompt ${budget.systemPrompt.toString().padStart(7)} ${pct(budget.systemPrompt).padStart(5)}%`);
46259
- this.log(`Identity/behavior ${(budget.identity + budget.behavior).toString().padStart(7)} ${pct(budget.identity + budget.behavior).padStart(5)}%`);
46260
- this.log(`Temporal summaries ${budget.temporalSummaries.toString().padStart(7)} ${pct(budget.temporalSummaries).padStart(5)}%`);
46261
- this.log(`Temporal messages ${budget.temporalMessages.toString().padStart(7)} ${pct(budget.temporalMessages).padStart(5)}%`);
46262
- this.log(`Present state ${budget.present.toString().padStart(7)} ${pct(budget.present).padStart(5)}%`);
46263
- this.log(`Tools ${budget.tools.toString().padStart(7)} ${pct(budget.tools).padStart(5)}%`);
46264
- this.log("\u2500".repeat(41));
46265
- this.log(`Total used ${budget.used.toString().padStart(7)} ${pct(budget.used).padStart(5)}%`);
46266
- this.log(`Available ${budget.available.toString().padStart(7)} ${pct(budget.available).padStart(5)}%`);
47410
+ const pct = (n) => colorPercent(n, budget.total);
47411
+ const totalK = (budget.total / 1000).toFixed(0);
47412
+ this.log(`
47413
+ ${styles.label("Component".padEnd(20))} ${styles.label("Tokens".padStart(7))} ${styles.label(`% of ${totalK}k`)}`);
47414
+ this.log(styles.separator("\u2500".repeat(41)));
47415
+ this.log(`${"System prompt".padEnd(20)} ${styles.number(budget.systemPrompt.toString().padStart(7))} ${pct(budget.systemPrompt).padStart(10)}`);
47416
+ this.log(`${"Identity/behavior".padEnd(20)} ${styles.number((budget.identity + budget.behavior).toString().padStart(7))} ${pct(budget.identity + budget.behavior).padStart(10)}`);
47417
+ this.log(`${"Temporal summaries".padEnd(20)} ${styles.number(budget.temporalSummaries.toString().padStart(7))} ${pct(budget.temporalSummaries).padStart(10)}`);
47418
+ this.log(`${"Temporal messages".padEnd(20)} ${styles.number(budget.temporalMessages.toString().padStart(7))} ${pct(budget.temporalMessages).padStart(10)}`);
47419
+ this.log(`${"Present state".padEnd(20)} ${styles.number(budget.present.toString().padStart(7))} ${pct(budget.present).padStart(10)}`);
47420
+ this.log(`${"Tools".padEnd(20)} ${styles.number(budget.tools.toString().padStart(7))} ${pct(budget.tools).padStart(10)}`);
47421
+ this.log(styles.separator("\u2500".repeat(41)));
47422
+ this.log(`${import_picocolors3.default.bold("Total used".padEnd(20))} ${import_picocolors3.default.bold(styles.number(budget.used.toString().padStart(7)))} ${pct(budget.used).padStart(10)}`);
47423
+ this.log(`${styles.success("Available".padEnd(20))} ${styles.success(budget.available.toString().padStart(7))} ${colorPercent(budget.available, budget.total).padStart(10)}`);
46267
47424
  }
46268
47425
  executionStart() {
46269
47426
  this.separator("AGENT EXECUTION");
46270
47427
  this.events = [];
46271
47428
  }
46272
47429
  event(event) {
46273
- const ts = event.timestamp ?? formatTimestamp2();
47430
+ const ts = styles.timestamp(event.timestamp ?? formatTimestamp2());
46274
47431
  const arrow = event.type === "user" || event.type === "tool_result" ? "\u2192" : "\u2190";
46275
- const typeLabel = event.type.replace("_", " ");
46276
- const content = event.content.length > 100 ? event.content.slice(0, 100) + "..." : event.content;
46277
- this.log(`[${ts}] ${arrow} ${typeLabel}: ${content}`);
46278
- this.events.push({ ...event, timestamp: ts });
47432
+ const styledArrow = styles.arrow(arrow);
47433
+ let typeLabel;
47434
+ switch (event.type) {
47435
+ case "user":
47436
+ typeLabel = styles.user("user");
47437
+ break;
47438
+ case "assistant":
47439
+ typeLabel = styles.assistant("assistant");
47440
+ break;
47441
+ case "tool_call":
47442
+ typeLabel = styles.tool("tool call");
47443
+ break;
47444
+ case "tool_result":
47445
+ typeLabel = styles.tool("tool result");
47446
+ break;
47447
+ case "error":
47448
+ typeLabel = styles.error("error");
47449
+ break;
47450
+ }
47451
+ const content = event.content.length > 100 ? event.content.slice(0, 100) + import_picocolors3.default.dim("...") : event.content;
47452
+ this.log(`[${ts}] ${styledArrow} ${typeLabel}: ${content}`);
47453
+ this.events.push({
47454
+ ...event,
47455
+ timestamp: event.timestamp ?? formatTimestamp2()
47456
+ });
46279
47457
  }
46280
47458
  memoryStateAfter(stats, present, usage) {
46281
47459
  this.separator("MEMORY STATE (after prompt)");
46282
- this.log(`Present:`);
46283
- this.log(` Mission: ${present.mission ?? "(none)"}`);
46284
- this.log(` Status: ${present.status ?? "(none)"}`);
47460
+ this.log(styles.subheader(`
47461
+ Present:`));
47462
+ this.log(` ${styles.label("Mission:")} ${present.mission ?? import_picocolors3.default.dim("(none)")}`);
47463
+ this.log(` ${styles.label("Status:")} ${present.status ?? import_picocolors3.default.dim("(none)")}`);
46285
47464
  const completed = present.tasks.filter((t) => t.status === "completed").length;
46286
47465
  const total = present.tasks.length;
46287
47466
  if (total > 0) {
46288
- const bar = "\u2588".repeat(completed) + "\u2591".repeat(total - completed);
46289
- this.log(` Tasks: [${completed}/${total} complete] ${bar}`);
47467
+ const bar = progressBar(completed, total, total);
47468
+ this.log(` ${styles.label("Tasks:")} [${styles.number(String(completed))}/${styles.number(String(total))} complete] ${bar}`);
46290
47469
  } else {
46291
- this.log(` Tasks: (none)`);
47470
+ this.log(` ${styles.label("Tasks:")} ${import_picocolors3.default.dim("(none)")}`);
46292
47471
  }
46293
- this.log(`
46294
- Temporal:`);
46295
- this.log(` Total messages: ${stats.totalMessages} (${stats.totalMessageTokens.toLocaleString()} tokens)`);
47472
+ this.log(styles.subheader(`
47473
+ Temporal:`));
47474
+ this.log(` ${styles.label("Total messages:")} ${styles.number(String(stats.totalMessages))} (${styles.number(stats.totalMessageTokens.toLocaleString())} tokens)`);
46296
47475
  if (stats.summariesByOrder.length > 0) {
46297
47476
  const maxOrder = Math.max(...stats.summariesByOrder.map((s) => s.order));
46298
- this.log(` Summaries: ${stats.totalSummaries} (orders 1-${maxOrder})`);
47477
+ this.log(` ${styles.label("Summaries:")} ${styles.number(String(stats.totalSummaries))} (orders 1-${maxOrder})`);
46299
47478
  for (const orderStats of stats.summariesByOrder) {
46300
- const coverage = orderStats.order === 1 ? orderStats.coveringMessages ? `covering ${orderStats.coveringMessages} messages` : "" : orderStats.coveringSummaries ? `covering ${orderStats.coveringSummaries} order-${orderStats.order - 1}` : "";
46301
- this.log(` Order ${orderStats.order}: ${orderStats.count} summaries (${orderStats.totalTokens.toLocaleString()} tokens${coverage ? ", " + coverage : ""})`);
47479
+ const coverage = orderStats.order === 1 ? orderStats.coveringMessages ? import_picocolors3.default.dim(`covering ${orderStats.coveringMessages} messages`) : "" : orderStats.coveringSummaries ? import_picocolors3.default.dim(`covering ${orderStats.coveringSummaries} order-${orderStats.order - 1}`) : "";
47480
+ this.log(` ${styles.label(`Order ${orderStats.order}:`)} ${styles.number(String(orderStats.count))} summaries (${styles.number(orderStats.totalTokens.toLocaleString())} tokens${coverage ? ", " + coverage : ""})`);
46302
47481
  }
46303
47482
  } else {
46304
- this.log(` Summaries: ${stats.totalSummaries}`);
47483
+ this.log(` ${styles.label("Summaries:")} ${styles.number(String(stats.totalSummaries))}`);
46305
47484
  }
46306
47485
  const needsCompaction = stats.effectiveViewTokens > stats.compactionThreshold;
46307
- this.log(` Effective view: ${stats.effectiveViewTokens.toLocaleString()} / ${stats.compactionThreshold.toLocaleString()} tokens${needsCompaction ? " (compaction needed)" : ""}`);
47486
+ const viewStatus = needsCompaction ? styles.warning(" (compaction needed)") : "";
47487
+ this.log(` ${styles.label("Effective view:")} ${styles.number(stats.effectiveViewTokens.toLocaleString())} / ${styles.number(stats.compactionThreshold.toLocaleString())} tokens${viewStatus}`);
46308
47488
  const inputCost = usage.inputTokens / 1e6 * 15;
46309
47489
  const outputCost = usage.outputTokens / 1e6 * 75;
46310
47490
  const totalCost = inputCost + outputCost;
46311
- this.log(`
46312
- Usage: ${usage.inputTokens.toLocaleString()} input tokens, ${usage.outputTokens.toLocaleString()} output tokens`);
46313
- this.log(`Cost: $${totalCost.toFixed(4)} (input: $${inputCost.toFixed(4)}, output: $${outputCost.toFixed(4)})`);
47491
+ this.log(styles.subheader(`
47492
+ Usage:`));
47493
+ this.log(` ${styles.label("Input:")} ${styles.number(usage.inputTokens.toLocaleString())} tokens`);
47494
+ this.log(` ${styles.label("Output:")} ${styles.number(usage.outputTokens.toLocaleString())} tokens`);
47495
+ this.log(` ${styles.label("Cost:")} ${styles.success("$" + totalCost.toFixed(4))} ${import_picocolors3.default.dim(`(input: $${inputCost.toFixed(4)}, output: $${outputCost.toFixed(4)})`)}`);
46314
47496
  }
46315
47497
  error(message, error2) {
46316
47498
  this.log(`
46317
- [ERROR] ${message}`);
47499
+ ${styles.error("[ERROR]")} ${message}`);
46318
47500
  if (error2?.stack) {
46319
- this.log(error2.stack);
47501
+ this.log(import_picocolors3.default.dim(error2.stack));
46320
47502
  }
46321
47503
  }
46322
47504
  compaction(result) {
46323
47505
  this.separator("COMPACTION");
46324
- this.log(`Distillations created: ${result.distillationsCreated}`);
46325
- this.log(`Agent turns used: ${result.turnsUsed}`);
46326
- const tokensCompressed = result.tokensBefore - result.tokensAfter;
46327
47506
  this.log(`
46328
- Tokens:`);
46329
- this.log(` Before: ${result.tokensBefore.toLocaleString()}`);
46330
- this.log(` After: ${result.tokensAfter.toLocaleString()}`);
46331
- this.log(` Compressed: ${tokensCompressed.toLocaleString()}`);
47507
+ ${styles.label("Distillations created:")} ${styles.number(String(result.distillationsCreated))}`);
47508
+ this.log(`${styles.label("Agent turns used:")} ${styles.number(String(result.turnsUsed))}`);
47509
+ const tokensCompressed = result.tokensBefore - result.tokensAfter;
47510
+ this.log(styles.subheader(`
47511
+ Tokens:`));
47512
+ this.log(` ${styles.label("Before:")} ${styles.number(result.tokensBefore.toLocaleString())}`);
47513
+ this.log(` ${styles.label("After:")} ${styles.number(result.tokensAfter.toLocaleString())}`);
47514
+ this.log(` ${styles.label("Compressed:")} ${styles.success(tokensCompressed.toLocaleString())}`);
46332
47515
  const ratio = tokensCompressed > 0 ? (tokensCompressed / result.tokensBefore * 100).toFixed(1) : "0.0";
46333
- this.log(` Compression: ${ratio}%`);
47516
+ this.log(` ${styles.label("Compression:")} ${styles.success(ratio + "%")}`);
46334
47517
  }
46335
47518
  }
46336
47519
 
@@ -46431,6 +47614,7 @@ async function runBatch(options) {
46431
47614
  verbose.executionStart();
46432
47615
  }
46433
47616
  const events = [];
47617
+ resetRenderer();
46434
47618
  const result = await runAgent(options.prompt, {
46435
47619
  storage,
46436
47620
  verbose: options.verbose,
@@ -46464,36 +47648,29 @@ async function runBatch(options) {
46464
47648
  ...e.toolCallId && { toolCallId: e.toolCallId }
46465
47649
  }))
46466
47650
  };
46467
- console.log(JSON.stringify(output, null, 2));
47651
+ renderRaw(JSON.stringify(output, null, 2) + `
47652
+ `);
46468
47653
  } else {
46469
- console.log(result.response);
47654
+ render({ type: "text", text: result.response });
46470
47655
  }
47656
+ renderEnd();
46471
47657
  } catch (error2) {
46472
- const err = error2;
46473
- if (err.message?.includes("API") || err.message?.includes("rate limit") || err.message?.includes("429")) {
46474
- verbose.error("API request failed", err);
46475
- console.error(`Error: API request failed - ${err.message}`);
46476
- } else if (err.message?.includes("ENOENT") || err.message?.includes("EACCES")) {
46477
- verbose.error("File system error", err);
46478
- console.error(`Error: File system error - ${err.message}`);
46479
- } else if (err.message?.includes("database") || err.message?.includes("SQLite")) {
46480
- verbose.error("Database error", err);
46481
- console.error(`Error: Database error - ${err.message}`);
46482
- } else {
46483
- verbose.error("Unexpected error", err);
46484
- console.error(`Error: ${err.message}`);
46485
- }
46486
- process.exit(1);
47658
+ throw error2;
46487
47659
  }
46488
47660
  }
46489
47661
 
46490
47662
  // src/cli/inspect.ts
46491
- var SEPARATOR2 = "\u2550".repeat(70);
46492
- var SUBSEPARATOR = "\u2500".repeat(70);
47663
+ var log13 = console.log;
47664
+ var blank = () => console.log();
47665
+ var SEPARATOR = styles.separator("\u2550".repeat(70));
47666
+ var SUBSEPARATOR = styles.separator("\u2500".repeat(70));
46493
47667
  function estimateTokens4(text3) {
46494
47668
  return Math.ceil(text3.length / 4);
46495
47669
  }
46496
47670
  function fmt(n) {
47671
+ return styles.number(n.toLocaleString());
47672
+ }
47673
+ function fmtPlain(n) {
46497
47674
  return n.toLocaleString();
46498
47675
  }
46499
47676
  async function buildLTMTree(storage) {
@@ -46532,12 +47709,17 @@ async function buildLTMTree(storage) {
46532
47709
  }
46533
47710
  function renderLTMTree(nodes, indent = 0) {
46534
47711
  const lines = [];
46535
- const prefix = " ".repeat(indent);
46536
- for (const node of nodes) {
46537
- const archived = node.archived ? " [archived]" : "";
46538
- const title = node.title ? ` "${node.title}"` : "";
46539
- const tokens = node.tokens > 0 ? ` (${fmt(node.tokens)} tokens)` : "";
46540
- lines.push(`${prefix}/${node.slug}${title}${tokens}${archived}`);
47712
+ for (let i = 0;i < nodes.length; i++) {
47713
+ const node = nodes[i];
47714
+ const isLast = i === nodes.length - 1;
47715
+ const branch = indent === 0 ? "" : isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
47716
+ const childPrefix = indent === 0 ? "" : isLast ? " " : "\u2502 ";
47717
+ const linePrefix = import_picocolors3.default.dim(" ".repeat(Math.max(0, indent - 1)) + branch);
47718
+ const archived = node.archived ? import_picocolors3.default.dim(" [archived]") : "";
47719
+ const title = node.title ? import_picocolors3.default.dim(` "${node.title}"`) : "";
47720
+ const tokens = node.tokens > 0 ? import_picocolors3.default.dim(` (${fmtPlain(node.tokens)} tokens)`) : "";
47721
+ const path9 = styles.path("/" + node.slug);
47722
+ lines.push(`${linePrefix}${path9}${title}${tokens}${archived}`);
46541
47723
  if (node.children.length > 0) {
46542
47724
  lines.push(renderLTMTree(node.children, indent + 1));
46543
47725
  }
@@ -46615,62 +47797,63 @@ async function runInspect(dbPath) {
46615
47797
  await initializeDefaultEntries(storage);
46616
47798
  const stats = await getMemoryStats2(storage);
46617
47799
  const ltmTree = await buildLTMTree(storage);
46618
- console.log();
46619
- console.log(SEPARATOR2);
46620
- console.log("LONG-TERM MEMORY TREE");
46621
- console.log(SEPARATOR2);
46622
- console.log();
47800
+ blank();
47801
+ log13(SEPARATOR);
47802
+ log13(styles.header("LONG-TERM MEMORY TREE"));
47803
+ log13(SEPARATOR);
47804
+ blank();
46623
47805
  if (ltmTree.length > 0) {
46624
- console.log(renderLTMTree(ltmTree));
47806
+ log13(renderLTMTree(ltmTree));
46625
47807
  } else {
46626
- console.log("(no entries)");
46627
- }
46628
- console.log();
46629
- console.log(`Total: ${stats.ltmActiveEntries} active, ${stats.ltmTotalEntries - stats.ltmActiveEntries} archived (${fmt(stats.ltmTotalTokens)} tokens)`);
46630
- console.log();
46631
- console.log(SEPARATOR2);
46632
- console.log("TEMPORAL MEMORY");
46633
- console.log(SEPARATOR2);
46634
- console.log();
46635
- console.log(`Messages: ${fmt(stats.totalMessages)} (${fmt(stats.totalMessageTokens)} tokens)`);
47808
+ log13(import_picocolors3.default.dim("(no entries)"));
47809
+ }
47810
+ blank();
47811
+ const archivedCount = stats.ltmTotalEntries - stats.ltmActiveEntries;
47812
+ log13(`${styles.label("Total:")} ${fmt(stats.ltmActiveEntries)} active${archivedCount > 0 ? `, ${fmt(archivedCount)} archived` : ""} (${fmt(stats.ltmTotalTokens)} tokens)`);
47813
+ blank();
47814
+ log13(SEPARATOR);
47815
+ log13(styles.header("TEMPORAL MEMORY"));
47816
+ log13(SEPARATOR);
47817
+ blank();
47818
+ log13(`${styles.label("Messages:")} ${fmt(stats.totalMessages)} (${fmt(stats.totalMessageTokens)} tokens)`);
46636
47819
  if (stats.summariesByOrder.length > 0) {
46637
- console.log(`Summaries:`);
47820
+ log13(`${styles.label("Summaries:")}`);
46638
47821
  for (const orderStats of stats.summariesByOrder) {
46639
- console.log(` Order-${orderStats.order}: ${orderStats.count} (${fmt(orderStats.totalTokens)} tokens)`);
47822
+ log13(` ${import_picocolors3.default.dim(`Order-${orderStats.order}:`)} ${fmt(orderStats.count)} (${fmt(orderStats.totalTokens)} tokens)`);
46640
47823
  }
46641
47824
  } else {
46642
- console.log(`Summaries: none`);
47825
+ log13(`${styles.label("Summaries:")} ${import_picocolors3.default.dim("none")}`);
46643
47826
  }
46644
- console.log();
47827
+ blank();
46645
47828
  const needsCompaction = stats.viewTotalTokens > stats.compactionThreshold;
46646
- const compactionStatus = needsCompaction ? " (compaction needed)" : "";
46647
- console.log(`Effective view (what goes to agent):`);
46648
- console.log(` Summaries: ${stats.viewSummaryCount} (${fmt(stats.viewSummaryTokens)} tokens)`);
46649
- console.log(` Messages: ${stats.viewMessageCount} (${fmt(stats.viewMessageTokens)} tokens)`);
46650
- console.log(` Total: ${fmt(stats.viewTotalTokens)} / ${fmt(stats.compactionThreshold)} threshold${compactionStatus}`);
46651
- console.log(` Target: ${fmt(stats.compactionTarget)} tokens`);
46652
- console.log();
46653
- console.log(SEPARATOR2);
46654
- console.log("PRESENT STATE");
46655
- console.log(SEPARATOR2);
46656
- console.log();
46657
- console.log(`Mission: ${stats.mission ?? "(none)"}`);
46658
- console.log(`Status: ${stats.status ?? "(none)"}`);
47829
+ const compactionStatus = needsCompaction ? styles.warning(" (compaction needed)") : "";
47830
+ log13(`${styles.label("Effective view")} ${import_picocolors3.default.dim("(what goes to agent)")}:`);
47831
+ log13(` ${styles.label("Summaries:")} ${fmt(stats.viewSummaryCount)} (${fmt(stats.viewSummaryTokens)} tokens)`);
47832
+ log13(` ${styles.label("Messages:")} ${fmt(stats.viewMessageCount)} (${fmt(stats.viewMessageTokens)} tokens)`);
47833
+ log13(` ${styles.label("Total:")} ${fmt(stats.viewTotalTokens)} / ${fmt(stats.compactionThreshold)} threshold${compactionStatus}`);
47834
+ log13(` ${styles.label("Target:")} ${fmt(stats.compactionTarget)} tokens`);
47835
+ blank();
47836
+ log13(SEPARATOR);
47837
+ log13(styles.header("PRESENT STATE"));
47838
+ log13(SEPARATOR);
47839
+ blank();
47840
+ log13(`${styles.label("Mission:")} ${stats.mission ?? import_picocolors3.default.dim("(none)")}`);
47841
+ log13(`${styles.label("Status:")} ${stats.status ?? import_picocolors3.default.dim("(none)")}`);
46659
47842
  const totalTasks = stats.tasksPending + stats.tasksInProgress + stats.tasksCompleted + stats.tasksBlocked;
46660
47843
  if (totalTasks > 0) {
46661
- console.log(`Tasks: ${totalTasks} total`);
47844
+ log13(`${styles.label("Tasks:")} ${fmt(totalTasks)} total`);
46662
47845
  if (stats.tasksPending > 0)
46663
- console.log(` Pending: ${stats.tasksPending}`);
47846
+ log13(` ${import_picocolors3.default.dim("Pending:")} ${fmt(stats.tasksPending)}`);
46664
47847
  if (stats.tasksInProgress > 0)
46665
- console.log(` In progress: ${stats.tasksInProgress}`);
47848
+ log13(` ${styles.warning("In progress:")} ${fmt(stats.tasksInProgress)}`);
46666
47849
  if (stats.tasksCompleted > 0)
46667
- console.log(` Completed: ${stats.tasksCompleted}`);
47850
+ log13(` ${styles.success("Completed:")} ${fmt(stats.tasksCompleted)}`);
46668
47851
  if (stats.tasksBlocked > 0)
46669
- console.log(` Blocked: ${stats.tasksBlocked}`);
47852
+ log13(` ${styles.error("Blocked:")} ${fmt(stats.tasksBlocked)}`);
46670
47853
  } else {
46671
- console.log(`Tasks: none`);
47854
+ log13(`${styles.label("Tasks:")} ${import_picocolors3.default.dim("none")}`);
46672
47855
  }
46673
- console.log();
47856
+ blank();
46674
47857
  }
46675
47858
  function renderTurnContent(turn) {
46676
47859
  if (typeof turn.content === "string") {
@@ -46681,10 +47864,10 @@ function renderTurnContent(turn) {
46681
47864
  if (part.type === "text") {
46682
47865
  parts.push(part.text);
46683
47866
  } else if (part.type === "tool-call") {
46684
- parts.push(`[tool_call: ${part.toolName}(${JSON.stringify(part.args)})]`);
47867
+ parts.push(styles.tool(`[tool_call: ${part.toolName}(${JSON.stringify(part.args)})]`));
46685
47868
  } else if (part.type === "tool-result") {
46686
47869
  const result = typeof part.result === "string" ? part.result.slice(0, 500) + (part.result.length > 500 ? "..." : "") : JSON.stringify(part.result).slice(0, 500);
46687
- parts.push(`[tool_result: ${part.toolName}] ${result}`);
47870
+ parts.push(import_picocolors3.default.dim(`[tool_result: ${part.toolName}] `) + result);
46688
47871
  }
46689
47872
  }
46690
47873
  return parts.join(`
@@ -46718,25 +47901,26 @@ async function runDump(dbPath) {
46718
47901
  return sum;
46719
47902
  }, 0);
46720
47903
  const totalTokens = systemTokens + conversationTokens;
46721
- console.log();
46722
- console.log(`# Agent Prompt Dump`);
46723
- console.log(`# System: ~${fmt(systemTokens)} tokens | Conversation: ${conversationTurns.length} turns, ~${fmt(conversationTokens)} tokens | Total: ~${fmt(totalTokens)} tokens`);
46724
- console.log();
46725
- console.log(`=== SYSTEM ===`);
46726
- console.log(systemPrompt);
47904
+ blank();
47905
+ log13(styles.header("Agent Prompt Dump"));
47906
+ log13(import_picocolors3.default.dim(`System: ~${fmtPlain(systemTokens)} tokens | Conversation: ${conversationTurns.length} turns, ~${fmtPlain(conversationTokens)} tokens | Total: ~${fmtPlain(totalTokens)} tokens`));
47907
+ blank();
47908
+ log13(styles.subheader("=== SYSTEM ==="));
47909
+ log13(systemPrompt);
46727
47910
  if (conversationTurns.length > 0) {
46728
- console.log();
46729
- console.log(`=== CONVERSATION (${conversationTurns.length} turns) ===`);
47911
+ blank();
47912
+ log13(styles.subheader(`=== CONVERSATION (${conversationTurns.length} turns) ===`));
46730
47913
  for (const turn of conversationTurns) {
46731
- console.log();
46732
- console.log(`--- ${turn.role.toUpperCase()} ---`);
46733
- console.log(renderTurnContent(turn));
47914
+ blank();
47915
+ const roleColor = turn.role === "user" ? styles.user : styles.assistant;
47916
+ log13(roleColor(`--- ${turn.role.toUpperCase()} ---`));
47917
+ log13(renderTurnContent(turn));
46734
47918
  }
46735
47919
  } else {
46736
- console.log();
46737
- console.log(`=== CONVERSATION (empty) ===`);
47920
+ blank();
47921
+ log13(styles.subheader("=== CONVERSATION (empty) ==="));
46738
47922
  }
46739
- console.log();
47923
+ blank();
46740
47924
  }
46741
47925
  async function runCompact(dbPath) {
46742
47926
  const storage = createStorage(dbPath);
@@ -46745,39 +47929,39 @@ async function runCompact(dbPath) {
46745
47929
  const threshold = config2.tokenBudgets.compactionThreshold;
46746
47930
  const target = config2.tokenBudgets.compactionTarget;
46747
47931
  const tokensBefore = await getEffectiveViewTokens(storage.temporal);
46748
- console.log(`Effective view: ${fmt(tokensBefore)} tokens`);
46749
- console.log(`Threshold: ${fmt(threshold)} tokens`);
46750
- console.log(`Target: ${fmt(target)} tokens`);
46751
- console.log();
47932
+ log13(`${styles.label("Effective view:")} ${fmt(tokensBefore)} tokens`);
47933
+ log13(`${styles.label("Threshold:")} ${fmt(threshold)} tokens`);
47934
+ log13(`${styles.label("Target:")} ${fmt(target)} tokens`);
47935
+ blank();
46752
47936
  if (tokensBefore <= target) {
46753
- console.log(`Already under target, but running anyway (forced)...`);
47937
+ log13(import_picocolors3.default.dim(`Already under target, but running anyway (forced)...`));
46754
47938
  } else {
46755
- console.log(`Running memory curation...`);
47939
+ log13(`Running memory curation...`);
46756
47940
  }
46757
- console.log();
47941
+ blank();
46758
47942
  const result = await runMemoryCuration(storage, { force: true });
46759
47943
  if (!result.ran) {
46760
- console.log(`Curation did not run (already in progress?)`);
47944
+ log13(styles.warning(`Curation did not run (already in progress?)`));
46761
47945
  return;
46762
47946
  }
46763
47947
  if (result.consolidation?.ran) {
46764
47948
  const c = result.consolidation;
46765
47949
  const changes = c.entriesCreated + c.entriesUpdated + c.entriesArchived;
46766
- console.log(`LTM Consolidation:`);
47950
+ log13(styles.subheader(`LTM Consolidation:`));
46767
47951
  if (changes > 0) {
46768
- console.log(` ${c.entriesCreated} created, ${c.entriesUpdated} updated, ${c.entriesArchived} archived`);
47952
+ log13(` ${styles.success(String(c.entriesCreated))} created, ${styles.number(String(c.entriesUpdated))} updated, ${import_picocolors3.default.dim(String(c.entriesArchived))} archived`);
46769
47953
  } else {
46770
- console.log(` No changes needed`);
47954
+ log13(import_picocolors3.default.dim(` No changes needed`));
46771
47955
  }
46772
- console.log();
47956
+ blank();
46773
47957
  }
46774
47958
  if (result.distillation) {
46775
47959
  const d = result.distillation;
46776
- console.log(`Distillation:`);
46777
- console.log(` Distillations created: ${d.distillationsCreated}`);
46778
- console.log(` Tokens: ${fmt(d.tokensBefore)} \u2192 ${fmt(d.tokensAfter)}`);
46779
- console.log(` Turns used: ${d.turnsUsed}`);
46780
- console.log(` LLM usage: ${fmt(d.usage.inputTokens)} input, ${fmt(d.usage.outputTokens)} output`);
47960
+ log13(styles.subheader(`Distillation:`));
47961
+ log13(` ${styles.label("Distillations created:")} ${fmt(d.distillationsCreated)}`);
47962
+ log13(` ${styles.label("Tokens:")} ${fmt(d.tokensBefore)} ${import_picocolors3.default.dim("\u2192")} ${styles.success(fmtPlain(d.tokensAfter))}`);
47963
+ log13(` ${styles.label("Turns used:")} ${fmt(d.turnsUsed)}`);
47964
+ log13(` ${styles.label("LLM usage:")} ${fmt(d.usage.inputTokens)} input, ${fmt(d.usage.outputTokens)} output`);
46781
47965
  }
46782
47966
  }
46783
47967
 
@@ -46842,12 +48026,21 @@ function assistantText(text3, model, sessionId) {
46842
48026
  function assistantToolUse(id, name17, input, model, sessionId) {
46843
48027
  return {
46844
48028
  type: "assistant",
46845
- message: { role: "assistant", content: [{ type: "tool_use", id, name: name17, input }], model },
48029
+ message: {
48030
+ role: "assistant",
48031
+ content: [{ type: "tool_use", id, name: name17, input }],
48032
+ model
48033
+ },
46846
48034
  session_id: sessionId
46847
48035
  };
46848
48036
  }
46849
48037
  function toolResult(toolUseId, content, isError = false) {
46850
- return { type: "tool_result", tool_use_id: toolUseId, content, is_error: isError || undefined };
48038
+ return {
48039
+ type: "tool_result",
48040
+ tool_use_id: toolUseId,
48041
+ content,
48042
+ is_error: isError || undefined
48043
+ };
46851
48044
  }
46852
48045
  function resultMessage(sessionId, subtype, durationMs, numTurns, options = {}) {
46853
48046
  return {
@@ -46858,7 +48051,10 @@ function resultMessage(sessionId, subtype, durationMs, numTurns, options = {}) {
46858
48051
  num_turns: numTurns,
46859
48052
  session_id: sessionId,
46860
48053
  result: options.result,
46861
- usage: options.inputTokens !== undefined ? { input_tokens: options.inputTokens, output_tokens: options.outputTokens ?? 0 } : undefined
48054
+ usage: options.inputTokens !== undefined ? {
48055
+ input_tokens: options.inputTokens,
48056
+ output_tokens: options.outputTokens ?? 0
48057
+ } : undefined
46862
48058
  };
46863
48059
  }
46864
48060
  function systemMessage(subtype, data = {}) {
@@ -46869,7 +48065,7 @@ function systemMessage(subtype, data = {}) {
46869
48065
  function getModelId() {
46870
48066
  return Config.resolveModelTier("reasoning");
46871
48067
  }
46872
- var log11 = Log.create({ service: "server" });
48068
+ var log14 = Log.create({ service: "server" });
46873
48069
 
46874
48070
  class Server {
46875
48071
  options;
@@ -46879,33 +48075,52 @@ class Server {
46879
48075
  rl = null;
46880
48076
  processing = false;
46881
48077
  sessionId = "";
48078
+ alarmInterval = null;
48079
+ checkingAlarms = false;
48080
+ outputHandler;
48081
+ turnCompleteResolve = null;
46882
48082
  constructor(options) {
46883
48083
  this.options = options;
46884
48084
  this.storage = createStorage(options.dbPath);
48085
+ this.outputHandler = options.outputHandler ?? ((msg) => {
48086
+ process.stdout.write(JSON.stringify(msg) + `
48087
+ `);
48088
+ });
46885
48089
  }
46886
48090
  async start() {
46887
48091
  await cleanupStaleWorkers(this.storage);
46888
48092
  await initializeDefaultEntries(this.storage);
48093
+ await this.recoverKilledTasks();
46889
48094
  this.sessionId = await this.storage.session.getId();
46890
48095
  await Mcp.initialize();
46891
48096
  const mcpTools = Mcp.getToolNames();
46892
- process.on("SIGTERM", () => this.shutdown("SIGTERM"));
46893
- process.on("SIGINT", () => this.shutdown("SIGINT"));
46894
- this.rl = readline.createInterface({
46895
- input: process.stdin,
46896
- output: process.stdout,
46897
- terminal: false
46898
- });
46899
- this.rl.on("line", (line) => {
46900
- this.handleLine(line).catch((error2) => {
46901
- log11.error("unhandled error in line handler", { error: error2 });
48097
+ if (!this.options.noStdin) {
48098
+ process.on("SIGTERM", () => this.shutdown("SIGTERM"));
48099
+ process.on("SIGINT", () => this.shutdown("SIGINT"));
48100
+ this.rl = readline.createInterface({
48101
+ input: process.stdin,
48102
+ output: process.stdout,
48103
+ terminal: false
46902
48104
  });
48105
+ this.rl.on("line", (line) => {
48106
+ this.handleLine(line).catch((error2) => {
48107
+ log14.error("unhandled error in line handler", { error: error2 });
48108
+ });
48109
+ });
48110
+ this.rl.on("close", () => {
48111
+ log14.info("stdin closed, shutting down");
48112
+ this.shutdown("stdin closed");
48113
+ });
48114
+ }
48115
+ this.alarmInterval = setInterval(() => {
48116
+ this.checkAlarms().catch((error2) => {
48117
+ log14.error("error checking alarms", { error: error2 });
48118
+ });
48119
+ }, 1000);
48120
+ log14.info("server started", {
48121
+ dbPath: this.options.dbPath,
48122
+ sessionId: this.sessionId
46903
48123
  });
46904
- this.rl.on("close", () => {
46905
- log11.info("stdin closed, shutting down");
46906
- this.shutdown("stdin closed");
46907
- });
46908
- log11.info("server started", { dbPath: this.options.dbPath, sessionId: this.sessionId });
46909
48124
  this.send(systemMessage("init", {
46910
48125
  session_id: this.sessionId,
46911
48126
  model: getModelId(),
@@ -46932,9 +48147,13 @@ class Server {
46932
48147
  switch (request.action) {
46933
48148
  case "interrupt":
46934
48149
  if (this.currentTurn) {
46935
- log11.info("interrupting current turn", { sessionId: this.currentTurn.sessionId });
48150
+ log14.info("interrupting current turn", {
48151
+ sessionId: this.currentTurn.sessionId
48152
+ });
46936
48153
  this.currentTurn.abortController.abort();
46937
- this.send(systemMessage("interrupted", { session_id: this.currentTurn.sessionId }));
48154
+ this.send(systemMessage("interrupted", {
48155
+ session_id: this.currentTurn.sessionId
48156
+ }));
46938
48157
  } else {
46939
48158
  this.send(systemMessage("error", { message: "No turn is currently running" }));
46940
48159
  }
@@ -46954,8 +48173,29 @@ class Server {
46954
48173
  break;
46955
48174
  }
46956
48175
  }
48176
+ async recoverKilledTasks() {
48177
+ const killedTasks = await this.storage.tasks.recoverKilledTasks();
48178
+ if (killedTasks.length === 0)
48179
+ return;
48180
+ log14.info("recovered killed tasks", { count: killedTasks.length });
48181
+ for (const task of killedTasks) {
48182
+ await this.storage.background.fileReport({
48183
+ subsystem: "task_recovery",
48184
+ report: {
48185
+ message: `Background task was killed when agent restarted: ${task.type} - "${task.description}". You may want to restart it.`,
48186
+ taskId: task.id,
48187
+ type: task.type,
48188
+ description: task.description
48189
+ }
48190
+ });
48191
+ }
48192
+ }
46957
48193
  async shutdown(reason) {
46958
- log11.info("shutting down", { reason });
48194
+ log14.info("shutting down", { reason });
48195
+ if (this.alarmInterval) {
48196
+ clearInterval(this.alarmInterval);
48197
+ this.alarmInterval = null;
48198
+ }
46959
48199
  if (this.currentTurn) {
46960
48200
  this.currentTurn.abortController.abort();
46961
48201
  }
@@ -46963,10 +48203,76 @@ class Server {
46963
48203
  this.rl?.close();
46964
48204
  process.exit(0);
46965
48205
  }
48206
+ interrupt() {
48207
+ if (this.currentTurn) {
48208
+ log14.info("interrupting current turn", {
48209
+ sessionId: this.currentTurn.sessionId
48210
+ });
48211
+ this.currentTurn.abortController.abort();
48212
+ this.send(systemMessage("interrupted", { session_id: this.currentTurn.sessionId }));
48213
+ }
48214
+ }
48215
+ async sendUserMessage(prompt) {
48216
+ const userMessage = {
48217
+ type: "user",
48218
+ session_id: this.sessionId,
48219
+ message: {
48220
+ role: "user",
48221
+ content: prompt
48222
+ }
48223
+ };
48224
+ const turnComplete = new Promise((resolve5) => {
48225
+ this.turnCompleteResolve = resolve5;
48226
+ });
48227
+ await this.handleUserMessage(userMessage);
48228
+ await turnComplete;
48229
+ }
48230
+ async checkAlarms() {
48231
+ if (this.checkingAlarms)
48232
+ return;
48233
+ this.checkingAlarms = true;
48234
+ try {
48235
+ const dueAlarms = await this.storage.tasks.getDueAlarms();
48236
+ if (dueAlarms.length > 0) {
48237
+ log14.info("alarms fired", { count: dueAlarms.length });
48238
+ for (const alarm of dueAlarms) {
48239
+ await this.storage.tasks.markAlarmFired(alarm.id);
48240
+ await this.storage.tasks.queueResult(alarm.id, `\u23F0 **Alarm fired**: ${alarm.note}`);
48241
+ }
48242
+ }
48243
+ const hasResults = await this.storage.tasks.hasQueuedResults();
48244
+ if (hasResults && !this.currentTurn && !this.processing) {
48245
+ await this.triggerSelfTurn();
48246
+ }
48247
+ } finally {
48248
+ this.checkingAlarms = false;
48249
+ }
48250
+ }
48251
+ async triggerSelfTurn() {
48252
+ const results = await this.storage.tasks.drainQueue();
48253
+ if (results.length === 0)
48254
+ return;
48255
+ log14.info("triggering self-turn", { resultCount: results.length });
48256
+ const content = results.map((r) => r.content).join(`
48257
+
48258
+ `);
48259
+ const selfMessage = {
48260
+ type: "user",
48261
+ session_id: this.sessionId,
48262
+ message: {
48263
+ role: "user",
48264
+ content: `[SYSTEM: Background events occurred]
48265
+
48266
+ ${content}`
48267
+ }
48268
+ };
48269
+ await this.processTurn(selfMessage);
48270
+ await this.processQueue();
48271
+ }
46966
48272
  async handleUserMessage(userMessage) {
46967
48273
  if (this.currentTurn) {
46968
48274
  this.messageQueue.push(userMessage);
46969
- log11.info("queued message", {
48275
+ log14.info("queued message", {
46970
48276
  sessionId: userMessage.session_id,
46971
48277
  queueLength: this.messageQueue.length,
46972
48278
  currentSession: this.currentTurn.sessionId
@@ -46992,7 +48298,7 @@ class Server {
46992
48298
  }
46993
48299
  if (userMessage.environment !== undefined) {
46994
48300
  setEnvironment(userMessage.environment);
46995
- log11.info("applied environment from message", {
48301
+ log14.info("applied environment from message", {
46996
48302
  count: Object.keys(userMessage.environment).length
46997
48303
  });
46998
48304
  } else {
@@ -47005,7 +48311,7 @@ class Server {
47005
48311
  numTurns: 0,
47006
48312
  startTime: Date.now()
47007
48313
  };
47008
- log11.debug("starting turn", { sessionId, promptLength: prompt.length });
48314
+ log14.debug("starting turn", { sessionId, promptLength: prompt.length });
47009
48315
  try {
47010
48316
  const agentOptions = {
47011
48317
  storage: this.storage,
@@ -47029,12 +48335,16 @@ class Server {
47029
48335
  return;
47030
48336
  }
47031
48337
  const message = error2 instanceof Error ? error2.message : String(error2);
47032
- log11.error("turn failed", { sessionId, error: message });
48338
+ log14.error("turn failed", { sessionId, error: message });
47033
48339
  this.send(resultMessage(sessionId, "error", Date.now() - (this.currentTurn?.startTime ?? Date.now()), this.currentTurn?.numTurns ?? 0, {
47034
48340
  result: message
47035
48341
  }));
47036
48342
  } finally {
47037
48343
  this.currentTurn = null;
48344
+ if (this.turnCompleteResolve) {
48345
+ this.turnCompleteResolve();
48346
+ this.turnCompleteResolve = null;
48347
+ }
47038
48348
  }
47039
48349
  }
47040
48350
  async processQueue() {
@@ -47044,7 +48354,7 @@ class Server {
47044
48354
  try {
47045
48355
  while (this.messageQueue.length > 0 && !this.currentTurn) {
47046
48356
  const nextMessage = this.messageQueue.shift();
47047
- log11.info("processing queued message", {
48357
+ log14.info("processing queued message", {
47048
48358
  sessionId: nextMessage.session_id,
47049
48359
  remainingInQueue: this.messageQueue.length
47050
48360
  });
@@ -47063,7 +48373,7 @@ class Server {
47063
48373
  const combined = contents.join(`
47064
48374
 
47065
48375
  `);
47066
- log11.info("injecting mid-turn messages", {
48376
+ log14.info("injecting mid-turn messages", {
47067
48377
  messageCount: messages.length,
47068
48378
  combinedLength: combined.length
47069
48379
  });
@@ -47097,7 +48407,10 @@ class Server {
47097
48407
  }
47098
48408
  break;
47099
48409
  case "error":
47100
- this.send(systemMessage("error", { message: event.content, session_id: sessionId }));
48410
+ this.send(systemMessage("error", {
48411
+ message: event.content,
48412
+ session_id: sessionId
48413
+ }));
47101
48414
  break;
47102
48415
  case "consolidation":
47103
48416
  if (event.consolidationResult?.ran) {
@@ -47122,14 +48435,13 @@ class Server {
47122
48435
  };
47123
48436
  const reinitialized = await Mcp.initialize(mergedConfig);
47124
48437
  if (reinitialized) {
47125
- log11.info("MCP reinitialized with message config", {
48438
+ log14.info("MCP reinitialized with message config", {
47126
48439
  serverCount: Object.keys(mergedConfig.mcpServers ?? {}).length
47127
48440
  });
47128
48441
  }
47129
48442
  }
47130
48443
  send(message) {
47131
- process.stdout.write(JSON.stringify(message) + `
47132
- `);
48444
+ this.outputHandler(message);
47133
48445
  }
47134
48446
  }
47135
48447
  async function runServer(options) {
@@ -47142,24 +48454,53 @@ import * as readline2 from "readline";
47142
48454
  import * as fs8 from "fs";
47143
48455
  import * as path9 from "path";
47144
48456
  import * as os3 from "os";
47145
- var PROMPT = "miriad-code> ";
47146
- var HISTORY_FILE = path9.join(os3.homedir(), ".miriad-code-history");
48457
+
48458
+ // src/util/markdown.ts
48459
+ function renderMarkdown(text3) {
48460
+ text3 = text3.replace(/```(\w*)\n([\s\S]*?)```/g, (_, lang, code) => {
48461
+ return styles.label("```" + lang) + `
48462
+ ` + code.trimEnd() + `
48463
+ ` + styles.label("```");
48464
+ });
48465
+ text3 = text3.replace(/`([^`]+)`/g, (_, code) => styles.code(code));
48466
+ text3 = text3.replace(/\*\*([^*]+)\*\*/g, (_, content) => import_picocolors3.default.bold(content));
48467
+ text3 = text3.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, (_, content) => styles.label(content));
48468
+ text3 = text3.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, linkText, url2) => {
48469
+ return import_picocolors3.default.underline(linkText) + styles.label(` (${url2})`);
48470
+ });
48471
+ text3 = text3.replace(/^(#{1,6})\s+(.+)$/gm, (_, _hashes, content) => {
48472
+ return styles.header(content);
48473
+ });
48474
+ text3 = text3.replace(/^(\s*)[-*]\s+/gm, (_, indent) => {
48475
+ return indent + styles.label("\u2022") + " ";
48476
+ });
48477
+ text3 = text3.replace(/^(\s*)(\d+)\.\s+/gm, (_, indent, num) => {
48478
+ return indent + styles.label(num + ".") + " ";
48479
+ });
48480
+ return text3;
48481
+ }
48482
+
48483
+ // src/cli/repl.ts
48484
+ var PROMPT = import_picocolors3.default.cyan("nuum") + import_picocolors3.default.dim("> ");
48485
+ var HISTORY_FILE = path9.join(os3.homedir(), ".nuum-history");
47147
48486
  var MAX_HISTORY = 1000;
47148
48487
 
47149
48488
  class ReplSession {
47150
48489
  options;
47151
- storage;
48490
+ server;
47152
48491
  rl = null;
47153
- abortController = null;
47154
- isRunning = false;
47155
48492
  history = [];
48493
+ isRunning = false;
47156
48494
  constructor(options) {
47157
48495
  this.options = options;
47158
- this.storage = createStorage(options.dbPath);
48496
+ this.server = new Server({
48497
+ dbPath: options.dbPath,
48498
+ outputHandler: (message) => this.handleServerOutput(message),
48499
+ noStdin: true
48500
+ });
47159
48501
  }
47160
48502
  async start() {
47161
- await cleanupStaleWorkers(this.storage);
47162
- await initializeDefaultEntries(this.storage);
48503
+ await this.server.start();
47163
48504
  this.loadHistory();
47164
48505
  this.rl = readline2.createInterface({
47165
48506
  input: process.stdin,
@@ -47171,28 +48512,35 @@ class ReplSession {
47171
48512
  for (const line of this.history) {
47172
48513
  this.rl.history?.unshift(line);
47173
48514
  }
48515
+ setReplContext(this.rl, PROMPT);
47174
48516
  this.rl.on("SIGINT", () => {
47175
- if (this.isRunning && this.abortController) {
47176
- this.abortController.abort();
47177
- process.stdout.write(`
47178
- ^C - Request cancelled
48517
+ if (this.isRunning) {
48518
+ this.server.interrupt();
48519
+ renderRaw(`
48520
+ `);
48521
+ renderRaw(styles.warning("^C - Request cancelled") + `
47179
48522
  `);
47180
48523
  } else {
47181
- process.stdout.write(`
47182
- (Use /quit or Ctrl+D to exit)
48524
+ renderRaw(`
48525
+ `);
48526
+ renderRaw(import_picocolors3.default.dim("(Use /quit or Ctrl+D to exit)") + `
47183
48527
  `);
47184
48528
  this.rl?.prompt();
47185
48529
  }
47186
48530
  });
47187
48531
  this.rl.on("close", () => {
48532
+ clearReplContext();
47188
48533
  this.saveHistory();
47189
- console.log(`
47190
- Goodbye!`);
47191
- process.exit(0);
48534
+ renderRaw(`
48535
+ `);
48536
+ renderRaw(import_picocolors3.default.dim("Goodbye!") + `
48537
+ `);
48538
+ this.server.shutdown("user exit");
47192
48539
  });
47193
48540
  this.rl.on("line", (line) => {
47194
48541
  this.handleLine(line).catch((error2) => {
47195
- console.error(`Error: ${error2 instanceof Error ? error2.message : String(error2)}`);
48542
+ renderRaw(styles.error(`Error: ${error2 instanceof Error ? error2.message : String(error2)}`) + `
48543
+ `);
47196
48544
  this.rl?.prompt();
47197
48545
  });
47198
48546
  });
@@ -47200,10 +48548,14 @@ Goodbye!`);
47200
48548
  this.rl.prompt();
47201
48549
  }
47202
48550
  printWelcome() {
47203
- console.log();
47204
- console.log("miriad-code interactive mode");
47205
- console.log("Type /help for commands, /quit to exit");
47206
- console.log();
48551
+ renderRaw(`
48552
+ `);
48553
+ renderRaw(import_picocolors3.default.bold(import_picocolors3.default.cyan("nuum")) + " " + import_picocolors3.default.dim("interactive mode") + `
48554
+ `);
48555
+ renderRaw(import_picocolors3.default.dim("Type /help for commands, /quit to exit") + `
48556
+ `);
48557
+ renderRaw(`
48558
+ `);
47207
48559
  }
47208
48560
  async handleLine(line) {
47209
48561
  const trimmed = line.trim();
@@ -47225,15 +48577,18 @@ Goodbye!`);
47225
48577
  case "quit":
47226
48578
  case "exit":
47227
48579
  case "q":
48580
+ clearReplContext();
47228
48581
  this.saveHistory();
47229
- console.log("Goodbye!");
47230
- process.exit(0);
48582
+ renderRaw(import_picocolors3.default.dim("Goodbye!") + `
48583
+ `);
48584
+ this.server.shutdown("user exit");
47231
48585
  break;
47232
48586
  case "inspect":
47233
48587
  try {
47234
48588
  await runInspect(this.options.dbPath);
47235
48589
  } catch (error2) {
47236
- console.error(`Error: ${error2 instanceof Error ? error2.message : String(error2)}`);
48590
+ renderRaw(styles.error(`Error: ${error2 instanceof Error ? error2.message : String(error2)}`) + `
48591
+ `);
47237
48592
  }
47238
48593
  this.rl?.prompt();
47239
48594
  break;
@@ -47241,7 +48596,8 @@ Goodbye!`);
47241
48596
  try {
47242
48597
  await runDump(this.options.dbPath);
47243
48598
  } catch (error2) {
47244
- console.error(`Error: ${error2 instanceof Error ? error2.message : String(error2)}`);
48599
+ renderRaw(styles.error(`Error: ${error2 instanceof Error ? error2.message : String(error2)}`) + `
48600
+ `);
47245
48601
  }
47246
48602
  this.rl?.prompt();
47247
48603
  break;
@@ -47252,129 +48608,106 @@ Goodbye!`);
47252
48608
  this.rl?.prompt();
47253
48609
  break;
47254
48610
  default:
47255
- console.log(`Unknown command: /${command}`);
47256
- console.log("Type /help for available commands.");
48611
+ renderRaw(styles.warning(`Unknown command: /${command}`) + `
48612
+ `);
48613
+ renderRaw(import_picocolors3.default.dim("Type /help for available commands.") + `
48614
+ `);
47257
48615
  this.rl?.prompt();
47258
48616
  }
47259
48617
  }
47260
48618
  printHelp() {
47261
- console.log();
47262
- console.log("Commands:");
47263
- console.log(" /help, /h, /? Show this help");
47264
- console.log(" /quit, /exit, /q Exit the REPL");
47265
- console.log(" /inspect Show memory statistics");
47266
- console.log(" /dump Show full system prompt");
47267
- console.log();
47268
- console.log("Shortcuts:");
47269
- console.log(" Ctrl+C Cancel current request");
47270
- console.log(" Ctrl+D Exit");
47271
- console.log(" Up/Down arrows Navigate history");
47272
- console.log(" Ctrl+R Reverse history search");
47273
- console.log();
48619
+ renderRaw(`
48620
+ `);
48621
+ renderRaw(styles.header("Commands") + `
48622
+ `);
48623
+ renderRaw(` ${import_picocolors3.default.cyan("/help")}, ${import_picocolors3.default.cyan("/h")}, ${import_picocolors3.default.cyan("/?")} ${import_picocolors3.default.dim("Show this help")}
48624
+ `);
48625
+ renderRaw(` ${import_picocolors3.default.cyan("/quit")}, ${import_picocolors3.default.cyan("/exit")}, ${import_picocolors3.default.cyan("/q")} ${import_picocolors3.default.dim("Exit the REPL")}
48626
+ `);
48627
+ renderRaw(` ${import_picocolors3.default.cyan("/inspect")} ${import_picocolors3.default.dim("Show memory statistics")}
48628
+ `);
48629
+ renderRaw(` ${import_picocolors3.default.cyan("/dump")} ${import_picocolors3.default.dim("Show full system prompt")}
48630
+ `);
48631
+ renderRaw(`
48632
+ `);
48633
+ renderRaw(styles.header("Shortcuts") + `
48634
+ `);
48635
+ renderRaw(` ${import_picocolors3.default.yellow("Ctrl+C")} ${import_picocolors3.default.dim("Cancel current request")}
48636
+ `);
48637
+ renderRaw(` ${import_picocolors3.default.yellow("Ctrl+D")} ${import_picocolors3.default.dim("Exit")}
48638
+ `);
48639
+ renderRaw(` ${import_picocolors3.default.yellow("Up/Down arrows")} ${import_picocolors3.default.dim("Navigate history")}
48640
+ `);
48641
+ renderRaw(` ${import_picocolors3.default.yellow("Ctrl+R")} ${import_picocolors3.default.dim("Reverse history search")}
48642
+ `);
48643
+ renderRaw(`
48644
+ `);
47274
48645
  }
47275
48646
  async runPrompt(prompt) {
47276
48647
  this.isRunning = true;
47277
- this.abortController = new AbortController;
47278
- let hasOutput = false;
47279
- const agentOptions = {
47280
- storage: this.storage,
47281
- verbose: false,
47282
- abortSignal: this.abortController.signal,
47283
- onEvent: (event) => this.handleAgentEvent(event, () => {
47284
- hasOutput = true;
47285
- })
47286
- };
48648
+ setReplRunning(true);
48649
+ resetRenderer();
48650
+ resetRenderer();
47287
48651
  try {
47288
- await runAgent(prompt, agentOptions);
47289
- if (hasOutput) {
47290
- console.log();
47291
- }
47292
- } catch (error2) {
47293
- if (error2 instanceof AgentLoopCancelledError) {} else {
47294
- console.error(`
47295
- Error: ${error2 instanceof Error ? error2.message : String(error2)}`);
47296
- }
48652
+ renderRaw(`
48653
+ `);
48654
+ await this.server.sendUserMessage(prompt);
47297
48655
  } finally {
47298
48656
  this.isRunning = false;
47299
- this.abortController = null;
47300
- console.log();
48657
+ setReplRunning(false);
48658
+ renderEnd();
47301
48659
  this.rl?.prompt();
47302
48660
  }
47303
48661
  }
47304
- handleAgentEvent(event, markOutput) {
47305
- switch (event.type) {
47306
- case "assistant":
47307
- process.stdout.write(event.content);
47308
- markOutput();
47309
- break;
47310
- case "tool_call":
47311
- if (event.toolName) {
47312
- const displayName = this.formatToolName(event.toolName);
47313
- const args = this.formatToolArgs(event.content);
47314
- process.stdout.write(`
47315
- [${displayName}${args}...]
47316
- `);
47317
- markOutput();
48662
+ handleServerOutput(message) {
48663
+ const msg = message;
48664
+ const type = msg.type;
48665
+ switch (type) {
48666
+ case "assistant": {
48667
+ const assistantMsg = msg.message;
48668
+ if (assistantMsg?.content) {
48669
+ for (const block of assistantMsg.content) {
48670
+ if (block.type === "text" && block.text) {
48671
+ render({ type: "text", text: renderMarkdown(block.text) });
48672
+ }
48673
+ }
47318
48674
  }
47319
48675
  break;
47320
- case "tool_result":
47321
- break;
47322
- case "error":
47323
- process.stdout.write(`
47324
- [Error: ${event.content}]
47325
- `);
47326
- markOutput();
47327
- break;
47328
- case "consolidation":
47329
- if (event.consolidationResult?.ran) {
47330
- const r = event.consolidationResult;
47331
- const changes = r.entriesCreated + r.entriesUpdated + r.entriesArchived;
47332
- if (changes > 0) {
47333
- process.stdout.write(`
47334
- [LTM updated: ${changes} change(s)]
47335
- `);
48676
+ }
48677
+ case "system": {
48678
+ const subtype = msg.subtype;
48679
+ switch (subtype) {
48680
+ case "init":
48681
+ case "tool_result":
48682
+ case "interrupted":
48683
+ break;
48684
+ case "error":
48685
+ render({
48686
+ type: "info",
48687
+ worker: "server",
48688
+ level: "error",
48689
+ message: msg.message || "Unknown error"
48690
+ });
48691
+ break;
48692
+ case "consolidation": {
48693
+ const changes = (msg.entries_created ?? 0) + (msg.entries_updated ?? 0) + (msg.entries_archived ?? 0);
48694
+ if (changes > 0) {
48695
+ render({
48696
+ type: "lifecycle",
48697
+ worker: "ltm-curator",
48698
+ action: "complete",
48699
+ message: `LTM updated: ${changes} change(s)`
48700
+ });
48701
+ }
48702
+ break;
47336
48703
  }
47337
48704
  }
47338
- markOutput();
47339
48705
  break;
47340
- case "compaction":
47341
- process.stdout.write(`
47342
- [Memory compacted]
47343
- `);
47344
- markOutput();
48706
+ }
48707
+ case "result": {
47345
48708
  break;
47346
- }
47347
- }
47348
- formatToolName(name17) {
47349
- const displayNames = {
47350
- bash: "Running command",
47351
- read: "Reading",
47352
- write: "Writing",
47353
- edit: "Editing",
47354
- glob: "Searching files",
47355
- grep: "Searching content",
47356
- present_set_mission: "Setting mission",
47357
- present_set_status: "Setting status",
47358
- present_update_tasks: "Updating tasks"
47359
- };
47360
- return displayNames[name17] || name17;
47361
- }
47362
- formatToolArgs(content) {
47363
- try {
47364
- const match = content.match(/\((\{.+?\})\.\.\.\)$/);
47365
- if (match) {
47366
- const args = JSON.parse(match[1] + "}");
47367
- if (args.path)
47368
- return ` ${args.path}`;
47369
- if (args.file)
47370
- return ` ${args.file}`;
47371
- if (args.pattern)
47372
- return ` ${args.pattern}`;
47373
- if (args.command)
47374
- return ` ${args.command.slice(0, 50)}${args.command.length > 50 ? "..." : ""}`;
47375
48709
  }
47376
- } catch {}
47377
- return "";
48710
+ }
47378
48711
  }
47379
48712
  loadHistory() {
47380
48713
  try {
@@ -47408,9 +48741,155 @@ async function runRepl(options) {
47408
48741
  }
47409
48742
 
47410
48743
  // src/version.ts
47411
- var VERSION = "0.2.2";
47412
- var GIT_HASH = "0764a52";
47413
- var VERSION_STRING = `miriad-code v${VERSION} (${GIT_HASH})`;
48744
+ var VERSION = "0.4.0";
48745
+ var GIT_HASH = "ae44f42";
48746
+ var VERSION_STRING = `nuum v${VERSION} (${GIT_HASH})`;
48747
+
48748
+ // src/cli/error.ts
48749
+ function categorizeError(error2) {
48750
+ if (!(error2 instanceof Error)) {
48751
+ return {
48752
+ title: "Unknown Error",
48753
+ message: String(error2)
48754
+ };
48755
+ }
48756
+ const msg = error2.message;
48757
+ if (msg.includes("rate limit") || msg.includes("429") || msg.includes("Too Many Requests")) {
48758
+ return {
48759
+ title: "Rate Limited",
48760
+ message: "API rate limit exceeded",
48761
+ hint: "Wait a moment and try again, or check your API usage limits."
48762
+ };
48763
+ }
48764
+ if (msg.includes("ANTHROPIC_API_KEY") && msg.includes("required")) {
48765
+ return {
48766
+ title: "Missing API Key",
48767
+ message: "ANTHROPIC_API_KEY environment variable is not set",
48768
+ hint: "Set it with: export ANTHROPIC_API_KEY=sk-ant-..."
48769
+ };
48770
+ }
48771
+ if (msg.includes("401") || msg.includes("Unauthorized") || msg.includes("invalid x-api-key") || msg.includes("invalid_api_key") || /invalid.*api.*key/i.test(msg)) {
48772
+ return {
48773
+ title: "Authentication Failed",
48774
+ message: "Invalid or missing API key",
48775
+ hint: "Set ANTHROPIC_API_KEY environment variable with a valid key."
48776
+ };
48777
+ }
48778
+ if (msg.includes("API") || msg.includes("fetch") || msg.includes("ECONNREFUSED") || msg.includes("ETIMEDOUT")) {
48779
+ return {
48780
+ title: "API Error",
48781
+ message: msg,
48782
+ hint: "Check your internet connection and try again."
48783
+ };
48784
+ }
48785
+ if (msg.includes("ENOENT")) {
48786
+ const match = msg.match(/ENOENT.*'([^']+)'/);
48787
+ const path10 = match?.[1] ?? "unknown";
48788
+ return {
48789
+ title: "File Not Found",
48790
+ message: `Cannot find: ${path10}`,
48791
+ hint: "Check that the file or directory exists."
48792
+ };
48793
+ }
48794
+ if (msg.includes("EACCES") || msg.includes("EPERM")) {
48795
+ return {
48796
+ title: "Permission Denied",
48797
+ message: msg,
48798
+ hint: "Check file permissions or try running with appropriate access."
48799
+ };
48800
+ }
48801
+ if (msg.includes("EROFS")) {
48802
+ return {
48803
+ title: "Read-Only File System",
48804
+ message: msg,
48805
+ hint: "Cannot write to this location. Try a different path."
48806
+ };
48807
+ }
48808
+ if (msg.includes("database") || msg.includes("SQLite") || msg.includes("SQLITE")) {
48809
+ return {
48810
+ title: "Database Error",
48811
+ message: msg,
48812
+ hint: "Try removing the database file and starting fresh, or check disk space."
48813
+ };
48814
+ }
48815
+ if (msg.includes("context") && msg.includes("overflow")) {
48816
+ return {
48817
+ title: "Context Overflow",
48818
+ message: "Conversation history is too large",
48819
+ hint: "Run 'nuum --compact' to reduce context size."
48820
+ };
48821
+ }
48822
+ if (msg.includes("MCP") || msg.includes("mcp")) {
48823
+ return {
48824
+ title: "MCP Error",
48825
+ message: msg,
48826
+ hint: "Check your MCP server configuration in ~/.nuum/mcp.json"
48827
+ };
48828
+ }
48829
+ return {
48830
+ title: "Error",
48831
+ message: msg,
48832
+ details: error2.stack
48833
+ };
48834
+ }
48835
+ function printError(error2, options) {
48836
+ const info = categorizeError(error2);
48837
+ const boxWidth = 60;
48838
+ const topBorder = import_picocolors3.default.red("\u256D" + "\u2500".repeat(boxWidth - 2) + "\u256E");
48839
+ const bottomBorder = import_picocolors3.default.red("\u2570" + "\u2500".repeat(boxWidth - 2) + "\u256F");
48840
+ const write = (text3) => renderRawStderr(text3 + `
48841
+ `);
48842
+ write("");
48843
+ write(topBorder);
48844
+ write(import_picocolors3.default.red("\u2502") + " " + import_picocolors3.default.bold(import_picocolors3.default.red(info.title.padEnd(boxWidth - 4))) + " " + import_picocolors3.default.red("\u2502"));
48845
+ write(import_picocolors3.default.red("\u2502") + " ".repeat(boxWidth - 2) + import_picocolors3.default.red("\u2502"));
48846
+ const messageLines = wrapText(info.message, boxWidth - 4);
48847
+ for (const line of messageLines) {
48848
+ write(import_picocolors3.default.red("\u2502") + " " + line.padEnd(boxWidth - 4) + " " + import_picocolors3.default.red("\u2502"));
48849
+ }
48850
+ if (info.hint) {
48851
+ write(import_picocolors3.default.red("\u2502") + " ".repeat(boxWidth - 2) + import_picocolors3.default.red("\u2502"));
48852
+ const hintLines = wrapText(info.hint, boxWidth - 4);
48853
+ for (const line of hintLines) {
48854
+ write(import_picocolors3.default.red("\u2502") + " " + import_picocolors3.default.dim(line.padEnd(boxWidth - 4)) + " " + import_picocolors3.default.red("\u2502"));
48855
+ }
48856
+ }
48857
+ write(bottomBorder);
48858
+ write("");
48859
+ if (options?.verbose && info.details) {
48860
+ write(import_picocolors3.default.dim("Stack trace:"));
48861
+ write(import_picocolors3.default.dim(info.details));
48862
+ write("");
48863
+ }
48864
+ }
48865
+ function wrapText(text3, maxWidth) {
48866
+ const normalized = text3.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
48867
+ const words = normalized.split(" ");
48868
+ const lines = [];
48869
+ let currentLine = "";
48870
+ for (const word of words) {
48871
+ if (currentLine.length + word.length + 1 <= maxWidth) {
48872
+ currentLine += (currentLine ? " " : "") + word;
48873
+ } else {
48874
+ if (currentLine)
48875
+ lines.push(currentLine);
48876
+ currentLine = word;
48877
+ }
48878
+ }
48879
+ if (currentLine)
48880
+ lines.push(currentLine);
48881
+ return lines.length > 0 ? lines : [""];
48882
+ }
48883
+ function printSimpleError(message, hint) {
48884
+ const write = (text3) => renderRawStderr(text3 + `
48885
+ `);
48886
+ write("");
48887
+ write(`${import_picocolors3.default.red("\u2717")} ${import_picocolors3.default.bold("Error:")} ${message}`);
48888
+ if (hint) {
48889
+ write(` ${import_picocolors3.default.dim(hint)}`);
48890
+ }
48891
+ write("");
48892
+ }
47414
48893
 
47415
48894
  // src/cli/index.ts
47416
48895
  function parseCliArgs() {
@@ -47451,14 +48930,14 @@ ${VERSION_STRING}
47451
48930
  A coding agent with persistent memory
47452
48931
 
47453
48932
  Usage:
47454
- miriad-code -p "prompt" Run agent with a prompt
47455
- miriad-code -p "prompt" --verbose Show debug output
47456
- miriad-code --repl Start interactive REPL mode
47457
- miriad-code --stdio Start protocol server over stdin/stdout
47458
- miriad-code --inspect Show memory stats (no LLM call)
47459
- miriad-code --dump Show raw system prompt (no LLM call)
47460
- miriad-code --compact Force run compaction (distillation)
47461
- miriad-code --help Show this help
48933
+ nuum -p "prompt" Run agent with a prompt
48934
+ nuum -p "prompt" --verbose Show debug output
48935
+ nuum --repl Start interactive REPL mode
48936
+ nuum --stdio Start protocol server over stdin/stdout
48937
+ nuum --inspect Show memory stats (no LLM call)
48938
+ nuum --dump Show raw system prompt (no LLM call)
48939
+ nuum --compact Force run compaction (distillation)
48940
+ nuum --help Show this help
47462
48941
 
47463
48942
  Options:
47464
48943
  -p, --prompt <text> The prompt to send to the agent
@@ -47495,35 +48974,35 @@ JSON-RPC Mode (--stdio):
47495
48974
  Methods: run, cancel, status
47496
48975
 
47497
48976
  Examples:
47498
- miriad-code -p "What files are in src/"
47499
- miriad-code -p "Refactor the auth module" --verbose
47500
- miriad-code --repl
47501
- miriad-code --repl --db ./project.db
47502
- miriad-code -p "List todos" --format=json
47503
- miriad-code --inspect --db ./my-agent.db
47504
- miriad-code --dump
47505
- miriad-code --stdio --db ./agent.db
48977
+ nuum -p "What files are in src/"
48978
+ nuum -p "Refactor the auth module" --verbose
48979
+ nuum --repl
48980
+ nuum --repl --db ./project.db
48981
+ nuum -p "List todos" --format=json
48982
+ nuum --inspect --db ./my-agent.db
48983
+ nuum --dump
48984
+ nuum --stdio --db ./agent.db
47506
48985
  `);
47507
48986
  }
47508
48987
  async function main() {
47509
48988
  const options = parseCliArgs();
48989
+ if (options.verbose) {
48990
+ Log.setLevel("DEBUG");
48991
+ }
47510
48992
  if (options.help) {
47511
48993
  printHelp();
47512
48994
  process.exit(0);
47513
48995
  }
47514
48996
  if (options.version) {
47515
- console.log(VERSION_STRING);
48997
+ renderRaw(VERSION_STRING + `
48998
+ `);
47516
48999
  process.exit(0);
47517
49000
  }
47518
49001
  if (options.repl) {
47519
49002
  try {
47520
49003
  await runRepl({ dbPath: options.db });
47521
49004
  } catch (error2) {
47522
- if (error2 instanceof Error) {
47523
- console.error(`Error: ${error2.message}`);
47524
- } else {
47525
- console.error("Unknown error:", error2);
47526
- }
49005
+ printError(error2, { verbose: options.verbose });
47527
49006
  process.exit(1);
47528
49007
  }
47529
49008
  return;
@@ -47532,11 +49011,7 @@ async function main() {
47532
49011
  try {
47533
49012
  await runServer({ dbPath: options.db });
47534
49013
  } catch (error2) {
47535
- if (error2 instanceof Error) {
47536
- console.error(`Error: ${error2.message}`);
47537
- } else {
47538
- console.error("Unknown error:", error2);
47539
- }
49014
+ printError(error2, { verbose: options.verbose });
47540
49015
  process.exit(1);
47541
49016
  }
47542
49017
  return;
@@ -47546,11 +49021,7 @@ async function main() {
47546
49021
  await runInspect(options.db);
47547
49022
  process.exit(0);
47548
49023
  } catch (error2) {
47549
- if (error2 instanceof Error) {
47550
- console.error(`Error: ${error2.message}`);
47551
- } else {
47552
- console.error("Unknown error:", error2);
47553
- }
49024
+ printError(error2, { verbose: options.verbose });
47554
49025
  process.exit(1);
47555
49026
  }
47556
49027
  }
@@ -47559,11 +49030,7 @@ async function main() {
47559
49030
  await runDump(options.db);
47560
49031
  process.exit(0);
47561
49032
  } catch (error2) {
47562
- if (error2 instanceof Error) {
47563
- console.error(`Error: ${error2.message}`);
47564
- } else {
47565
- console.error("Unknown error:", error2);
47566
- }
49033
+ printError(error2, { verbose: options.verbose });
47567
49034
  process.exit(1);
47568
49035
  }
47569
49036
  }
@@ -47572,17 +49039,12 @@ async function main() {
47572
49039
  await runCompact(options.db);
47573
49040
  process.exit(0);
47574
49041
  } catch (error2) {
47575
- if (error2 instanceof Error) {
47576
- console.error(`Error: ${error2.message}`);
47577
- } else {
47578
- console.error("Unknown error:", error2);
47579
- }
49042
+ printError(error2, { verbose: options.verbose });
47580
49043
  process.exit(1);
47581
49044
  }
47582
49045
  }
47583
49046
  if (!options.prompt) {
47584
- console.error("Error: --prompt (-p) is required (or use --repl/--stdio/--inspect/--dump)");
47585
- console.error("Run with --help for usage information");
49047
+ printSimpleError("--prompt (-p) is required (or use --repl/--stdio/--inspect/--dump)", "Run with --help for usage information");
47586
49048
  process.exit(1);
47587
49049
  }
47588
49050
  try {
@@ -47593,14 +49055,7 @@ async function main() {
47593
49055
  format: options.format
47594
49056
  });
47595
49057
  } catch (error2) {
47596
- if (error2 instanceof Error) {
47597
- console.error(`Error: ${error2.message}`);
47598
- if (options.verbose && error2.stack) {
47599
- console.error(error2.stack);
47600
- }
47601
- } else {
47602
- console.error("Unknown error:", error2);
47603
- }
49058
+ printError(error2, { verbose: options.verbose });
47604
49059
  process.exit(1);
47605
49060
  }
47606
49061
  }