aoaoe 0.89.0 → 0.90.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { execSync } from "node:child_process";
2
3
  import { loadConfig, validateEnvironment, parseCliArgs, printHelp, configFileExists, findConfigFile, DEFAULTS, computeConfigDiff } from "./config.js";
3
4
  import { Poller, computeTmuxName } from "./poller.js";
4
5
  import { createReasoner } from "./reasoner/index.js";
@@ -15,7 +16,7 @@ import { wakeableSleep } from "./wake.js";
15
16
  import { classifyMessages, formatUserMessages, buildReceipts, shouldSkipSleep, hasPendingFile, isInsistMessage, stripInsistPrefix } from "./message.js";
16
17
  import { TaskManager, loadTaskDefinitions, loadTaskState, formatTaskTable } from "./task-manager.js";
17
18
  import { runTaskCli, handleTaskSlashCommand } from "./task-cli.js";
18
- import { TUI, hitTestSession, nextSortMode, SORT_MODES, formatUptime } from "./tui.js";
19
+ import { TUI, hitTestSession, nextSortMode, SORT_MODES, formatUptime, formatClipText } from "./tui.js";
19
20
  import { isDaemonRunningFromState } from "./chat.js";
20
21
  import { sendNotification, sendTestNotification } from "./notify.js";
21
22
  import { startHealthServer } from "./health.js";
@@ -517,6 +518,30 @@ async function main() {
517
518
  }
518
519
  }
519
520
  });
521
+ // wire /clip to export activity entries to clipboard or file
522
+ input.onClip((count) => {
523
+ const buffer = tui.getActivityBuffer();
524
+ if (buffer.length === 0) {
525
+ tui.log("system", "no activity to clip");
526
+ return;
527
+ }
528
+ const text = formatClipText(buffer, count);
529
+ const entryCount = Math.min(count, buffer.length);
530
+ try {
531
+ execSync("pbcopy", { input: text, timeout: 5000 });
532
+ tui.log("system", `copied ${entryCount} entries to clipboard`);
533
+ }
534
+ catch {
535
+ try {
536
+ const clipPath = join(homedir(), ".aoaoe", "clip.txt");
537
+ writeFileSync(clipPath, text, "utf-8");
538
+ tui.log("system", `saved ${entryCount} entries to ~/.aoaoe/clip.txt`);
539
+ }
540
+ catch (writeErr) {
541
+ tui.log("error", `clip failed: ${writeErr}`);
542
+ }
543
+ }
544
+ });
520
545
  // wire mouse move to hover highlight on session cards (disabled in compact)
