open-agents-ai 0.187.58 → 0.187.59

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.
Files changed (2) hide show
  1. package/dist/index.js +174 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -276129,17 +276129,20 @@ var oa_directory_exports = {};
276129
276129
  __export(oa_directory_exports, {
276130
276130
  OA_DIR: () => OA_DIR,
276131
276131
  buildContextRestorePrompt: () => buildContextRestorePrompt,
276132
+ deleteSession: () => deleteSession,
276132
276133
  deleteUsageRecord: () => deleteUsageRecord,
276133
276134
  discoverContextFiles: () => discoverContextFiles,
276134
276135
  generateProjectMap: () => generateProjectMap,
276135
276136
  getLastTaskSummary: () => getLastTaskSummary,
276136
276137
  hasOaDirectory: () => hasOaDirectory,
276137
276138
  initOaDirectory: () => initOaDirectory,
276139
+ listSessions: () => listSessions,
276138
276140
  loadGlobalSettings: () => loadGlobalSettings,
276139
276141
  loadPendingTask: () => loadPendingTask,
276140
276142
  loadProjectSettings: () => loadProjectSettings,
276141
276143
  loadRecentSessions: () => loadRecentSessions,
276142
276144
  loadSessionContext: () => loadSessionContext,
276145
+ loadSessionHistory: () => loadSessionHistory,
276143
276146
  loadUsageHistory: () => loadUsageHistory,
276144
276147
  readIndexData: () => readIndexData,
276145
276148
  readIndexMeta: () => readIndexMeta,
@@ -276150,6 +276153,7 @@ __export(oa_directory_exports, {
276150
276153
  saveProjectSettings: () => saveProjectSettings,
276151
276154
  saveSession: () => saveSession,
276152
276155
  saveSessionContext: () => saveSessionContext,
276156
+ saveSessionHistory: () => saveSessionHistory,
276153
276157
  writeIndexData: () => writeIndexData,
276154
276158
  writeIndexMeta: () => writeIndexMeta
276155
276159
  });
@@ -276469,6 +276473,111 @@ function getLastTaskSummary(repoRoot) {
276469
276473
  const clean3 = text.replace(/^\[.*?\]\s*/, "").replace(/\s+/g, " ").trim();
276470
276474
  return clean3.length > 40 ? clean3.slice(0, 37) + "..." : clean3;
276471
276475
  }
276476
+ function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
276477
+ const sessDir = join58(repoRoot, OA_DIR, SESSIONS_DIR);
276478
+ mkdirSync16(sessDir, { recursive: true });
276479
+ const stripped = contentLines.map((line) => typeof line === "string" ? line.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "") : "");
276480
+ const autoName = meta.name || generateSessionName(stripped);
276481
+ const autoDesc = meta.description || generateSessionDescription(stripped);
276482
+ const contentPath = join58(sessDir, `${sessionId}.jsonl`);
276483
+ writeFileSync17(contentPath, stripped.join("\n"), "utf-8");
276484
+ const indexPath = join58(sessDir, SESSIONS_INDEX);
276485
+ let index = [];
276486
+ try {
276487
+ if (existsSync41(indexPath)) {
276488
+ index = JSON.parse(readFileSync31(indexPath, "utf-8"));
276489
+ }
276490
+ } catch {
276491
+ }
276492
+ const existing = index.findIndex((s2) => s2.id === sessionId);
276493
+ const record = {
276494
+ id: sessionId,
276495
+ name: autoName,
276496
+ description: autoDesc,
276497
+ createdAt: existing >= 0 ? index[existing].createdAt : (/* @__PURE__ */ new Date()).toISOString(),
276498
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
276499
+ taskCount: meta.taskCount ?? 1,
276500
+ model: meta.model ?? "unknown"
276501
+ };
276502
+ if (existing >= 0) {
276503
+ index[existing] = record;
276504
+ } else {
276505
+ index.push(record);
276506
+ }
276507
+ if (index.length > 50) {
276508
+ const removed = index.shift();
276509
+ try {
276510
+ unlinkSync7(join58(sessDir, `${removed.id}.jsonl`));
276511
+ } catch {
276512
+ }
276513
+ }
276514
+ writeFileSync17(indexPath, JSON.stringify(index, null, 2), "utf-8");
276515
+ }
276516
+ function listSessions(repoRoot) {
276517
+ const indexPath = join58(repoRoot, OA_DIR, SESSIONS_DIR, SESSIONS_INDEX);
276518
+ try {
276519
+ if (!existsSync41(indexPath))
276520
+ return [];
276521
+ const index = JSON.parse(readFileSync31(indexPath, "utf-8"));
276522
+ return index.sort((a2, b) => b.updatedAt.localeCompare(a2.updatedAt));
276523
+ } catch {
276524
+ return [];
276525
+ }
276526
+ }
276527
+ function loadSessionHistory(repoRoot, sessionId) {
276528
+ const contentPath = join58(repoRoot, OA_DIR, SESSIONS_DIR, `${sessionId}.jsonl`);
276529
+ try {
276530
+ if (!existsSync41(contentPath))
276531
+ return null;
276532
+ return readFileSync31(contentPath, "utf-8").split("\n");
276533
+ } catch {
276534
+ return null;
276535
+ }
276536
+ }
276537
+ function deleteSession(repoRoot, sessionId) {
276538
+ const sessDir = join58(repoRoot, OA_DIR, SESSIONS_DIR);
276539
+ const indexPath = join58(sessDir, SESSIONS_INDEX);
276540
+ try {
276541
+ const contentPath = join58(sessDir, `${sessionId}.jsonl`);
276542
+ if (existsSync41(contentPath))
276543
+ unlinkSync7(contentPath);
276544
+ if (existsSync41(indexPath)) {
276545
+ let index = JSON.parse(readFileSync31(indexPath, "utf-8"));
276546
+ index = index.filter((s2) => s2.id !== sessionId);
276547
+ writeFileSync17(indexPath, JSON.stringify(index, null, 2), "utf-8");
276548
+ }
276549
+ return true;
276550
+ } catch {
276551
+ return false;
276552
+ }
276553
+ }
276554
+ function generateSessionName(lines) {
276555
+ for (const line of lines.slice(0, 30)) {
276556
+ const clean3 = line.trim();
276557
+ if (clean3.length > 10 && !clean3.startsWith("i ") && !clean3.startsWith(" ")) {
276558
+ const phrase = clean3.replace(/^[>❯▹]\s*/, "").slice(0, 40);
276559
+ return phrase.length > 37 ? phrase.slice(0, 37) + "..." : phrase;
276560
+ }
276561
+ }
276562
+ return `Session ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
276563
+ }
276564
+ function generateSessionDescription(lines) {
276565
+ const topics = [];
276566
+ const seen = /* @__PURE__ */ new Set();
276567
+ for (const line of lines) {
276568
+ const fileMatch = line.match(/(?:Read|Write|Edit|Shell):\s*(.+)/);
276569
+ if (fileMatch) {
276570
+ const file = fileMatch[1].trim().slice(0, 30);
276571
+ if (!seen.has(file)) {
276572
+ topics.push(file);
276573
+ seen.add(file);
276574
+ }
276575
+ }
276576
+ if (topics.length >= 3)
276577
+ break;
276578
+ }
276579
+ return topics.length > 0 ? topics.join(", ") : "General session";
276580
+ }
276472
276581
  function detectManifests(repoRoot) {
276473
276582
  const manifests = [];
276474
276583
  const checks = [
@@ -276646,7 +276755,7 @@ function deleteUsageRecord(kind, value2, repoRoot) {
276646
276755
  remove(join58(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
276647
276756
  }
276648
276757
  }
276649
- var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
276758
+ var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SESSIONS_DIR, SESSIONS_INDEX, SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
276650
276759
  var init_oa_directory = __esm({
276651
276760
  "packages/cli/dist/tui/oa-directory.js"() {
276652
276761
  "use strict";
@@ -276665,6 +276774,8 @@ var init_oa_directory = __esm({
276665
276774
  PENDING_TASK_FILE = "pending-task.json";
276666
276775
  CONTEXT_SAVE_FILE = "session-context.json";
276667
276776
  MAX_CONTEXT_ENTRIES = 20;
276777
+ SESSIONS_DIR = "sessions";
276778
+ SESSIONS_INDEX = "sessions-index.json";
276668
276779
  SKIP_DIRS = /* @__PURE__ */ new Set([
276669
276780
  "node_modules",
276670
276781
  ".git",
@@ -285653,6 +285764,11 @@ async function handleSlashCommand(input, ctx3) {
285653
285764
  await showColorMenu(ctx3);
285654
285765
  return "handled";
285655
285766
  }
285767
+ case "sessions":
285768
+ case "session": {
285769
+ await showSessionsMenu(ctx3);
285770
+ return "handled";
285771
+ }
285656
285772
  case "cost":
285657
285773
  case "costs":
285658
285774
  if (ctx3.costTracker) {
@@ -288263,6 +288379,44 @@ The session corrections MUST become hard rules in the SKILL.md Rules section.`;
288263
288379
  }
