@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/README.md +4 -2
- package/dist/index.js +1981 -526
- package/package.json +4 -1
- package/src/storage/migrations/0004_background_tasks.sql +36 -0
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: () =>
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
22860
|
+
const keyStr = import_picocolors.default.dim(key + "=");
|
|
22760
22861
|
if (value instanceof Error)
|
|
22761
|
-
return
|
|
22862
|
+
return keyStr + import_picocolors.default.red(formatError(value));
|
|
22762
22863
|
if (typeof value === "object")
|
|
22763
|
-
return
|
|
22764
|
-
return
|
|
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
|
-
|
|
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
|
|
22879
|
+
write(build("DEBUG", message, extra));
|
|
22776
22880
|
}
|
|
22777
22881
|
},
|
|
22778
22882
|
info(message, extra) {
|
|
22779
22883
|
if (shouldLog("INFO")) {
|
|
22780
|
-
write("INFO
|
|
22884
|
+
write(build("INFO", message, extra));
|
|
22781
22885
|
}
|
|
22782
22886
|
},
|
|
22783
22887
|
error(message, extra) {
|
|
22784
22888
|
if (shouldLog("ERROR")) {
|
|
22785
|
-
write("ERROR
|
|
22889
|
+
write(build("ERROR", message, extra));
|
|
22786
22890
|
}
|
|
22787
22891
|
},
|
|
22788
22892
|
warn(message, extra) {
|
|
22789
22893
|
if (shouldLog("WARN")) {
|
|
22790
|
-
write("WARN
|
|
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", {
|
|
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 ({
|
|
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"], {
|
|
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/
|
|
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
|
-
|
|
34299
|
-
|
|
34300
|
-
|
|
34301
|
-
|
|
34302
|
-
|
|
34303
|
-
|
|
34304
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
34687
|
+
display = truncate(value, 50);
|
|
34341
34688
|
} else if (typeof value === "number" || typeof value === "boolean") {
|
|
34342
|
-
|
|
34689
|
+
display = String(value);
|
|
34343
34690
|
} else {
|
|
34344
|
-
|
|
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
|
|
34350
|
-
|
|
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
|
-
|
|
34361
|
-
|
|
34812
|
+
render({
|
|
34813
|
+
type: "tool_start",
|
|
34814
|
+
worker: this.worker,
|
|
34815
|
+
tool: name17,
|
|
34816
|
+
args
|
|
34817
|
+
});
|
|
34362
34818
|
}
|
|
34363
34819
|
toolResult(name17, summary) {
|
|
34364
|
-
|
|
34820
|
+
render({
|
|
34821
|
+
type: "tool_result",
|
|
34822
|
+
worker: this.worker,
|
|
34823
|
+
tool: name17,
|
|
34824
|
+
summary
|
|
34825
|
+
});
|
|
34365
34826
|
}
|
|
34366
34827
|
toolError(name17, error) {
|
|
34367
|
-
|
|
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
|
-
|
|
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,
|
|
34373
|
-
|
|
34374
|
-
|
|
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
|
-
|
|
34378
|
-
|
|
34379
|
-
|
|
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
|
-
|
|
34383
|
-
|
|
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
|
-
|
|
34869
|
+
render({
|
|
34870
|
+
type: "lifecycle",
|
|
34871
|
+
worker: this.worker,
|
|
34872
|
+
action: "complete",
|
|
34873
|
+
message: summary
|
|
34874
|
+
});
|
|
34387
34875
|
}
|
|
34388
34876
|
skip(reason) {
|
|
34389
|
-
|
|
34877
|
+
render({
|
|
34878
|
+
type: "lifecycle",
|
|
34879
|
+
worker: this.worker,
|
|
34880
|
+
action: "skip",
|
|
34881
|
+
message: `Skipped: ${reason}`
|
|
34882
|
+
});
|
|
34390
34883
|
}
|
|
34391
34884
|
thinking(thought) {
|
|
34392
|
-
|
|
34885
|
+
render({
|
|
34886
|
+
type: "thinking",
|
|
34887
|
+
worker: this.worker,
|
|
34888
|
+
message: thought
|
|
34889
|
+
});
|
|
34393
34890
|
}
|
|
34394
34891
|
info(message) {
|
|
34395
|
-
|
|
34892
|
+
render({
|
|
34893
|
+
type: "info",
|
|
34894
|
+
worker: this.worker,
|
|
34895
|
+
level: "info",
|
|
34896
|
+
message
|
|
34897
|
+
});
|
|
34396
34898
|
}
|
|
34397
34899
|
warn(message) {
|
|
34398
|
-
|
|
34900
|
+
render({
|
|
34901
|
+
type: "info",
|
|
34902
|
+
worker: this.worker,
|
|
34903
|
+
level: "warn",
|
|
34904
|
+
message
|
|
34905
|
+
});
|
|
34399
34906
|
}
|
|
34400
34907
|
error(message) {
|
|
34401
|
-
|
|
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
|
|
34406
|
-
|
|
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({
|
|
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({
|
|
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({
|
|
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", {
|
|
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", {
|
|
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", {
|
|
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, {
|
|
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", "
|
|
44321
|
-
const CONFIG_ENV_VAR = "
|
|
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: "
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
45965
|
-
description:
|
|
45966
|
-
parameters:
|
|
45967
|
-
execute: async (args, { toolCallId }) => safeExecute("
|
|
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.
|
|
45970
|
-
description:
|
|
45971
|
-
parameters:
|
|
45972
|
-
execute: async (args, { toolCallId }) => safeExecute("
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
46004
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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(`
|
|
46222
|
-
|
|
46223
|
-
this.log(`
|
|
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 =
|
|
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}
|
|
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
|
-
|
|
46247
|
-
this.log(`
|
|
46248
|
-
|
|
46249
|
-
|
|
46250
|
-
this.log(`
|
|
46251
|
-
this.log(` /
|
|
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
|
|
46256
|
-
|
|
46257
|
-
this.log(
|
|
46258
|
-
|
|
46259
|
-
this.log(
|
|
46260
|
-
this.log(
|
|
46261
|
-
this.log(
|
|
46262
|
-
this.log(
|
|
46263
|
-
this.log(
|
|
46264
|
-
this.log("
|
|
46265
|
-
this.log(
|
|
46266
|
-
this.log(
|
|
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
|
|
46276
|
-
|
|
46277
|
-
|
|
46278
|
-
|
|
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(`
|
|
46283
|
-
|
|
46284
|
-
this.log(`
|
|
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 =
|
|
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}
|
|
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
|
-
|
|
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
|
|
46313
|
-
this.log(`
|
|
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
|
-
|
|
46329
|
-
this.log(
|
|
46330
|
-
|
|
46331
|
-
this.log(
|
|
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
|
-
|
|
47651
|
+
renderRaw(JSON.stringify(output, null, 2) + `
|
|
47652
|
+
`);
|
|
46468
47653
|
} else {
|
|
46469
|
-
|
|
47654
|
+
render({ type: "text", text: result.response });
|
|
46470
47655
|
}
|
|
47656
|
+
renderEnd();
|
|
46471
47657
|
} catch (error2) {
|
|
46472
|
-
|
|
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
|
|
46492
|
-
var
|
|
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
|
-
|
|
46536
|
-
|
|
46537
|
-
const
|
|
46538
|
-
const
|
|
46539
|
-
const
|
|
46540
|
-
|
|
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
|
-
|
|
46619
|
-
|
|
46620
|
-
|
|
46621
|
-
|
|
46622
|
-
|
|
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
|
-
|
|
47806
|
+
log13(renderLTMTree(ltmTree));
|
|
46625
47807
|
} else {
|
|
46626
|
-
|
|
46627
|
-
}
|
|
46628
|
-
|
|
46629
|
-
|
|
46630
|
-
|
|
46631
|
-
|
|
46632
|
-
|
|
46633
|
-
|
|
46634
|
-
|
|
46635
|
-
|
|
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
|
-
|
|
47820
|
+
log13(`${styles.label("Summaries:")}`);
|
|
46638
47821
|
for (const orderStats of stats.summariesByOrder) {
|
|
46639
|
-
|
|
47822
|
+
log13(` ${import_picocolors3.default.dim(`Order-${orderStats.order}:`)} ${fmt(orderStats.count)} (${fmt(orderStats.totalTokens)} tokens)`);
|
|
46640
47823
|
}
|
|
46641
47824
|
} else {
|
|
46642
|
-
|
|
47825
|
+
log13(`${styles.label("Summaries:")} ${import_picocolors3.default.dim("none")}`);
|
|
46643
47826
|
}
|
|
46644
|
-
|
|
47827
|
+
blank();
|
|
46645
47828
|
const needsCompaction = stats.viewTotalTokens > stats.compactionThreshold;
|
|
46646
|
-
const compactionStatus = needsCompaction ? " (compaction needed)" : "";
|
|
46647
|
-
|
|
46648
|
-
|
|
46649
|
-
|
|
46650
|
-
|
|
46651
|
-
|
|
46652
|
-
|
|
46653
|
-
|
|
46654
|
-
|
|
46655
|
-
|
|
46656
|
-
|
|
46657
|
-
|
|
46658
|
-
|
|
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
|
-
|
|
47844
|
+
log13(`${styles.label("Tasks:")} ${fmt(totalTasks)} total`);
|
|
46662
47845
|
if (stats.tasksPending > 0)
|
|
46663
|
-
|
|
47846
|
+
log13(` ${import_picocolors3.default.dim("Pending:")} ${fmt(stats.tasksPending)}`);
|
|
46664
47847
|
if (stats.tasksInProgress > 0)
|
|
46665
|
-
|
|
47848
|
+
log13(` ${styles.warning("In progress:")} ${fmt(stats.tasksInProgress)}`);
|
|
46666
47849
|
if (stats.tasksCompleted > 0)
|
|
46667
|
-
|
|
47850
|
+
log13(` ${styles.success("Completed:")} ${fmt(stats.tasksCompleted)}`);
|
|
46668
47851
|
if (stats.tasksBlocked > 0)
|
|
46669
|
-
|
|
47852
|
+
log13(` ${styles.error("Blocked:")} ${fmt(stats.tasksBlocked)}`);
|
|
46670
47853
|
} else {
|
|
46671
|
-
|
|
47854
|
+
log13(`${styles.label("Tasks:")} ${import_picocolors3.default.dim("none")}`);
|
|
46672
47855
|
}
|
|
46673
|
-
|
|
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}]
|
|
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
|
-
|
|
46722
|
-
|
|
46723
|
-
|
|
46724
|
-
|
|
46725
|
-
|
|
46726
|
-
|
|
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
|
-
|
|
46729
|
-
|
|
47911
|
+
blank();
|
|
47912
|
+
log13(styles.subheader(`=== CONVERSATION (${conversationTurns.length} turns) ===`));
|
|
46730
47913
|
for (const turn of conversationTurns) {
|
|
46731
|
-
|
|
46732
|
-
|
|
46733
|
-
|
|
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
|
-
|
|
46737
|
-
|
|
47920
|
+
blank();
|
|
47921
|
+
log13(styles.subheader("=== CONVERSATION (empty) ==="));
|
|
46738
47922
|
}
|
|
46739
|
-
|
|
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
|
-
|
|
46749
|
-
|
|
46750
|
-
|
|
46751
|
-
|
|
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
|
-
|
|
47937
|
+
log13(import_picocolors3.default.dim(`Already under target, but running anyway (forced)...`));
|
|
46754
47938
|
} else {
|
|
46755
|
-
|
|
47939
|
+
log13(`Running memory curation...`);
|
|
46756
47940
|
}
|
|
46757
|
-
|
|
47941
|
+
blank();
|
|
46758
47942
|
const result = await runMemoryCuration(storage, { force: true });
|
|
46759
47943
|
if (!result.ran) {
|
|
46760
|
-
|
|
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
|
-
|
|
47950
|
+
log13(styles.subheader(`LTM Consolidation:`));
|
|
46767
47951
|
if (changes > 0) {
|
|
46768
|
-
|
|
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
|
-
|
|
47954
|
+
log13(import_picocolors3.default.dim(` No changes needed`));
|
|
46771
47955
|
}
|
|
46772
|
-
|
|
47956
|
+
blank();
|
|
46773
47957
|
}
|
|
46774
47958
|
if (result.distillation) {
|
|
46775
47959
|
const d = result.distillation;
|
|
46776
|
-
|
|
46777
|
-
|
|
46778
|
-
|
|
46779
|
-
|
|
46780
|
-
|
|
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: {
|
|
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 {
|
|
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 ? {
|
|
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
|
|
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
|
-
|
|
46893
|
-
|
|
46894
|
-
|
|
46895
|
-
|
|
46896
|
-
|
|
46897
|
-
|
|
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
|
-
|
|
48150
|
+
log14.info("interrupting current turn", {
|
|
48151
|
+
sessionId: this.currentTurn.sessionId
|
|
48152
|
+
});
|
|
46936
48153
|
this.currentTurn.abortController.abort();
|
|
46937
|
-
this.send(systemMessage("interrupted", {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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", {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47146
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
47176
|
-
this.
|
|
47177
|
-
|
|
47178
|
-
|
|
48517
|
+
if (this.isRunning) {
|
|
48518
|
+
this.server.interrupt();
|
|
48519
|
+
renderRaw(`
|
|
48520
|
+
`);
|
|
48521
|
+
renderRaw(styles.warning("^C - Request cancelled") + `
|
|
47179
48522
|
`);
|
|
47180
48523
|
} else {
|
|
47181
|
-
|
|
47182
|
-
|
|
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
|
-
|
|
47190
|
-
|
|
47191
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47204
|
-
|
|
47205
|
-
|
|
47206
|
-
|
|
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
|
-
|
|
47230
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47256
|
-
|
|
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
|
-
|
|
47262
|
-
|
|
47263
|
-
|
|
47264
|
-
|
|
47265
|
-
|
|
47266
|
-
|
|
47267
|
-
|
|
47268
|
-
|
|
47269
|
-
|
|
47270
|
-
|
|
47271
|
-
|
|
47272
|
-
|
|
47273
|
-
|
|
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
|
-
|
|
47278
|
-
|
|
47279
|
-
|
|
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
|
-
|
|
47289
|
-
|
|
47290
|
-
|
|
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
|
-
|
|
47300
|
-
|
|
48657
|
+
setReplRunning(false);
|
|
48658
|
+
renderEnd();
|
|
47301
48659
|
this.rl?.prompt();
|
|
47302
48660
|
}
|
|
47303
48661
|
}
|
|
47304
|
-
|
|
47305
|
-
|
|
47306
|
-
|
|
47307
|
-
|
|
47308
|
-
|
|
47309
|
-
|
|
47310
|
-
|
|
47311
|
-
|
|
47312
|
-
|
|
47313
|
-
|
|
47314
|
-
|
|
47315
|
-
|
|
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
|
-
|
|
47321
|
-
|
|
47322
|
-
|
|
47323
|
-
|
|
47324
|
-
|
|
47325
|
-
|
|
47326
|
-
|
|
47327
|
-
|
|
47328
|
-
|
|
47329
|
-
|
|
47330
|
-
|
|
47331
|
-
|
|
47332
|
-
|
|
47333
|
-
|
|
47334
|
-
|
|
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
|
-
|
|
47341
|
-
|
|
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
|
-
}
|
|
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.
|
|
47412
|
-
var GIT_HASH = "
|
|
47413
|
-
var VERSION_STRING = `
|
|
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
|
-
|
|
47455
|
-
|
|
47456
|
-
|
|
47457
|
-
|
|
47458
|
-
|
|
47459
|
-
|
|
47460
|
-
|
|
47461
|
-
|
|
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
|
-
|
|
47499
|
-
|
|
47500
|
-
|
|
47501
|
-
|
|
47502
|
-
|
|
47503
|
-
|
|
47504
|
-
|
|
47505
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|