521
546
  input.onMouseMove((row, _col) => {
522
547
  if (tui.getViewMode() === "overview" && !tui.isCompact()) {
package/dist/input.d.ts CHANGED
@@ -18,6 +18,7 @@ export type UptimeHandler = () => void;
18
18
  export type AutoPinHandler = () => void;
19
19
  export type NoteHandler = (target: string, text: string) => void;
20
20
  export type NotesHandler = () => void;
21
+ export type ClipHandler = (count: number) => void;
21
22
  export interface MouseEvent {
22
23
  button: number;
23
24
  col: number;
@@ -58,6 +59,7 @@ export declare class InputReader {
58
59
  private autoPinHandler;
59
60
  private noteHandler;
60
61
  private notesHandler;
62
+ private clipHandler;
61
63
  private mouseDataListener;
62
64
  onScroll(handler: (dir: ScrollDirection) => void): void;
63
65
  onQueueChange(handler: (count: number) => void): void;
@@ -82,6 +84,7 @@ export declare class InputReader {
82
84
  onAutoPin(handler: AutoPinHandler): void;
83
85
  onNote(handler: NoteHandler): void;
84
86
  onNotes(handler: NotesHandler): void;
87
+ onClip(handler: ClipHandler): void;
85
88
  private notifyQueueChange;
86
89
  start(): void;
87
90
  drain(): string[];
package/dist/input.js CHANGED
@@ -50,6 +50,7 @@ export class InputReader {
50
50
  autoPinHandler = null;
51
51
  noteHandler = null;
52
52
  notesHandler = null;
53
+ clipHandler = null;
53
54
  mouseDataListener = null;
54
55
  // register a callback for scroll key events (PgUp/PgDn/Home/End)
55
56
  onScroll(handler) {
@@ -143,6 +144,10 @@ export class InputReader {
143
144
  onNotes(handler) {
144
145
  this.notesHandler = handler;
145
146
  }
147
+ // register a callback for clipboard export (/clip [N])
148
+ onClip(handler) {
149
+ this.clipHandler = handler;
150
+ }
146
151
  notifyQueueChange() {
147
152
  this.queueChangeHandler?.(this.queue.length);
148
153
  }
@@ -332,6 +337,7 @@ ${BOLD}navigation:${RESET}
332
337
  /auto-pin toggle auto-pin on error (pin sessions that emit errors)
333
338
  /note N|name text attach a note to a session (no text = clear)
334
339
  /notes list all session notes
340
+ /clip [N] copy last N activity entries to clipboard (default 20)
335
341
  /mark bookmark current activity position
336
342
  /jump N jump to bookmark N
337
343
  /marks list all bookmarks
@@ -543,6 +549,20 @@ ${BOLD}other:${RESET}
543
549
  console.error(`${DIM}notes not available (no TUI)${RESET}`);
544
550
  }
545
551
  break;
552
+ case "/clip": {
553
+ const clipArg = line.slice("/clip".length).trim();
554
+ const clipCount = clipArg ? parseInt(clipArg, 10) : 20;
555
+ if (this.clipHandler && !isNaN(clipCount) && clipCount > 0) {
556
+ this.clipHandler(clipCount);
557
+ }
558
+ else if (!this.clipHandler) {
559
+ console.error(`${DIM}clip not available (no TUI)${RESET}`);
560
+ }
561
+ else {
562
+ console.error(`${DIM}usage: /clip [N] — copy last N activity entries to clipboard${RESET}`);
563
+ }
564
+ break;
565
+ }
546
566
  case "/mark":
547
567
  if (this.markHandler) {
548
568
  this.markHandler();
package/dist/tui.d.ts CHANGED
@@ -57,6 +57,10 @@ export declare function formatMuteBadge(count: number): string;
57
57
  export declare function matchesTagFilter(entry: ActivityEntry, tag: string): boolean;
58
58
  /** Format the tag filter indicator text for the separator bar. */
59
59
  export declare function formatTagFilterIndicator(tag: string, matchCount: number, totalCount: number): string;
60
+ /** Default number of entries for /clip when no count specified. */
61
+ export declare const CLIP_DEFAULT_COUNT = 20;
62
+ /** Format activity entries as plain text for clipboard/export. One line per entry. */
63
+ export declare function formatClipText(entries: readonly ActivityEntry[], n?: number): string;
60
64
  /** Determine if a log entry should trigger auto-pin (error-like tags). */
61
65
  export declare function shouldAutoPin(tag: string): boolean;
62
66
  /** Format milliseconds as human-readable uptime: "2h 15m", "45m", "3d 2h", "< 1m". */
@@ -175,6 +179,8 @@ export declare class TUI {
175
179
  getUptime(id: string): number;
176
180
  /** Return all session first-seen timestamps (for /uptime listing). */
177
181
  getAllFirstSeen(): ReadonlyMap<string, number>;
182
+ /** Return the activity buffer (for /clip export). */
183
+ getActivityBuffer(): readonly ActivityEntry[];
178
184
  /**
179
185
  * Add a bookmark at the current activity position.
180
186
  * Returns the bookmark number (1-indexed) or 0 if buffer is empty.
package/dist/tui.js CHANGED
@@ -191,6 +191,15 @@ export function matchesTagFilter(entry, tag) {
191
191
  export function formatTagFilterIndicator(tag, matchCount, totalCount) {
192
192
  return `${SLATE}filter:${RESET} ${AMBER}${tag}${RESET} ${DIM}(${matchCount}/${totalCount})${RESET}`;
193
193
  }
194
+ // ── Clip ─────────────────────────────────────────────────────────────────────
195
+ /** Default number of entries for /clip when no count specified. */
196
+ export const CLIP_DEFAULT_COUNT = 20;
197
+ /** Format activity entries as plain text for clipboard/export. One line per entry. */
198
+ export function formatClipText(entries, n) {
199
+ const count = n ?? CLIP_DEFAULT_COUNT;
200
+ const slice = entries.slice(-Math.max(1, count));
201
+ return slice.map((e) => `[${e.time}] ${e.tag}: ${e.text}`).join("\n") + "\n";
202
+ }
194
203
  // ── Auto-pin ─────────────────────────────────────────────────────────────────
195
204
  /** Determine if a log entry should trigger auto-pin (error-like tags). */
196
205
  export function shouldAutoPin(tag) {
@@ -527,6 +536,10 @@ export class TUI {
527
536
  getAllFirstSeen() {
528
537
  return this.sessionFirstSeen;
529
538
  }
539
+ /** Return the activity buffer (for /clip export). */
540
+ getActivityBuffer() {
541
+ return this.activityBuffer;
542
+ }
530
543
  /**
531
544
  * Add a bookmark at the current activity position.
532
545
  * Returns the bookmark number (1-indexed) or 0 if buffer is empty.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aoaoe",
3
- "version": "0.89.0",
3
+ "version": "0.90.0",
4
4
  "description": "Autonomous supervisor for agent-of-empires sessions using OpenCode or Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",