288264
288380
  }
288265
288381
  }
288382
+ async function showSessionsMenu(ctx3) {
288383
+ const sessions2 = listSessions(ctx3.repoRoot);
288384
+ if (sessions2.length === 0) {
288385
+ renderInfo("No saved sessions found. Sessions are saved automatically after each task.");
288386
+ return;
288387
+ }
288388
+ const items = sessions2.map((s2) => {
288389
+ const date = s2.updatedAt.slice(0, 16).replace("T", " ");
288390
+ const tasks = s2.taskCount > 1 ? `${s2.taskCount} tasks` : "1 task";
288391
+ return {
288392
+ key: s2.id,
288393
+ label: `${s2.name}`,
288394
+ detail: `${date} | ${tasks} | ${s2.model}`
288395
+ };
288396
+ });
288397
+ const result = await tuiSelect({
288398
+ items,
288399
+ title: "Session History",
288400
+ onDelete: async (item) => {
288401
+ deleteSession(ctx3.repoRoot, item.key);
288402
+ return true;
288403
+ }
288404
+ });
288405
+ if (!result || result.key === "cancel")
288406
+ return;
288407
+ const content = loadSessionHistory(ctx3.repoRoot, result.key);
288408
+ if (!content || content.length === 0) {
288409
+ renderWarning("Session content not found or empty.");
288410
+ return;
288411
+ }
288412
+ const session = sessions2.find((s2) => s2.id === result.key);
288413
+ renderInfo(`Loading session: ${session?.name ?? result.key} (${content.length} lines)`);
288414
+ for (const line of content) {
288415
+ process.stdout.write(` ${line}
288416
+ `);
288417
+ }
288418
+ renderInfo("Session history loaded. Scroll up to review.");
288419
+ }
288266
288420
  async function showColorMenu(_ctx) {
288267
288421
  const currentConfig = getThemeConfig();
288268
288422
  const items = [
@@ -291308,7 +291462,7 @@ function loadMemoryDir(memDir, scope) {
291308
291462
  }
291309
291463
  return lines.join("\n");
291310
291464
  }
291311
- function loadSessionHistory(repoRoot) {
291465
+ function loadSessionHistory2(repoRoot) {
291312
291466
  const sessions2 = loadRecentSessions(repoRoot, 5);
291313
291467
  if (sessions2.length === 0)
291314
291468
  return "";
@@ -291411,7 +291565,7 @@ function buildProjectContext(repoRoot, stores) {
291411
291565
  projectMap: loadProjectMap(repoRoot),
291412
291566
  gitInfo: getGitInfo(repoRoot),
291413
291567
  memoryContext: loadMemoryContext(repoRoot),
291414
- sessionHistory: loadSessionHistory(repoRoot),
291568
+ sessionHistory: loadSessionHistory2(repoRoot),
291415
291569
  environment: getEnvironment(repoRoot),
291416
291570
  taskMemories: stores?.taskMemoryStore ? loadTaskMemories(repoRoot, stores.taskMemoryStore) : "",
291417
291571
  failurePatterns: stores?.failureStore ? loadFailurePatterns(stores.failureStore) : "",
@@ -303910,7 +304064,7 @@ function addAssistantMessage(session, content) {
303910
304064
  session.messages.push({ role: "assistant", content });
303911
304065
  session.lastActivity = Date.now();
303912
304066
  }
303913
- function listSessions() {
304067
+ function listSessions2() {
303914
304068
  return Array.from(sessions.values()).map((s2) => ({
303915
304069
  id: s2.id,
303916
304070
  model: s2.model,
@@ -306035,7 +306189,7 @@ ${historyLines}
306035
306189
  if (pathname === "/v1/chat/sessions" && method === "GET") {
306036
306190
  if (!checkAuth(req2, res, "read"))
306037
306191
  return;
306038
- jsonResponse(res, 200, { sessions: listSessions() });
306192
+ jsonResponse(res, 200, { sessions: listSessions2() });
306039
306193
  return;
306040
306194
  }
306041
306195
  if (pathname === "/v1/models" && method === "GET") {
@@ -308134,6 +308288,21 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
308134
308288
  });
308135
308289
  } catch {
308136
308290
  }
308291
+ try {
308292
+ const sessionId2 = `session-${Date.now().toString(36)}`;
308293
+ const contentLines = statusBar?._contentLines ?? [];
308294
+ if (contentLines.length > 0) {
308295
+ saveSessionHistory(repoRoot, sessionId2, contentLines, {
308296
+ name: void 0,
308297
+ // auto-generate from content
308298
+ description: void 0,
308299
+ // auto-generate
308300
+ taskCount: 1,
308301
+ model: config.model
308302
+ });
308303
+ }
308304
+ } catch {
308305
+ }
308137
308306
  if (taskStores?.taskMemoryStore) {
308138
308307
  try {
308139
308308
  taskStores.taskMemoryStore.insert({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.58",
3
+ "version": "0.187.59",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",