@sanity-labs/nuum 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +939 -136
- package/package.json +1 -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) => {
|
|
@@ -17401,7 +17401,10 @@ __export(exports_schema, {
|
|
|
17401
17401
|
sessionConfig: () => sessionConfig,
|
|
17402
17402
|
presentState: () => presentState,
|
|
17403
17403
|
ltmEntries: () => ltmEntries,
|
|
17404
|
-
|
|
17404
|
+
backgroundTasks: () => backgroundTasks,
|
|
17405
|
+
backgroundTaskQueue: () => backgroundTaskQueue,
|
|
17406
|
+
backgroundReports: () => backgroundReports,
|
|
17407
|
+
alarms: () => alarms
|
|
17405
17408
|
});
|
|
17406
17409
|
|
|
17407
17410
|
// node_modules/drizzle-orm/entity.js
|
|
@@ -18575,6 +18578,9 @@ function and(...unfilteredConditions) {
|
|
|
18575
18578
|
var gte = (left, right) => {
|
|
18576
18579
|
return sql`${left} >= ${bindIfParam(right, left)}`;
|
|
18577
18580
|
};
|
|
18581
|
+
var lt = (left, right) => {
|
|
18582
|
+
return sql`${left} < ${bindIfParam(right, left)}`;
|
|
18583
|
+
};
|
|
18578
18584
|
var lte = (left, right) => {
|
|
18579
18585
|
return sql`${left} <= ${bindIfParam(right, left)}`;
|
|
18580
18586
|
};
|
|
@@ -18704,6 +18710,34 @@ var backgroundReports = sqliteTable("background_reports", {
|
|
|
18704
18710
|
}, (table) => [
|
|
18705
18711
|
index("idx_background_reports_unsurfaced").on(table.surfacedAt)
|
|
18706
18712
|
]);
|
|
18713
|
+
var backgroundTasks = sqliteTable("background_tasks", {
|
|
18714
|
+
id: text("id").primaryKey(),
|
|
18715
|
+
type: text("type").notNull(),
|
|
18716
|
+
description: text("description").notNull(),
|
|
18717
|
+
status: text("status").notNull(),
|
|
18718
|
+
createdAt: text("created_at").notNull(),
|
|
18719
|
+
completedAt: text("completed_at"),
|
|
18720
|
+
result: text("result"),
|
|
18721
|
+
error: text("error")
|
|
18722
|
+
}, (table) => [
|
|
18723
|
+
index("idx_background_tasks_status").on(table.status)
|
|
18724
|
+
]);
|
|
18725
|
+
var backgroundTaskQueue = sqliteTable("background_task_queue", {
|
|
18726
|
+
id: text("id").primaryKey(),
|
|
18727
|
+
taskId: text("task_id").notNull(),
|
|
18728
|
+
createdAt: text("created_at").notNull(),
|
|
18729
|
+
content: text("content").notNull()
|
|
18730
|
+
}, (table) => [
|
|
18731
|
+
index("idx_background_task_queue_created").on(table.createdAt)
|
|
18732
|
+
]);
|
|
18733
|
+
var alarms = sqliteTable("alarms", {
|
|
18734
|
+
id: text("id").primaryKey(),
|
|
18735
|
+
firesAt: text("fires_at").notNull(),
|
|
18736
|
+
note: text("note").notNull(),
|
|
18737
|
+
fired: integer("fired").notNull().default(0)
|
|
18738
|
+
}, (table) => [
|
|
18739
|
+
index("idx_alarms_fires_at").on(table.firesAt)
|
|
18740
|
+
]);
|
|
18707
18741
|
|
|
18708
18742
|
// src/storage/db.ts
|
|
18709
18743
|
var isBun = typeof globalThis.Bun !== "undefined";
|
|
@@ -23468,6 +23502,9 @@ var Identifier;
|
|
|
23468
23502
|
entry: "ent",
|
|
23469
23503
|
worker: "wrk",
|
|
23470
23504
|
report: "rpt",
|
|
23505
|
+
bgtask: "bgt",
|
|
23506
|
+
queue: "que",
|
|
23507
|
+
alarm: "alm",
|
|
23471
23508
|
session: "ses",
|
|
23472
23509
|
toolcall: "tcl"
|
|
23473
23510
|
};
|
|
@@ -23612,6 +23649,159 @@ function createBackgroundStorage(db) {
|
|
|
23612
23649
|
};
|
|
23613
23650
|
}
|
|
23614
23651
|
|
|
23652
|
+
// src/storage/tasks.ts
|
|
23653
|
+
function createTasksStorage(db) {
|
|
23654
|
+
return {
|
|
23655
|
+
async createTask(input) {
|
|
23656
|
+
const id = Identifier.ascending("bgtask");
|
|
23657
|
+
const now = new Date().toISOString();
|
|
23658
|
+
await db.insert(backgroundTasks).values({
|
|
23659
|
+
id,
|
|
23660
|
+
type: input.type,
|
|
23661
|
+
description: input.description,
|
|
23662
|
+
status: "running",
|
|
23663
|
+
createdAt: now
|
|
23664
|
+
});
|
|
23665
|
+
return id;
|
|
23666
|
+
},
|
|
23667
|
+
async getTask(id) {
|
|
23668
|
+
const rows = await db.select().from(backgroundTasks).where(eq(backgroundTasks.id, id)).limit(1);
|
|
23669
|
+
if (rows.length === 0)
|
|
23670
|
+
return null;
|
|
23671
|
+
const row = rows[0];
|
|
23672
|
+
return {
|
|
23673
|
+
id: row.id,
|
|
23674
|
+
type: row.type,
|
|
23675
|
+
description: row.description,
|
|
23676
|
+
status: row.status,
|
|
23677
|
+
createdAt: row.createdAt,
|
|
23678
|
+
completedAt: row.completedAt,
|
|
23679
|
+
result: row.result ? JSON.parse(row.result) : null,
|
|
23680
|
+
error: row.error
|
|
23681
|
+
};
|
|
23682
|
+
},
|
|
23683
|
+
async listTasks(options) {
|
|
23684
|
+
const limit = options?.limit ?? 50;
|
|
23685
|
+
let query = db.select().from(backgroundTasks);
|
|
23686
|
+
if (options?.status) {
|
|
23687
|
+
query = query.where(eq(backgroundTasks.status, options.status));
|
|
23688
|
+
}
|
|
23689
|
+
const rows = await query.orderBy(backgroundTasks.createdAt).limit(limit);
|
|
23690
|
+
return rows.map((row) => ({
|
|
23691
|
+
id: row.id,
|
|
23692
|
+
type: row.type,
|
|
23693
|
+
description: row.description,
|
|
23694
|
+
status: row.status,
|
|
23695
|
+
createdAt: row.createdAt,
|
|
23696
|
+
completedAt: row.completedAt,
|
|
23697
|
+
result: row.result ? JSON.parse(row.result) : null,
|
|
23698
|
+
error: row.error
|
|
23699
|
+
}));
|
|
23700
|
+
},
|
|
23701
|
+
async completeTask(id, result) {
|
|
23702
|
+
const now = new Date().toISOString();
|
|
23703
|
+
await db.update(backgroundTasks).set({
|
|
23704
|
+
status: "completed",
|
|
23705
|
+
completedAt: now,
|
|
23706
|
+
result: JSON.stringify(result)
|
|
23707
|
+
}).where(eq(backgroundTasks.id, id));
|
|
23708
|
+
},
|
|
23709
|
+
async failTask(id, error) {
|
|
23710
|
+
const now = new Date().toISOString();
|
|
23711
|
+
await db.update(backgroundTasks).set({
|
|
23712
|
+
status: "failed",
|
|
23713
|
+
completedAt: now,
|
|
23714
|
+
error
|
|
23715
|
+
}).where(eq(backgroundTasks.id, id));
|
|
23716
|
+
},
|
|
23717
|
+
async recoverKilledTasks() {
|
|
23718
|
+
const runningTasks = await db.select().from(backgroundTasks).where(eq(backgroundTasks.status, "running"));
|
|
23719
|
+
if (runningTasks.length > 0) {
|
|
23720
|
+
const now = new Date().toISOString();
|
|
23721
|
+
await db.update(backgroundTasks).set({
|
|
23722
|
+
status: "killed",
|
|
23723
|
+
completedAt: now
|
|
23724
|
+
}).where(eq(backgroundTasks.status, "running"));
|
|
23725
|
+
}
|
|
23726
|
+
return runningTasks.map((row) => ({
|
|
23727
|
+
id: row.id,
|
|
23728
|
+
type: row.type,
|
|
23729
|
+
description: row.description,
|
|
23730
|
+
status: "killed",
|
|
23731
|
+
createdAt: row.createdAt,
|
|
23732
|
+
completedAt: row.completedAt,
|
|
23733
|
+
result: null,
|
|
23734
|
+
error: null
|
|
23735
|
+
}));
|
|
23736
|
+
},
|
|
23737
|
+
async queueResult(taskId, content) {
|
|
23738
|
+
const id = Identifier.ascending("bgtask");
|
|
23739
|
+
const now = new Date().toISOString();
|
|
23740
|
+
await db.insert(backgroundTaskQueue).values({
|
|
23741
|
+
id,
|
|
23742
|
+
taskId,
|
|
23743
|
+
createdAt: now,
|
|
23744
|
+
content
|
|
23745
|
+
});
|
|
23746
|
+
},
|
|
23747
|
+
async drainQueue() {
|
|
23748
|
+
const rows = await db.select().from(backgroundTaskQueue).orderBy(backgroundTaskQueue.createdAt);
|
|
23749
|
+
if (rows.length === 0)
|
|
23750
|
+
return [];
|
|
23751
|
+
const ids = rows.map((r) => r.id);
|
|
23752
|
+
for (const id of ids) {
|
|
23753
|
+
await db.delete(backgroundTaskQueue).where(eq(backgroundTaskQueue.id, id));
|
|
23754
|
+
}
|
|
23755
|
+
return rows.map((row) => ({
|
|
23756
|
+
id: row.id,
|
|
23757
|
+
taskId: row.taskId,
|
|
23758
|
+
createdAt: row.createdAt,
|
|
23759
|
+
content: row.content
|
|
23760
|
+
}));
|
|
23761
|
+
},
|
|
23762
|
+
async hasQueuedResults() {
|
|
23763
|
+
const rows = await db.select({ id: backgroundTaskQueue.id }).from(backgroundTaskQueue).limit(1);
|
|
23764
|
+
return rows.length > 0;
|
|
23765
|
+
},
|
|
23766
|
+
async createAlarm(input) {
|
|
23767
|
+
const id = Identifier.ascending("bgtask");
|
|
23768
|
+
await db.insert(alarms).values({
|
|
23769
|
+
id,
|
|
23770
|
+
firesAt: input.firesAt,
|
|
23771
|
+
note: input.note,
|
|
23772
|
+
fired: 0
|
|
23773
|
+
});
|
|
23774
|
+
return id;
|
|
23775
|
+
},
|
|
23776
|
+
async getDueAlarms() {
|
|
23777
|
+
const now = new Date().toISOString();
|
|
23778
|
+
const rows = await db.select().from(alarms).where(and(eq(alarms.fired, 0), lt(alarms.firesAt, now))).orderBy(alarms.firesAt);
|
|
23779
|
+
return rows.map((row) => ({
|
|
23780
|
+
id: row.id,
|
|
23781
|
+
firesAt: row.firesAt,
|
|
23782
|
+
note: row.note,
|
|
23783
|
+
fired: row.fired === 1
|
|
23784
|
+
}));
|
|
23785
|
+
},
|
|
23786
|
+
async markAlarmFired(id) {
|
|
23787
|
+
await db.update(alarms).set({ fired: 1 }).where(eq(alarms.id, id));
|
|
23788
|
+
},
|
|
23789
|
+
async listAlarms(options) {
|
|
23790
|
+
let query = db.select().from(alarms);
|
|
23791
|
+
if (!options?.includeFired) {
|
|
23792
|
+
query = query.where(eq(alarms.fired, 0));
|
|
23793
|
+
}
|
|
23794
|
+
const rows = await query.orderBy(alarms.firesAt);
|
|
23795
|
+
return rows.map((row) => ({
|
|
23796
|
+
id: row.id,
|
|
23797
|
+
firesAt: row.firesAt,
|
|
23798
|
+
note: row.note,
|
|
23799
|
+
fired: row.fired === 1
|
|
23800
|
+
}));
|
|
23801
|
+
}
|
|
23802
|
+
};
|
|
23803
|
+
}
|
|
23804
|
+
|
|
23615
23805
|
// src/storage/index.ts
|
|
23616
23806
|
function createStorage(dbPath, options) {
|
|
23617
23807
|
const { mkdirSync } = __require("fs");
|
|
@@ -23631,6 +23821,7 @@ function createStorageFromDb(db) {
|
|
|
23631
23821
|
workers: createWorkerStorage(db),
|
|
23632
23822
|
session: createSessionStorage(db),
|
|
23633
23823
|
background: createBackgroundStorage(db),
|
|
23824
|
+
tasks: createTasksStorage(db),
|
|
23634
23825
|
_db: db
|
|
23635
23826
|
};
|
|
23636
23827
|
}
|
|
@@ -45105,6 +45296,488 @@ var LTMTools = {
|
|
|
45105
45296
|
...LTMReadOnlyTools,
|
|
45106
45297
|
...LTMWriteTools
|
|
45107
45298
|
};
|
|
45299
|
+
// src/tool/list-tasks.ts
|
|
45300
|
+
function formatElapsed(startTime) {
|
|
45301
|
+
const start = new Date(startTime).getTime();
|
|
45302
|
+
const now2 = Date.now();
|
|
45303
|
+
const elapsed = Math.floor((now2 - start) / 1000);
|
|
45304
|
+
if (elapsed < 60)
|
|
45305
|
+
return `${elapsed}s`;
|
|
45306
|
+
if (elapsed < 3600)
|
|
45307
|
+
return `${Math.floor(elapsed / 60)}m ${elapsed % 60}s`;
|
|
45308
|
+
const hours = Math.floor(elapsed / 3600);
|
|
45309
|
+
const mins = Math.floor(elapsed % 3600 / 60);
|
|
45310
|
+
return `${hours}h ${mins}m`;
|
|
45311
|
+
}
|
|
45312
|
+
function formatTimeUntil(firesAt) {
|
|
45313
|
+
const fires = new Date(firesAt).getTime();
|
|
45314
|
+
const now2 = Date.now();
|
|
45315
|
+
const remaining = Math.floor((fires - now2) / 1000);
|
|
45316
|
+
if (remaining <= 0)
|
|
45317
|
+
return "due now";
|
|
45318
|
+
if (remaining < 60)
|
|
45319
|
+
return `in ${remaining}s`;
|
|
45320
|
+
if (remaining < 3600)
|
|
45321
|
+
return `in ${Math.floor(remaining / 60)}m`;
|
|
45322
|
+
const hours = Math.floor(remaining / 3600);
|
|
45323
|
+
const mins = Math.floor(remaining % 3600 / 60);
|
|
45324
|
+
return `in ${hours}h ${mins}m`;
|
|
45325
|
+
}
|
|
45326
|
+
function formatTask(task) {
|
|
45327
|
+
const elapsed = formatElapsed(task.createdAt);
|
|
45328
|
+
const statusIcon = {
|
|
45329
|
+
running: "\uD83D\uDD04",
|
|
45330
|
+
completed: "\u2705",
|
|
45331
|
+
failed: "\u274C",
|
|
45332
|
+
killed: "\uD83D\uDC80"
|
|
45333
|
+
}[task.status];
|
|
45334
|
+
let line = `${statusIcon} #${task.id.slice(-8)} ${task.type}: "${task.description}" (${task.status}, ${elapsed})`;
|
|
45335
|
+
if (task.error) {
|
|
45336
|
+
line += `
|
|
45337
|
+
Error: ${task.error}`;
|
|
45338
|
+
}
|
|
45339
|
+
return line;
|
|
45340
|
+
}
|
|
45341
|
+
function formatAlarm(alarm) {
|
|
45342
|
+
const timeUntil = formatTimeUntil(alarm.firesAt);
|
|
45343
|
+
return `\u23F0 #${alarm.id.slice(-8)}: "${alarm.note}" (${timeUntil})`;
|
|
45344
|
+
}
|
|
45345
|
+
var DESCRIPTION5 = `List background tasks and alarms.
|
|
45346
|
+
|
|
45347
|
+
Shows:
|
|
45348
|
+
- Running background tasks (research, reflect)
|
|
45349
|
+
- Scheduled alarms (notes to self)
|
|
45350
|
+
- Recent completed/failed tasks (if includeCompleted=true)
|
|
45351
|
+
|
|
45352
|
+
Use this to see what's in progress or scheduled.`;
|
|
45353
|
+
var parameters6 = exports_external.object({
|
|
45354
|
+
includeCompleted: exports_external.boolean().optional().describe("Include completed/failed tasks (default: false, only shows running)")
|
|
45355
|
+
});
|
|
45356
|
+
var ListTasksTool = Tool.define("list_tasks", {
|
|
45357
|
+
description: DESCRIPTION5,
|
|
45358
|
+
parameters: parameters6,
|
|
45359
|
+
async execute({ includeCompleted }, ctx) {
|
|
45360
|
+
const tasksStorage = ctx.extra?.tasks;
|
|
45361
|
+
if (!tasksStorage) {
|
|
45362
|
+
return {
|
|
45363
|
+
output: "Error: Tasks storage not available",
|
|
45364
|
+
title: "List tasks failed",
|
|
45365
|
+
metadata: {
|
|
45366
|
+
runningCount: 0,
|
|
45367
|
+
alarmCount: 0,
|
|
45368
|
+
completedCount: 0
|
|
45369
|
+
}
|
|
45370
|
+
};
|
|
45371
|
+
}
|
|
45372
|
+
const allTasks = await tasksStorage.listTasks({ limit: 20 });
|
|
45373
|
+
const runningTasks = allTasks.filter((t) => t.status === "running");
|
|
45374
|
+
const completedTasks = allTasks.filter((t) => t.status !== "running");
|
|
45375
|
+
const alarms2 = await tasksStorage.listAlarms();
|
|
45376
|
+
const lines = [];
|
|
45377
|
+
if (runningTasks.length > 0) {
|
|
45378
|
+
lines.push("**Running Tasks:**");
|
|
45379
|
+
for (const task of runningTasks) {
|
|
45380
|
+
lines.push(formatTask(task));
|
|
45381
|
+
}
|
|
45382
|
+
}
|
|
45383
|
+
if (alarms2.length > 0) {
|
|
45384
|
+
if (lines.length > 0)
|
|
45385
|
+
lines.push("");
|
|
45386
|
+
lines.push("**Scheduled Alarms:**");
|
|
45387
|
+
for (const alarm of alarms2) {
|
|
45388
|
+
lines.push(formatAlarm(alarm));
|
|
45389
|
+
}
|
|
45390
|
+
}
|
|
45391
|
+
if (includeCompleted && completedTasks.length > 0) {
|
|
45392
|
+
if (lines.length > 0)
|
|
45393
|
+
lines.push("");
|
|
45394
|
+
lines.push("**Recent Completed/Failed:**");
|
|
45395
|
+
for (const task of completedTasks.slice(0, 10)) {
|
|
45396
|
+
lines.push(formatTask(task));
|
|
45397
|
+
}
|
|
45398
|
+
}
|
|
45399
|
+
if (lines.length === 0) {
|
|
45400
|
+
return {
|
|
45401
|
+
output: "No background tasks or alarms.",
|
|
45402
|
+
title: "No tasks",
|
|
45403
|
+
metadata: {
|
|
45404
|
+
runningCount: 0,
|
|
45405
|
+
alarmCount: 0,
|
|
45406
|
+
completedCount: 0
|
|
45407
|
+
}
|
|
45408
|
+
};
|
|
45409
|
+
}
|
|
45410
|
+
return {
|
|
45411
|
+
output: lines.join(`
|
|
45412
|
+
`),
|
|
45413
|
+
title: `${runningTasks.length} running, ${alarms2.length} alarms`,
|
|
45414
|
+
metadata: {
|
|
45415
|
+
runningCount: runningTasks.length,
|
|
45416
|
+
alarmCount: alarms2.length,
|
|
45417
|
+
completedCount: completedTasks.length
|
|
45418
|
+
}
|
|
45419
|
+
};
|
|
45420
|
+
}
|
|
45421
|
+
});
|
|
45422
|
+
// src/tool/set-alarm.ts
|
|
45423
|
+
function parseDelay(delay2) {
|
|
45424
|
+
const match = delay2.match(/^(\d+(?:\.\d+)?)\s*(s|sec|second|seconds|m|min|minute|minutes|h|hr|hour|hours)$/i);
|
|
45425
|
+
if (!match)
|
|
45426
|
+
return null;
|
|
45427
|
+
const value = parseFloat(match[1]);
|
|
45428
|
+
const unit = match[2].toLowerCase();
|
|
45429
|
+
switch (unit) {
|
|
45430
|
+
case "s":
|
|
45431
|
+
case "sec":
|
|
45432
|
+
case "second":
|
|
45433
|
+
case "seconds":
|
|
45434
|
+
return value * 1000;
|
|
45435
|
+
case "m":
|
|
45436
|
+
case "min":
|
|
45437
|
+
case "minute":
|
|
45438
|
+
case "minutes":
|
|
45439
|
+
return value * 60 * 1000;
|
|
45440
|
+
case "h":
|
|
45441
|
+
case "hr":
|
|
45442
|
+
case "hour":
|
|
45443
|
+
case "hours":
|
|
45444
|
+
return value * 60 * 60 * 1000;
|
|
45445
|
+
default:
|
|
45446
|
+
return null;
|
|
45447
|
+
}
|
|
45448
|
+
}
|
|
45449
|
+
var DESCRIPTION6 = `Schedule a future reminder (alarm).
|
|
45450
|
+
|
|
45451
|
+
When the alarm fires, you'll receive a message with your note.
|
|
45452
|
+
Use this to:
|
|
45453
|
+
- Check back on something later ("check if deploy succeeded")
|
|
45454
|
+
- Set a reminder for a task
|
|
45455
|
+
- Schedule periodic check-ins
|
|
45456
|
+
|
|
45457
|
+
Examples:
|
|
45458
|
+
- set_alarm({ delay: "5m", note: "check deployment status" })
|
|
45459
|
+
- set_alarm({ delay: "1h", note: "follow up on PR review" })
|
|
45460
|
+
- set_alarm({ delay: "30s", note: "verify test results" })`;
|
|
45461
|
+
var parameters7 = exports_external.object({
|
|
45462
|
+
delay: exports_external.string().describe('How long until the alarm fires (e.g., "5m", "1h", "30s")'),
|
|
45463
|
+
note: exports_external.string().describe("The reminder message you'll receive when the alarm fires")
|
|
45464
|
+
});
|
|
45465
|
+
var SetAlarmTool = Tool.define("set_alarm", {
|
|
45466
|
+
description: DESCRIPTION6,
|
|
45467
|
+
parameters: parameters7,
|
|
45468
|
+
async execute({ delay: delay2, note }, ctx) {
|
|
45469
|
+
const tasksStorage = ctx.extra?.tasks;
|
|
45470
|
+
if (!tasksStorage) {
|
|
45471
|
+
return {
|
|
45472
|
+
output: "Error: Tasks storage not available",
|
|
45473
|
+
title: "Set alarm failed",
|
|
45474
|
+
metadata: {
|
|
45475
|
+
alarmId: "",
|
|
45476
|
+
firesAt: "",
|
|
45477
|
+
delayMs: 0
|
|
45478
|
+
}
|
|
45479
|
+
};
|
|
45480
|
+
}
|
|
45481
|
+
const delayMs = parseDelay(delay2);
|
|
45482
|
+
if (delayMs === null) {
|
|
45483
|
+
return {
|
|
45484
|
+
output: `Invalid delay format: "${delay2}". Use formats like "5m", "1h", "30s".`,
|
|
45485
|
+
title: "Invalid delay",
|
|
45486
|
+
metadata: {
|
|
45487
|
+
alarmId: "",
|
|
45488
|
+
firesAt: "",
|
|
45489
|
+
delayMs: 0
|
|
45490
|
+
}
|
|
45491
|
+
};
|
|
45492
|
+
}
|
|
45493
|
+
const firesAt = new Date(Date.now() + delayMs).toISOString();
|
|
45494
|
+
const alarmId = await tasksStorage.createAlarm({
|
|
45495
|
+
firesAt,
|
|
45496
|
+
note
|
|
45497
|
+
});
|
|
45498
|
+
const displayDelay = delayMs >= 3600000 ? `${Math.round(delayMs / 3600000 * 10) / 10}h` : delayMs >= 60000 ? `${Math.round(delayMs / 60000)}m` : `${Math.round(delayMs / 1000)}s`;
|
|
45499
|
+
return {
|
|
45500
|
+
output: `\u23F0 Alarm set for ${displayDelay} from now.
|
|
45501
|
+
Note: "${note}"
|
|
45502
|
+
Fires at: ${firesAt}`,
|
|
45503
|
+
title: `Alarm in ${displayDelay}`,
|
|
45504
|
+
metadata: {
|
|
45505
|
+
alarmId,
|
|
45506
|
+
firesAt,
|
|
45507
|
+
delayMs
|
|
45508
|
+
}
|
|
45509
|
+
};
|
|
45510
|
+
}
|
|
45511
|
+
});
|
|
45512
|
+
// src/tool/background-research.ts
|
|
45513
|
+
var log9 = Log.create({ service: "background-research" });
|
|
45514
|
+
var DESCRIPTION7 = `Start a research task in the background.
|
|
45515
|
+
|
|
45516
|
+
This spawns a research sub-agent that runs asynchronously while you continue working.
|
|
45517
|
+
When the research completes, you'll receive the results automatically.
|
|
45518
|
+
|
|
45519
|
+
Use this when:
|
|
45520
|
+
- You want to research something without blocking your current work
|
|
45521
|
+
- The research might take a while and you have other things to do
|
|
45522
|
+
- You want to parallelize multiple research tasks
|
|
45523
|
+
|
|
45524
|
+
The research agent can:
|
|
45525
|
+
- Search and update your long-term knowledge base
|
|
45526
|
+
- Search the web and fetch documentation
|
|
45527
|
+
- Search your conversation history
|
|
45528
|
+
- Read files in the codebase
|
|
45529
|
+
|
|
45530
|
+
Example: background_research({ topic: "How does Stripe's payment intent API work?" })`;
|
|
45531
|
+
var parameters8 = exports_external.object({
|
|
45532
|
+
topic: exports_external.string().describe("The topic to research. Be specific about what you want to learn.")
|
|
45533
|
+
});
|
|
45534
|
+
var BackgroundResearchTool = Tool.define("background_research", {
|
|
45535
|
+
description: DESCRIPTION7,
|
|
45536
|
+
parameters: parameters8,
|
|
45537
|
+
async execute({ topic }, ctx) {
|
|
45538
|
+
const storage = ctx.extra?.storage;
|
|
45539
|
+
if (!storage) {
|
|
45540
|
+
return {
|
|
45541
|
+
output: "Error: Storage not available for background research",
|
|
45542
|
+
title: "Background research failed",
|
|
45543
|
+
metadata: {
|
|
45544
|
+
taskId: "",
|
|
45545
|
+
topic
|
|
45546
|
+
}
|
|
45547
|
+
};
|
|
45548
|
+
}
|
|
45549
|
+
const MAX_CONCURRENT_TASKS = 3;
|
|
45550
|
+
const runningTasks = await storage.tasks.listTasks({ status: "running" });
|
|
45551
|
+
if (runningTasks.length >= MAX_CONCURRENT_TASKS) {
|
|
45552
|
+
return {
|
|
45553
|
+
output: `Too many background tasks running (${runningTasks.length}/${MAX_CONCURRENT_TASKS}). Wait for some to complete or cancel them with cancel_task.`,
|
|
45554
|
+
title: "Too many tasks",
|
|
45555
|
+
metadata: {
|
|
45556
|
+
taskId: "",
|
|
45557
|
+
topic
|
|
45558
|
+
}
|
|
45559
|
+
};
|
|
45560
|
+
}
|
|
45561
|
+
const taskId = await storage.tasks.createTask({
|
|
45562
|
+
type: "research",
|
|
45563
|
+
description: topic.slice(0, 100) + (topic.length > 100 ? "..." : "")
|
|
45564
|
+
});
|
|
45565
|
+
log9.info("spawning background research", { taskId, topic: topic.slice(0, 50) });
|
|
45566
|
+
runBackgroundResearch(storage, taskId, topic).catch((error2) => {
|
|
45567
|
+
log9.error("background research failed", { taskId, error: error2 });
|
|
45568
|
+
});
|
|
45569
|
+
return {
|
|
45570
|
+
output: `\uD83D\uDD2C Research started in background.
|
|
45571
|
+
Task ID: ${taskId}
|
|
45572
|
+
Topic: "${topic}"
|
|
45573
|
+
|
|
45574
|
+
You'll receive the results when the research completes. Use list_tasks to check status.`,
|
|
45575
|
+
title: `Research started: ${topic.slice(0, 30)}...`,
|
|
45576
|
+
metadata: {
|
|
45577
|
+
taskId,
|
|
45578
|
+
topic
|
|
45579
|
+
}
|
|
45580
|
+
};
|
|
45581
|
+
}
|
|
45582
|
+
});
|
|
45583
|
+
async function runBackgroundResearch(storage, taskId, topic) {
|
|
45584
|
+
try {
|
|
45585
|
+
const result = await runResearch(storage, topic);
|
|
45586
|
+
const entriesCreated = result.entriesCreated.length;
|
|
45587
|
+
const entriesUpdated = result.entriesUpdated.length;
|
|
45588
|
+
const report = [
|
|
45589
|
+
`## Research Complete: ${topic}`,
|
|
45590
|
+
"",
|
|
45591
|
+
result.report,
|
|
45592
|
+
"",
|
|
45593
|
+
`---`,
|
|
45594
|
+
`*Research used ${result.turnsUsed} turns, ${result.usage.inputTokens} input / ${result.usage.outputTokens} output tokens*`,
|
|
45595
|
+
entriesCreated > 0 ? `*Created ${entriesCreated} LTM entries: ${result.entriesCreated.join(", ")}*` : "",
|
|
45596
|
+
entriesUpdated > 0 ? `*Updated ${entriesUpdated} LTM entries: ${result.entriesUpdated.join(", ")}*` : ""
|
|
45597
|
+
].filter(Boolean).join(`
|
|
45598
|
+
`);
|
|
45599
|
+
await storage.tasks.completeTask(taskId, {
|
|
45600
|
+
report: result.report,
|
|
45601
|
+
entriesCreated: result.entriesCreated,
|
|
45602
|
+
entriesUpdated: result.entriesUpdated,
|
|
45603
|
+
turnsUsed: result.turnsUsed,
|
|
45604
|
+
usage: result.usage
|
|
45605
|
+
});
|
|
45606
|
+
await storage.tasks.queueResult(taskId, report);
|
|
45607
|
+
log9.info("background research completed", {
|
|
45608
|
+
taskId,
|
|
45609
|
+
turnsUsed: result.turnsUsed,
|
|
45610
|
+
entriesCreated,
|
|
45611
|
+
entriesUpdated
|
|
45612
|
+
});
|
|
45613
|
+
} catch (error2) {
|
|
45614
|
+
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
45615
|
+
await storage.tasks.failTask(taskId, errorMsg);
|
|
45616
|
+
await storage.tasks.queueResult(taskId, `## Research Failed: ${topic}
|
|
45617
|
+
|
|
45618
|
+
Error: ${errorMsg}`);
|
|
45619
|
+
log9.error("background research failed", { taskId, error: errorMsg });
|
|
45620
|
+
}
|
|
45621
|
+
}
|
|
45622
|
+
// src/tool/background-reflect.ts
|
|
45623
|
+
var log10 = Log.create({ service: "background-reflect" });
|
|
45624
|
+
var DESCRIPTION8 = `Start a reflection task in the background.
|
|
45625
|
+
|
|
45626
|
+
This spawns a reflection sub-agent that runs asynchronously while you continue working.
|
|
45627
|
+
When the reflection completes, you'll receive the answer automatically.
|
|
45628
|
+
|
|
45629
|
+
Use this when:
|
|
45630
|
+
- You want to search your memory without blocking your current work
|
|
45631
|
+
- The question might require extensive searching
|
|
45632
|
+
- You want to parallelize multiple reflection tasks
|
|
45633
|
+
|
|
45634
|
+
The reflection agent can:
|
|
45635
|
+
- Search your conversation history with full-text search
|
|
45636
|
+
- Retrieve specific messages with surrounding context
|
|
45637
|
+
- Search and read your long-term knowledge base
|
|
45638
|
+
|
|
45639
|
+
Example: background_reflect({ question: "What did we decide about the API authentication approach?" })`;
|
|
45640
|
+
var parameters9 = exports_external.object({
|
|
45641
|
+
question: exports_external.string().describe("The question to answer or research task to complete. Be specific about what you're looking for.")
|
|
45642
|
+
});
|
|
45643
|
+
var BackgroundReflectTool = Tool.define("background_reflect", {
|
|
45644
|
+
description: DESCRIPTION8,
|
|
45645
|
+
parameters: parameters9,
|
|
45646
|
+
async execute({ question }, ctx) {
|
|
45647
|
+
const storage = ctx.extra?.storage;
|
|
45648
|
+
if (!storage) {
|
|
45649
|
+
return {
|
|
45650
|
+
output: "Error: Storage not available for background reflection",
|
|
45651
|
+
title: "Background reflection failed",
|
|
45652
|
+
metadata: {
|
|
45653
|
+
taskId: "",
|
|
45654
|
+
question
|
|
45655
|
+
}
|
|
45656
|
+
};
|
|
45657
|
+
}
|
|
45658
|
+
const MAX_CONCURRENT_TASKS = 3;
|
|
45659
|
+
const runningTasks = await storage.tasks.listTasks({ status: "running" });
|
|
45660
|
+
if (runningTasks.length >= MAX_CONCURRENT_TASKS) {
|
|
45661
|
+
return {
|
|
45662
|
+
output: `Too many background tasks running (${runningTasks.length}/${MAX_CONCURRENT_TASKS}). Wait for some to complete or cancel them with cancel_task.`,
|
|
45663
|
+
title: "Too many tasks",
|
|
45664
|
+
metadata: {
|
|
45665
|
+
taskId: "",
|
|
45666
|
+
question
|
|
45667
|
+
}
|
|
45668
|
+
};
|
|
45669
|
+
}
|
|
45670
|
+
const taskId = await storage.tasks.createTask({
|
|
45671
|
+
type: "reflect",
|
|
45672
|
+
description: question.slice(0, 100) + (question.length > 100 ? "..." : "")
|
|
45673
|
+
});
|
|
45674
|
+
log10.info("spawning background reflection", { taskId, question: question.slice(0, 50) });
|
|
45675
|
+
runBackgroundReflection(storage, taskId, question).catch((error2) => {
|
|
45676
|
+
log10.error("background reflection failed", { taskId, error: error2 });
|
|
45677
|
+
});
|
|
45678
|
+
return {
|
|
45679
|
+
output: `\uD83D\uDD0D Reflection started in background.
|
|
45680
|
+
Task ID: ${taskId}
|
|
45681
|
+
Question: "${question}"
|
|
45682
|
+
|
|
45683
|
+
You'll receive the answer when the reflection completes. Use list_tasks to check status.`,
|
|
45684
|
+
title: `Reflection started: ${question.slice(0, 30)}...`,
|
|
45685
|
+
metadata: {
|
|
45686
|
+
taskId,
|
|
45687
|
+
question
|
|
45688
|
+
}
|
|
45689
|
+
};
|
|
45690
|
+
}
|
|
45691
|
+
});
|
|
45692
|
+
async function runBackgroundReflection(storage, taskId, question) {
|
|
45693
|
+
try {
|
|
45694
|
+
const result = await runReflection(storage, question);
|
|
45695
|
+
const report = [
|
|
45696
|
+
`## Reflection Complete: ${question}`,
|
|
45697
|
+
"",
|
|
45698
|
+
result.answer,
|
|
45699
|
+
"",
|
|
45700
|
+
`---`,
|
|
45701
|
+
`*Reflection used ${result.turnsUsed} turns, ${result.usage.inputTokens} input / ${result.usage.outputTokens} output tokens*`
|
|
45702
|
+
].join(`
|
|
45703
|
+
`);
|
|
45704
|
+
await storage.tasks.completeTask(taskId, {
|
|
45705
|
+
answer: result.answer,
|
|
45706
|
+
turnsUsed: result.turnsUsed,
|
|
45707
|
+
usage: result.usage
|
|
45708
|
+
});
|
|
45709
|
+
await storage.tasks.queueResult(taskId, report);
|
|
45710
|
+
log10.info("background reflection completed", {
|
|
45711
|
+
taskId,
|
|
45712
|
+
turnsUsed: result.turnsUsed
|
|
45713
|
+
});
|
|
45714
|
+
} catch (error2) {
|
|
45715
|
+
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
45716
|
+
await storage.tasks.failTask(taskId, errorMsg);
|
|
45717
|
+
await storage.tasks.queueResult(taskId, `## Reflection Failed: ${question}
|
|
45718
|
+
|
|
45719
|
+
Error: ${errorMsg}`);
|
|
45720
|
+
log10.error("background reflection failed", { taskId, error: errorMsg });
|
|
45721
|
+
}
|
|
45722
|
+
}
|
|
45723
|
+
// src/tool/cancel-task.ts
|
|
45724
|
+
var DESCRIPTION9 = `Cancel a running background task.
|
|
45725
|
+
|
|
45726
|
+
Note: This marks the task as cancelled, but cannot stop work already in progress.
|
|
45727
|
+
The task may still complete, but its results will be discarded.
|
|
45728
|
+
|
|
45729
|
+
Use list_tasks to see running tasks and their IDs.`;
|
|
45730
|
+
var parameters10 = exports_external.object({
|
|
45731
|
+
taskId: exports_external.string().describe("The task ID to cancel (from list_tasks)")
|
|
45732
|
+
});
|
|
45733
|
+
var CancelTaskTool = Tool.define("cancel_task", {
|
|
45734
|
+
description: DESCRIPTION9,
|
|
45735
|
+
parameters: parameters10,
|
|
45736
|
+
async execute({ taskId }, ctx) {
|
|
45737
|
+
const tasksStorage = ctx.extra?.tasks;
|
|
45738
|
+
if (!tasksStorage) {
|
|
45739
|
+
return {
|
|
45740
|
+
output: "Error: Tasks storage not available",
|
|
45741
|
+
title: "Cancel task failed",
|
|
45742
|
+
metadata: {
|
|
45743
|
+
taskId,
|
|
45744
|
+
success: false
|
|
45745
|
+
}
|
|
45746
|
+
};
|
|
45747
|
+
}
|
|
45748
|
+
const task = await tasksStorage.getTask(taskId);
|
|
45749
|
+
if (!task) {
|
|
45750
|
+
return {
|
|
45751
|
+
output: `Task not found: ${taskId}`,
|
|
45752
|
+
title: "Task not found",
|
|
45753
|
+
metadata: {
|
|
45754
|
+
taskId,
|
|
45755
|
+
success: false
|
|
45756
|
+
}
|
|
45757
|
+
};
|
|
45758
|
+
}
|
|
45759
|
+
if (task.status !== "running") {
|
|
45760
|
+
return {
|
|
45761
|
+
output: `Task ${taskId} is not running (status: ${task.status})`,
|
|
45762
|
+
title: "Cannot cancel",
|
|
45763
|
+
metadata: {
|
|
45764
|
+
taskId,
|
|
45765
|
+
success: false
|
|
45766
|
+
}
|
|
45767
|
+
};
|
|
45768
|
+
}
|
|
45769
|
+
await tasksStorage.failTask(taskId, "Cancelled by user");
|
|
45770
|
+
return {
|
|
45771
|
+
output: `Task ${taskId} marked as cancelled.
|
|
45772
|
+
Note: The task may still complete in the background, but results will be discarded.`,
|
|
45773
|
+
title: "Task cancelled",
|
|
45774
|
+
metadata: {
|
|
45775
|
+
taskId,
|
|
45776
|
+
success: true
|
|
45777
|
+
}
|
|
45778
|
+
};
|
|
45779
|
+
}
|
|
45780
|
+
});
|
|
45108
45781
|
// src/ltm/tools.ts
|
|
45109
45782
|
var AGENT_TYPE2 = "ltm-consolidate";
|
|
45110
45783
|
function buildConsolidationTools(storage) {
|
|
@@ -45344,7 +46017,7 @@ function buildConsolidationTools(storage) {
|
|
|
45344
46017
|
}
|
|
45345
46018
|
|
|
45346
46019
|
// src/ltm/consolidation.ts
|
|
45347
|
-
var
|
|
46020
|
+
var log11 = Log.create({ service: "consolidation-agent" });
|
|
45348
46021
|
var MAX_CONSOLIDATION_TURNS = 20;
|
|
45349
46022
|
function isConversationNoteworthy(messages) {
|
|
45350
46023
|
if (messages.length < 5) {
|
|
@@ -45499,14 +46172,14 @@ async function runConsolidation(storage, messages) {
|
|
|
45499
46172
|
usage: { inputTokens: 0, outputTokens: 0 }
|
|
45500
46173
|
};
|
|
45501
46174
|
if (!isConversationNoteworthy(messages)) {
|
|
45502
|
-
|
|
46175
|
+
log11.info("skipping consolidation - conversation not noteworthy", {
|
|
45503
46176
|
messageCount: messages.length
|
|
45504
46177
|
});
|
|
45505
46178
|
result.summary = "Skipped - conversation not noteworthy";
|
|
45506
46179
|
return result;
|
|
45507
46180
|
}
|
|
45508
46181
|
result.ran = true;
|
|
45509
|
-
|
|
46182
|
+
log11.info("starting consolidation", { messageCount: messages.length });
|
|
45510
46183
|
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000).toISOString();
|
|
45511
46184
|
const allEntries = await storage.ltm.glob("/**");
|
|
45512
46185
|
const recentlyUpdated = allEntries.filter((e) => e.updatedAt > oneHourAgo && e.slug !== "identity" && e.slug !== "behavior");
|
|
@@ -45554,7 +46227,7 @@ async function runConsolidation(storage, messages) {
|
|
|
45554
46227
|
if (!result.summary) {
|
|
45555
46228
|
result.summary = "Consolidation ended without explicit finish";
|
|
45556
46229
|
}
|
|
45557
|
-
|
|
46230
|
+
log11.info("consolidation complete", {
|
|
45558
46231
|
entriesCreated: result.entriesCreated,
|
|
45559
46232
|
entriesUpdated: result.entriesUpdated,
|
|
45560
46233
|
entriesArchived: result.entriesArchived,
|
|
@@ -45673,13 +46346,13 @@ async function runDistillation(storage, threshold, target, force) {
|
|
|
45673
46346
|
}
|
|
45674
46347
|
|
|
45675
46348
|
// src/agent/index.ts
|
|
45676
|
-
var
|
|
46349
|
+
var log12 = Log.create({ service: "agent" });
|
|
45677
46350
|
var MAX_TURNS = 200;
|
|
45678
46351
|
async function surfaceBackgroundReports(storage) {
|
|
45679
46352
|
const reports = await storage.background.getUnsurfaced();
|
|
45680
46353
|
if (reports.length === 0)
|
|
45681
46354
|
return;
|
|
45682
|
-
|
|
46355
|
+
log12.info("surfacing background reports", { count: reports.length });
|
|
45683
46356
|
for (const report of reports) {
|
|
45684
46357
|
const toolCallId = Identifier.ascending("toolcall");
|
|
45685
46358
|
await storage.temporal.appendMessage({
|
|
@@ -45849,6 +46522,16 @@ function createToolContextFactory(storage, sessionId, messageId, abortSignal) {
|
|
|
45849
46522
|
storage
|
|
45850
46523
|
};
|
|
45851
46524
|
return ctx;
|
|
46525
|
+
},
|
|
46526
|
+
createListTasksContext(callId) {
|
|
46527
|
+
const ctx = Tool.createContext({
|
|
46528
|
+
...baseContext,
|
|
46529
|
+
callID: callId
|
|
46530
|
+
});
|
|
46531
|
+
ctx.extra = {
|
|
46532
|
+
tasks: storage.tasks
|
|
46533
|
+
};
|
|
46534
|
+
return ctx;
|
|
45852
46535
|
}
|
|
45853
46536
|
};
|
|
45854
46537
|
}
|
|
@@ -45961,15 +46644,30 @@ function buildTools(storage, sessionId, messageId, abortSignal) {
|
|
|
45961
46644
|
parameters: LTMReadTool.definition.parameters,
|
|
45962
46645
|
execute: async (args, { toolCallId }) => safeExecute("ltm_read", () => LTMReadTool.definition.execute(args, factory.createLTMContext(toolCallId)))
|
|
45963
46646
|
});
|
|
45964
|
-
tools.
|
|
45965
|
-
description:
|
|
45966
|
-
parameters:
|
|
45967
|
-
execute: async (args, { toolCallId }) => safeExecute("
|
|
46647
|
+
tools.list_tasks = tool({
|
|
46648
|
+
description: ListTasksTool.definition.description,
|
|
46649
|
+
parameters: ListTasksTool.definition.parameters,
|
|
46650
|
+
execute: async (args, { toolCallId }) => safeExecute("list_tasks", () => ListTasksTool.definition.execute(args, factory.createListTasksContext(toolCallId)))
|
|
46651
|
+
});
|
|
46652
|
+
tools.set_alarm = tool({
|
|
46653
|
+
description: SetAlarmTool.definition.description,
|
|
46654
|
+
parameters: SetAlarmTool.definition.parameters,
|
|
46655
|
+
execute: async (args, { toolCallId }) => safeExecute("set_alarm", () => SetAlarmTool.definition.execute(args, factory.createListTasksContext(toolCallId)))
|
|
46656
|
+
});
|
|
46657
|
+
tools.background_research = tool({
|
|
46658
|
+
description: BackgroundResearchTool.definition.description,
|
|
46659
|
+
parameters: BackgroundResearchTool.definition.parameters,
|
|
46660
|
+
execute: async (args, { toolCallId }) => safeExecute("background_research", () => BackgroundResearchTool.definition.execute(args, factory.createResearchContext(toolCallId)))
|
|
45968
46661
|
});
|
|
45969
|
-
tools.
|
|
45970
|
-
description:
|
|
45971
|
-
parameters:
|
|
45972
|
-
execute: async (args, { toolCallId }) => safeExecute("
|
|
46662
|
+
tools.background_reflect = tool({
|
|
46663
|
+
description: BackgroundReflectTool.definition.description,
|
|
46664
|
+
parameters: BackgroundReflectTool.definition.parameters,
|
|
46665
|
+
execute: async (args, { toolCallId }) => safeExecute("background_reflect", () => BackgroundReflectTool.definition.execute(args, factory.createReflectContext(toolCallId)))
|
|
46666
|
+
});
|
|
46667
|
+
tools.cancel_task = tool({
|
|
46668
|
+
description: CancelTaskTool.definition.description,
|
|
46669
|
+
parameters: CancelTaskTool.definition.parameters,
|
|
46670
|
+
execute: async (args, { toolCallId }) => safeExecute("cancel_task", () => CancelTaskTool.definition.execute(args, factory.createListTasksContext(toolCallId)))
|
|
45973
46671
|
});
|
|
45974
46672
|
return tools;
|
|
45975
46673
|
}
|
|
@@ -45979,14 +46677,14 @@ async function initializeMcp() {
|
|
|
45979
46677
|
if (didInitialize) {
|
|
45980
46678
|
const status = Mcp.getStatus();
|
|
45981
46679
|
if (status.length > 0) {
|
|
45982
|
-
|
|
46680
|
+
log12.info("MCP servers connected", {
|
|
45983
46681
|
servers: status.map((s) => `${s.name} (${s.toolCount} tools)`)
|
|
45984
46682
|
});
|
|
45985
46683
|
}
|
|
45986
46684
|
}
|
|
45987
46685
|
return didInitialize;
|
|
45988
46686
|
} catch (error2) {
|
|
45989
|
-
|
|
46687
|
+
log12.error("Failed to initialize MCP", { error: error2 });
|
|
45990
46688
|
return false;
|
|
45991
46689
|
}
|
|
45992
46690
|
}
|
|
@@ -46000,11 +46698,11 @@ async function runAgent(prompt, options) {
|
|
|
46000
46698
|
const hardLimit = config2.tokenBudgets.compactionHardLimit;
|
|
46001
46699
|
const tokensBefore = await getEffectiveViewTokens(storage.temporal);
|
|
46002
46700
|
if (tokensBefore > hardLimit) {
|
|
46003
|
-
|
|
46701
|
+
log12.error("context overflow - refusing turn", { tokens: tokensBefore, hardLimit });
|
|
46004
46702
|
throw new Error(`Context overflow: ${tokensBefore} tokens exceeds hard limit of ${hardLimit}. ` + `Run 'miriad-code --compact' to reduce context size before continuing.`);
|
|
46005
46703
|
}
|
|
46006
46704
|
if (tokensBefore > softLimit) {
|
|
46007
|
-
|
|
46705
|
+
log12.warn("approaching token limit, running compaction before turn", {
|
|
46008
46706
|
tokens: tokensBefore,
|
|
46009
46707
|
softLimit,
|
|
46010
46708
|
target: config2.tokenBudgets.compactionTarget
|
|
@@ -46012,13 +46710,13 @@ async function runAgent(prompt, options) {
|
|
|
46012
46710
|
await runMemoryCuration(storage, { force: true });
|
|
46013
46711
|
const tokensAfter = await getEffectiveViewTokens(storage.temporal);
|
|
46014
46712
|
if (tokensAfter > softLimit) {
|
|
46015
|
-
|
|
46713
|
+
log12.warn("compaction didn't reduce tokens below soft limit", {
|
|
46016
46714
|
before: tokensBefore,
|
|
46017
46715
|
after: tokensAfter,
|
|
46018
46716
|
softLimit
|
|
46019
46717
|
});
|
|
46020
46718
|
} else {
|
|
46021
|
-
|
|
46719
|
+
log12.info("pre-turn compaction successful", { before: tokensBefore, after: tokensAfter });
|
|
46022
46720
|
}
|
|
46023
46721
|
}
|
|
46024
46722
|
const model = Provider.getModelForTier("reasoning");
|
|
@@ -46033,7 +46731,7 @@ async function runAgent(prompt, options) {
|
|
|
46033
46731
|
createdAt: new Date().toISOString()
|
|
46034
46732
|
});
|
|
46035
46733
|
} catch (error2) {
|
|
46036
|
-
|
|
46734
|
+
log12.error("failed to persist user message", {
|
|
46037
46735
|
messageId: userMessageId,
|
|
46038
46736
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
46039
46737
|
});
|
|
@@ -46067,7 +46765,7 @@ async function runAgent(prompt, options) {
|
|
|
46067
46765
|
});
|
|
46068
46766
|
lastLoggedText = text3;
|
|
46069
46767
|
} catch (error2) {
|
|
46070
|
-
|
|
46768
|
+
log12.error("failed to persist assistant message", {
|
|
46071
46769
|
messageId: assistantMessageId,
|
|
46072
46770
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
46073
46771
|
});
|
|
@@ -46088,7 +46786,7 @@ async function runAgent(prompt, options) {
|
|
|
46088
46786
|
createdAt: new Date().toISOString()
|
|
46089
46787
|
});
|
|
46090
46788
|
} catch (error2) {
|
|
46091
|
-
|
|
46789
|
+
log12.error("failed to persist tool call", {
|
|
46092
46790
|
messageId: toolCallMsgId,
|
|
46093
46791
|
toolName,
|
|
46094
46792
|
toolCallId,
|
|
@@ -46117,7 +46815,7 @@ async function runAgent(prompt, options) {
|
|
|
46117
46815
|
createdAt: new Date().toISOString()
|
|
46118
46816
|
});
|
|
46119
46817
|
} catch (error2) {
|
|
46120
|
-
|
|
46818
|
+
log12.error("failed to persist tool result", {
|
|
46121
46819
|
messageId: toolResultMsgId,
|
|
46122
46820
|
toolName,
|
|
46123
46821
|
toolCallId,
|
|
@@ -46145,7 +46843,7 @@ async function runAgent(prompt, options) {
|
|
|
46145
46843
|
createdAt: new Date().toISOString()
|
|
46146
46844
|
});
|
|
46147
46845
|
} catch (error2) {
|
|
46148
|
-
|
|
46846
|
+
log12.error("failed to persist injected user message", {
|
|
46149
46847
|
messageId: injectedMsgId,
|
|
46150
46848
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
46151
46849
|
});
|
|
@@ -46177,7 +46875,7 @@ async function runAgent(prompt, options) {
|
|
|
46177
46875
|
}
|
|
46178
46876
|
}
|
|
46179
46877
|
}).catch((error2) => {
|
|
46180
|
-
|
|
46878
|
+
log12.error("background memory curation failed", { error: error2 instanceof Error ? error2.message : String(error2) });
|
|
46181
46879
|
});
|
|
46182
46880
|
return {
|
|
46183
46881
|
response: result.finalText,
|
|
@@ -46869,7 +47567,7 @@ function systemMessage(subtype, data = {}) {
|
|
|
46869
47567
|
function getModelId() {
|
|
46870
47568
|
return Config.resolveModelTier("reasoning");
|
|
46871
47569
|
}
|
|
46872
|
-
var
|
|
47570
|
+
var log13 = Log.create({ service: "server" });
|
|
46873
47571
|
|
|
46874
47572
|
class Server {
|
|
46875
47573
|
options;
|
|
@@ -46879,33 +47577,49 @@ class Server {
|
|
|
46879
47577
|
rl = null;
|
|
46880
47578
|
processing = false;
|
|
46881
47579
|
sessionId = "";
|
|
47580
|
+
alarmInterval = null;
|
|
47581
|
+
checkingAlarms = false;
|
|
47582
|
+
outputHandler;
|
|
47583
|
+
turnCompleteResolve = null;
|
|
46882
47584
|
constructor(options) {
|
|
46883
47585
|
this.options = options;
|
|
46884
47586
|
this.storage = createStorage(options.dbPath);
|
|
47587
|
+
this.outputHandler = options.outputHandler ?? ((msg) => {
|
|
47588
|
+
process.stdout.write(JSON.stringify(msg) + `
|
|
47589
|
+
`);
|
|
47590
|
+
});
|
|
46885
47591
|
}
|
|
46886
47592
|
async start() {
|
|
46887
47593
|
await cleanupStaleWorkers(this.storage);
|
|
46888
47594
|
await initializeDefaultEntries(this.storage);
|
|
47595
|
+
await this.recoverKilledTasks();
|
|
46889
47596
|
this.sessionId = await this.storage.session.getId();
|
|
46890
47597
|
await Mcp.initialize();
|
|
46891
47598
|
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 });
|
|
47599
|
+
if (!this.options.noStdin) {
|
|
47600
|
+
process.on("SIGTERM", () => this.shutdown("SIGTERM"));
|
|
47601
|
+
process.on("SIGINT", () => this.shutdown("SIGINT"));
|
|
47602
|
+
this.rl = readline.createInterface({
|
|
47603
|
+
input: process.stdin,
|
|
47604
|
+
output: process.stdout,
|
|
47605
|
+
terminal: false
|
|
46902
47606
|
});
|
|
46903
|
-
|
|
46904
|
-
|
|
46905
|
-
|
|
46906
|
-
|
|
46907
|
-
|
|
46908
|
-
|
|
47607
|
+
this.rl.on("line", (line) => {
|
|
47608
|
+
this.handleLine(line).catch((error2) => {
|
|
47609
|
+
log13.error("unhandled error in line handler", { error: error2 });
|
|
47610
|
+
});
|
|
47611
|
+
});
|
|
47612
|
+
this.rl.on("close", () => {
|
|
47613
|
+
log13.info("stdin closed, shutting down");
|
|
47614
|
+
this.shutdown("stdin closed");
|
|
47615
|
+
});
|
|
47616
|
+
}
|
|
47617
|
+
this.alarmInterval = setInterval(() => {
|
|
47618
|
+
this.checkAlarms().catch((error2) => {
|
|
47619
|
+
log13.error("error checking alarms", { error: error2 });
|
|
47620
|
+
});
|
|
47621
|
+
}, 1000);
|
|
47622
|
+
log13.info("server started", { dbPath: this.options.dbPath, sessionId: this.sessionId });
|
|
46909
47623
|
this.send(systemMessage("init", {
|
|
46910
47624
|
session_id: this.sessionId,
|
|
46911
47625
|
model: getModelId(),
|
|
@@ -46932,7 +47646,7 @@ class Server {
|
|
|
46932
47646
|
switch (request.action) {
|
|
46933
47647
|
case "interrupt":
|
|
46934
47648
|
if (this.currentTurn) {
|
|
46935
|
-
|
|
47649
|
+
log13.info("interrupting current turn", { sessionId: this.currentTurn.sessionId });
|
|
46936
47650
|
this.currentTurn.abortController.abort();
|
|
46937
47651
|
this.send(systemMessage("interrupted", { session_id: this.currentTurn.sessionId }));
|
|
46938
47652
|
} else {
|
|
@@ -46954,8 +47668,29 @@ class Server {
|
|
|
46954
47668
|
break;
|
|
46955
47669
|
}
|
|
46956
47670
|
}
|
|
47671
|
+
async recoverKilledTasks() {
|
|
47672
|
+
const killedTasks = await this.storage.tasks.recoverKilledTasks();
|
|
47673
|
+
if (killedTasks.length === 0)
|
|
47674
|
+
return;
|
|
47675
|
+
log13.info("recovered killed tasks", { count: killedTasks.length });
|
|
47676
|
+
for (const task of killedTasks) {
|
|
47677
|
+
await this.storage.background.fileReport({
|
|
47678
|
+
subsystem: "task_recovery",
|
|
47679
|
+
report: {
|
|
47680
|
+
message: `Background task was killed when agent restarted: ${task.type} - "${task.description}". You may want to restart it.`,
|
|
47681
|
+
taskId: task.id,
|
|
47682
|
+
type: task.type,
|
|
47683
|
+
description: task.description
|
|
47684
|
+
}
|
|
47685
|
+
});
|
|
47686
|
+
}
|
|
47687
|
+
}
|
|
46957
47688
|
async shutdown(reason) {
|
|
46958
|
-
|
|
47689
|
+
log13.info("shutting down", { reason });
|
|
47690
|
+
if (this.alarmInterval) {
|
|
47691
|
+
clearInterval(this.alarmInterval);
|
|
47692
|
+
this.alarmInterval = null;
|
|
47693
|
+
}
|
|
46959
47694
|
if (this.currentTurn) {
|
|
46960
47695
|
this.currentTurn.abortController.abort();
|
|
46961
47696
|
}
|
|
@@ -46963,10 +47698,74 @@ class Server {
|
|
|
46963
47698
|
this.rl?.close();
|
|
46964
47699
|
process.exit(0);
|
|
46965
47700
|
}
|
|
47701
|
+
interrupt() {
|
|
47702
|
+
if (this.currentTurn) {
|
|
47703
|
+
log13.info("interrupting current turn", { sessionId: this.currentTurn.sessionId });
|
|
47704
|
+
this.currentTurn.abortController.abort();
|
|
47705
|
+
this.send(systemMessage("interrupted", { session_id: this.currentTurn.sessionId }));
|
|
47706
|
+
}
|
|
47707
|
+
}
|
|
47708
|
+
async sendUserMessage(prompt) {
|
|
47709
|
+
const userMessage = {
|
|
47710
|
+
type: "user",
|
|
47711
|
+
session_id: this.sessionId,
|
|
47712
|
+
message: {
|
|
47713
|
+
role: "user",
|
|
47714
|
+
content: prompt
|
|
47715
|
+
}
|
|
47716
|
+
};
|
|
47717
|
+
const turnComplete = new Promise((resolve5) => {
|
|
47718
|
+
this.turnCompleteResolve = resolve5;
|
|
47719
|
+
});
|
|
47720
|
+
await this.handleUserMessage(userMessage);
|
|
47721
|
+
await turnComplete;
|
|
47722
|
+
}
|
|
47723
|
+
async checkAlarms() {
|
|
47724
|
+
if (this.checkingAlarms)
|
|
47725
|
+
return;
|
|
47726
|
+
this.checkingAlarms = true;
|
|
47727
|
+
try {
|
|
47728
|
+
const dueAlarms = await this.storage.tasks.getDueAlarms();
|
|
47729
|
+
if (dueAlarms.length > 0) {
|
|
47730
|
+
log13.info("alarms fired", { count: dueAlarms.length });
|
|
47731
|
+
for (const alarm of dueAlarms) {
|
|
47732
|
+
await this.storage.tasks.markAlarmFired(alarm.id);
|
|
47733
|
+
await this.storage.tasks.queueResult(alarm.id, `\u23F0 **Alarm fired**: ${alarm.note}`);
|
|
47734
|
+
}
|
|
47735
|
+
}
|
|
47736
|
+
const hasResults = await this.storage.tasks.hasQueuedResults();
|
|
47737
|
+
if (hasResults && !this.currentTurn && !this.processing) {
|
|
47738
|
+
await this.triggerSelfTurn();
|
|
47739
|
+
}
|
|
47740
|
+
} finally {
|
|
47741
|
+
this.checkingAlarms = false;
|
|
47742
|
+
}
|
|
47743
|
+
}
|
|
47744
|
+
async triggerSelfTurn() {
|
|
47745
|
+
const results = await this.storage.tasks.drainQueue();
|
|
47746
|
+
if (results.length === 0)
|
|
47747
|
+
return;
|
|
47748
|
+
log13.info("triggering self-turn", { resultCount: results.length });
|
|
47749
|
+
const content = results.map((r) => r.content).join(`
|
|
47750
|
+
|
|
47751
|
+
`);
|
|
47752
|
+
const selfMessage = {
|
|
47753
|
+
type: "user",
|
|
47754
|
+
session_id: this.sessionId,
|
|
47755
|
+
message: {
|
|
47756
|
+
role: "user",
|
|
47757
|
+
content: `[SYSTEM: Background events occurred]
|
|
47758
|
+
|
|
47759
|
+
${content}`
|
|
47760
|
+
}
|
|
47761
|
+
};
|
|
47762
|
+
await this.processTurn(selfMessage);
|
|
47763
|
+
await this.processQueue();
|
|
47764
|
+
}
|
|
46966
47765
|
async handleUserMessage(userMessage) {
|
|
46967
47766
|
if (this.currentTurn) {
|
|
46968
47767
|
this.messageQueue.push(userMessage);
|
|
46969
|
-
|
|
47768
|
+
log13.info("queued message", {
|
|
46970
47769
|
sessionId: userMessage.session_id,
|
|
46971
47770
|
queueLength: this.messageQueue.length,
|
|
46972
47771
|
currentSession: this.currentTurn.sessionId
|
|
@@ -46992,7 +47791,7 @@ class Server {
|
|
|
46992
47791
|
}
|
|
46993
47792
|
if (userMessage.environment !== undefined) {
|
|
46994
47793
|
setEnvironment(userMessage.environment);
|
|
46995
|
-
|
|
47794
|
+
log13.info("applied environment from message", {
|
|
46996
47795
|
count: Object.keys(userMessage.environment).length
|
|
46997
47796
|
});
|
|
46998
47797
|
} else {
|
|
@@ -47005,7 +47804,7 @@ class Server {
|
|
|
47005
47804
|
numTurns: 0,
|
|
47006
47805
|
startTime: Date.now()
|
|
47007
47806
|
};
|
|
47008
|
-
|
|
47807
|
+
log13.debug("starting turn", { sessionId, promptLength: prompt.length });
|
|
47009
47808
|
try {
|
|
47010
47809
|
const agentOptions = {
|
|
47011
47810
|
storage: this.storage,
|
|
@@ -47029,12 +47828,16 @@ class Server {
|
|
|
47029
47828
|
return;
|
|
47030
47829
|
}
|
|
47031
47830
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
47032
|
-
|
|
47831
|
+
log13.error("turn failed", { sessionId, error: message });
|
|
47033
47832
|
this.send(resultMessage(sessionId, "error", Date.now() - (this.currentTurn?.startTime ?? Date.now()), this.currentTurn?.numTurns ?? 0, {
|
|
47034
47833
|
result: message
|
|
47035
47834
|
}));
|
|
47036
47835
|
} finally {
|
|
47037
47836
|
this.currentTurn = null;
|
|
47837
|
+
if (this.turnCompleteResolve) {
|
|
47838
|
+
this.turnCompleteResolve();
|
|
47839
|
+
this.turnCompleteResolve = null;
|
|
47840
|
+
}
|
|
47038
47841
|
}
|
|
47039
47842
|
}
|
|
47040
47843
|
async processQueue() {
|
|
@@ -47044,7 +47847,7 @@ class Server {
|
|
|
47044
47847
|
try {
|
|
47045
47848
|
while (this.messageQueue.length > 0 && !this.currentTurn) {
|
|
47046
47849
|
const nextMessage = this.messageQueue.shift();
|
|
47047
|
-
|
|
47850
|
+
log13.info("processing queued message", {
|
|
47048
47851
|
sessionId: nextMessage.session_id,
|
|
47049
47852
|
remainingInQueue: this.messageQueue.length
|
|
47050
47853
|
});
|
|
@@ -47063,7 +47866,7 @@ class Server {
|
|
|
47063
47866
|
const combined = contents.join(`
|
|
47064
47867
|
|
|
47065
47868
|
`);
|
|
47066
|
-
|
|
47869
|
+
log13.info("injecting mid-turn messages", {
|
|
47067
47870
|
messageCount: messages.length,
|
|
47068
47871
|
combinedLength: combined.length
|
|
47069
47872
|
});
|
|
@@ -47122,14 +47925,13 @@ class Server {
|
|
|
47122
47925
|
};
|
|
47123
47926
|
const reinitialized = await Mcp.initialize(mergedConfig);
|
|
47124
47927
|
if (reinitialized) {
|
|
47125
|
-
|
|
47928
|
+
log13.info("MCP reinitialized with message config", {
|
|
47126
47929
|
serverCount: Object.keys(mergedConfig.mcpServers ?? {}).length
|
|
47127
47930
|
});
|
|
47128
47931
|
}
|
|
47129
47932
|
}
|
|
47130
47933
|
send(message) {
|
|
47131
|
-
|
|
47132
|
-
`);
|
|
47934
|
+
this.outputHandler(message);
|
|
47133
47935
|
}
|
|
47134
47936
|
}
|
|
47135
47937
|
async function runServer(options) {
|
|
@@ -47148,18 +47950,20 @@ var MAX_HISTORY = 1000;
|
|
|
47148
47950
|
|
|
47149
47951
|
class ReplSession {
|
|
47150
47952
|
options;
|
|
47151
|
-
|
|
47953
|
+
server;
|
|
47152
47954
|
rl = null;
|
|
47153
|
-
abortController = null;
|
|
47154
|
-
isRunning = false;
|
|
47155
47955
|
history = [];
|
|
47956
|
+
isRunning = false;
|
|
47156
47957
|
constructor(options) {
|
|
47157
47958
|
this.options = options;
|
|
47158
|
-
this.
|
|
47959
|
+
this.server = new Server({
|
|
47960
|
+
dbPath: options.dbPath,
|
|
47961
|
+
outputHandler: (message) => this.handleServerOutput(message),
|
|
47962
|
+
noStdin: true
|
|
47963
|
+
});
|
|
47159
47964
|
}
|
|
47160
47965
|
async start() {
|
|
47161
|
-
await
|
|
47162
|
-
await initializeDefaultEntries(this.storage);
|
|
47966
|
+
await this.server.start();
|
|
47163
47967
|
this.loadHistory();
|
|
47164
47968
|
this.rl = readline2.createInterface({
|
|
47165
47969
|
input: process.stdin,
|
|
@@ -47172,8 +47976,8 @@ class ReplSession {
|
|
|
47172
47976
|
this.rl.history?.unshift(line);
|
|
47173
47977
|
}
|
|
47174
47978
|
this.rl.on("SIGINT", () => {
|
|
47175
|
-
if (this.isRunning
|
|
47176
|
-
this.
|
|
47979
|
+
if (this.isRunning) {
|
|
47980
|
+
this.server.interrupt();
|
|
47177
47981
|
process.stdout.write(`
|
|
47178
47982
|
^C - Request cancelled
|
|
47179
47983
|
`);
|
|
@@ -47188,7 +47992,7 @@ class ReplSession {
|
|
|
47188
47992
|
this.saveHistory();
|
|
47189
47993
|
console.log(`
|
|
47190
47994
|
Goodbye!`);
|
|
47191
|
-
|
|
47995
|
+
this.server.shutdown("user exit");
|
|
47192
47996
|
});
|
|
47193
47997
|
this.rl.on("line", (line) => {
|
|
47194
47998
|
this.handleLine(line).catch((error2) => {
|
|
@@ -47227,7 +48031,7 @@ Goodbye!`);
|
|
|
47227
48031
|
case "q":
|
|
47228
48032
|
this.saveHistory();
|
|
47229
48033
|
console.log("Goodbye!");
|
|
47230
|
-
|
|
48034
|
+
this.server.shutdown("user exit");
|
|
47231
48035
|
break;
|
|
47232
48036
|
case "inspect":
|
|
47233
48037
|
try {
|
|
@@ -47274,75 +48078,64 @@ Goodbye!`);
|
|
|
47274
48078
|
}
|
|
47275
48079
|
async runPrompt(prompt) {
|
|
47276
48080
|
this.isRunning = true;
|
|
47277
|
-
this.abortController = new AbortController;
|
|
47278
|
-
let hasOutput = false;
|
|
47279
|
-
const agentOptions = {
|
|
47280
|
-
storage: this.storage,
|
|
47281
|
-
verbose: false,
|
|
47282
|
-
abortSignal: this.abortController.signal,
|
|
47283
|
-
onEvent: (event) => this.handleAgentEvent(event, () => {
|
|
47284
|
-
hasOutput = true;
|
|
47285
|
-
})
|
|
47286
|
-
};
|
|
47287
48081
|
try {
|
|
47288
|
-
await
|
|
47289
|
-
if (hasOutput) {
|
|
47290
|
-
console.log();
|
|
47291
|
-
}
|
|
47292
|
-
} catch (error2) {
|
|
47293
|
-
if (error2 instanceof AgentLoopCancelledError) {} else {
|
|
47294
|
-
console.error(`
|
|
47295
|
-
Error: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
47296
|
-
}
|
|
48082
|
+
await this.server.sendUserMessage(prompt);
|
|
47297
48083
|
} finally {
|
|
47298
48084
|
this.isRunning = false;
|
|
47299
|
-
this.abortController = null;
|
|
47300
48085
|
console.log();
|
|
47301
48086
|
this.rl?.prompt();
|
|
47302
48087
|
}
|
|
47303
48088
|
}
|
|
47304
|
-
|
|
47305
|
-
|
|
47306
|
-
|
|
47307
|
-
|
|
47308
|
-
|
|
47309
|
-
|
|
47310
|
-
|
|
47311
|
-
|
|
47312
|
-
|
|
47313
|
-
|
|
47314
|
-
|
|
48089
|
+
handleServerOutput(message) {
|
|
48090
|
+
const msg = message;
|
|
48091
|
+
const type = msg.type;
|
|
48092
|
+
switch (type) {
|
|
48093
|
+
case "assistant": {
|
|
48094
|
+
const assistantMsg = msg.message;
|
|
48095
|
+
if (assistantMsg?.content) {
|
|
48096
|
+
for (const block of assistantMsg.content) {
|
|
48097
|
+
if (block.type === "text" && block.text) {
|
|
48098
|
+
process.stdout.write(block.text);
|
|
48099
|
+
} else if (block.type === "tool_use" && block.name) {
|
|
48100
|
+
const displayName = this.formatToolName(block.name);
|
|
48101
|
+
const args = this.formatToolArgs(block.input);
|
|
48102
|
+
process.stdout.write(`
|
|
47315
48103
|
[${displayName}${args}...]
|
|
47316
48104
|
`);
|
|
47317
|
-
|
|
48105
|
+
}
|
|
48106
|
+
}
|
|
47318
48107
|
}
|
|
47319
48108
|
break;
|
|
47320
|
-
|
|
47321
|
-
|
|
47322
|
-
|
|
47323
|
-
|
|
47324
|
-
|
|
47325
|
-
|
|
47326
|
-
|
|
47327
|
-
|
|
47328
|
-
|
|
47329
|
-
if (event.consolidationResult?.ran) {
|
|
47330
|
-
const r = event.consolidationResult;
|
|
47331
|
-
const changes = r.entriesCreated + r.entriesUpdated + r.entriesArchived;
|
|
47332
|
-
if (changes > 0) {
|
|
48109
|
+
}
|
|
48110
|
+
case "system": {
|
|
48111
|
+
const subtype = msg.subtype;
|
|
48112
|
+
switch (subtype) {
|
|
48113
|
+
case "init":
|
|
48114
|
+
break;
|
|
48115
|
+
case "tool_result":
|
|
48116
|
+
break;
|
|
48117
|
+
case "error":
|
|
47333
48118
|
process.stdout.write(`
|
|
48119
|
+
[Error: ${msg.message}]
|
|
48120
|
+
`);
|
|
48121
|
+
break;
|
|
48122
|
+
case "consolidation": {
|
|
48123
|
+
const changes = (msg.entries_created ?? 0) + (msg.entries_updated ?? 0) + (msg.entries_archived ?? 0);
|
|
48124
|
+
if (changes > 0) {
|
|
48125
|
+
process.stdout.write(`
|
|
47334
48126
|
[LTM updated: ${changes} change(s)]
|
|
47335
48127
|
`);
|
|
48128
|
+
}
|
|
48129
|
+
break;
|
|
47336
48130
|
}
|
|
48131
|
+
case "interrupted":
|
|
48132
|
+
break;
|
|
47337
48133
|
}
|
|
47338
|
-
markOutput();
|
|
47339
48134
|
break;
|
|
47340
|
-
|
|
47341
|
-
|
|
47342
|
-
[Memory compacted]
|
|
47343
|
-
`);
|
|
47344
|
-
markOutput();
|
|
48135
|
+
}
|
|
48136
|
+
case "result": {
|
|
47345
48137
|
break;
|
|
48138
|
+
}
|
|
47346
48139
|
}
|
|
47347
48140
|
}
|
|
47348
48141
|
formatToolName(name17) {
|
|
@@ -47355,25 +48148,35 @@ Error: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
|
47355
48148
|
grep: "Searching content",
|
|
47356
48149
|
present_set_mission: "Setting mission",
|
|
47357
48150
|
present_set_status: "Setting status",
|
|
47358
|
-
present_update_tasks: "Updating tasks"
|
|
48151
|
+
present_update_tasks: "Updating tasks",
|
|
48152
|
+
set_alarm: "Setting alarm",
|
|
48153
|
+
list_tasks: "Listing tasks",
|
|
48154
|
+
background_research: "Starting research",
|
|
48155
|
+
background_reflect: "Starting reflection",
|
|
48156
|
+
cancel_task: "Cancelling task"
|
|
47359
48157
|
};
|
|
47360
48158
|
return displayNames[name17] || name17;
|
|
47361
48159
|
}
|
|
47362
|
-
formatToolArgs(
|
|
47363
|
-
|
|
47364
|
-
|
|
47365
|
-
|
|
47366
|
-
|
|
47367
|
-
|
|
47368
|
-
|
|
47369
|
-
|
|
47370
|
-
|
|
47371
|
-
|
|
47372
|
-
|
|
47373
|
-
|
|
47374
|
-
|
|
47375
|
-
|
|
47376
|
-
|
|
48160
|
+
formatToolArgs(input) {
|
|
48161
|
+
if (!input || typeof input !== "object")
|
|
48162
|
+
return "";
|
|
48163
|
+
const args = input;
|
|
48164
|
+
if (args.path)
|
|
48165
|
+
return ` ${args.path}`;
|
|
48166
|
+
if (args.filePath)
|
|
48167
|
+
return ` ${args.filePath}`;
|
|
48168
|
+
if (args.pattern)
|
|
48169
|
+
return ` ${args.pattern}`;
|
|
48170
|
+
if (args.command) {
|
|
48171
|
+
const cmd = String(args.command);
|
|
48172
|
+
return ` ${cmd.slice(0, 50)}${cmd.length > 50 ? "..." : ""}`;
|
|
48173
|
+
}
|
|
48174
|
+
if (args.delay)
|
|
48175
|
+
return ` ${args.delay}`;
|
|
48176
|
+
if (args.topic)
|
|
48177
|
+
return ` "${String(args.topic).slice(0, 40)}..."`;
|
|
48178
|
+
if (args.question)
|
|
48179
|
+
return ` "${String(args.question).slice(0, 40)}..."`;
|
|
47377
48180
|
return "";
|
|
47378
48181
|
}
|
|
47379
48182
|
loadHistory() {
|
|
@@ -47408,8 +48211,8 @@ async function runRepl(options) {
|
|
|
47408
48211
|
}
|
|
47409
48212
|
|
|
47410
48213
|
// src/version.ts
|
|
47411
|
-
var VERSION = "0.
|
|
47412
|
-
var GIT_HASH = "
|
|
48214
|
+
var VERSION = "0.3.0";
|
|
48215
|
+
var GIT_HASH = "18005cc";
|
|
47413
48216
|
var VERSION_STRING = `miriad-code v${VERSION} (${GIT_HASH})`;
|
|
47414
48217
|
|
|
47415
48218
|
// src/cli/index.ts
|