@sandropadin/tend 0.1.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/src/types.ts ADDED
@@ -0,0 +1,73 @@
1
+ // Core data model. The whole detection system is data, not code: manifests
2
+ // describe how to recognize an agent and how to read its state off the rendered
3
+ // terminal.
4
+
5
+ export type AgentState = "blocked" | "working" | "idle" | "unknown";
6
+
7
+ // Which slice of the captured pane text a rule looks at. See src/regions.ts for
8
+ // the region extractor implementations.
9
+ export type Region =
10
+ | "full" // the entire capture
11
+ | "after_last_horizontal_rule" // everything below the last ─── rule (the live area)
12
+ | "prompt_box_body" // the interior of the input box (between its top/bottom borders)
13
+ | { bottom_non_empty_lines: number }; // the last N non-blank lines
14
+
15
+ export interface Rule {
16
+ id: string;
17
+ state: AgentState;
18
+ priority: number; // highest matching rule wins
19
+ region: Region;
20
+ contains?: string[]; // ALL of these substrings must be present (case-insensitive)
21
+ anyContains?: string[]; // AT LEAST ONE of these must be present
22
+ regex?: string; // regex (multiline, case-insensitive) that must match
23
+ not?: string[]; // NONE of these substrings may be present
24
+ // When true and this rule matches, hold the previously-known state instead of
25
+ // overwriting it. Used for scrollback / transcript / menu screens that don't
26
+ // reflect live agent state.
27
+ skipStateUpdate?: boolean;
28
+ }
29
+
30
+ export interface Manifest {
31
+ agent: string; // display name, e.g. "claude"
32
+ // pane_current_command values that identify this agent directly (fast path).
33
+ match: string[];
34
+ // Regex matched against pane_current_command. Claude Code renames its own
35
+ // process comm to its version string (e.g. "2.1.200"), so the literal name
36
+ // "claude" never appears — a semver pattern catches it. This is the most
37
+ // reliable signal because it's available regardless of what's scrolled into
38
+ // view, unlike screen signatures.
39
+ commandPattern?: string;
40
+ // Substrings that identify the agent from the *screen*, used when the process
41
+ // name is generic (e.g. Claude launched as `node`). These must be strings the
42
+ // agent keeps on screen in ANY state — persistent footer/chrome, not the
43
+ // welcome banner (which scrolls away mid-conversation).
44
+ signature: string[];
45
+ rules: Rule[];
46
+ }
47
+
48
+ export interface PaneInfo {
49
+ id: string; // tmux pane id, e.g. "%3"
50
+ command: string; // #{pane_current_command}
51
+ pid: number; // #{pane_pid}
52
+ path: string; // #{pane_current_path}
53
+ title: string; // #{pane_title}
54
+ sessionName: string; // #{session_name}
55
+ windowName: string; // #{window_name}
56
+ windowIndex: string; // #{window_index}
57
+ active: boolean;
58
+ }
59
+
60
+ export interface GitStatus {
61
+ branch: string | null;
62
+ dirty: boolean;
63
+ ahead: number;
64
+ behind: number;
65
+ }
66
+
67
+ export interface AgentStatus {
68
+ pane: PaneInfo;
69
+ agent: string;
70
+ state: AgentState;
71
+ matchedRule: string | null;
72
+ git: GitStatus | null;
73
+ }