@zeph-to/hook-sdk 1.8.0 → 1.10.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.
@@ -0,0 +1,116 @@
1
+ /**
2
+ * `zeph listener` — resident daemon that watches the user's Zeph feed
3
+ * over a persistent WebSocket and injects matching messages into a
4
+ * named tmux session via `tmux send-keys`.
5
+ *
6
+ * Solves the MCP polling-window problem: an `zeph_ask` polling cycle
7
+ * times out (120–600 s) and the CC/Codex session becomes unaddressable
8
+ * from the phone. The listener stays subscribed indefinitely and can
9
+ * deliver to any named tmux session at any time.
10
+ *
11
+ * Wire format: pushes with `type='agent.command'` carry the tmux
12
+ * session name in `agentSessionName` and the message in `body`. The
13
+ * "AI Agent에게 명령" sheet on the phone builds these structured
14
+ * pushes from the listener-reported session inventory. Other push
15
+ * types (Stop-hook auto-pushes, zeph_ask responses, channel
16
+ * broadcasts) are ignored.
17
+ *
18
+ * Transport: WebSocket against the Zeph $connect endpoint with
19
+ * `?apiKey=<key>`. The server fan-out pushes `{ type: 'push.new', data }`
20
+ * messages as new pushes are created. Reconnects with exponential
21
+ * backoff on transient failures; gives up on auth failures (4001/4002/4003).
22
+ */
23
+ type AgentKind = 'claude' | 'codex' | 'gemini';
24
+ interface AgentSession {
25
+ name: string;
26
+ attached: boolean;
27
+ agentKind: AgentKind;
28
+ agentSessionId?: string | null;
29
+ project: string;
30
+ label?: string | null;
31
+ createdAt?: string;
32
+ lastActivityAt?: string;
33
+ }
34
+ export declare const checkRateLimit: (session: string, now?: number) => boolean;
35
+ /** Read the foreground command in the named tmux session's active pane. */
36
+ export declare const paneCurrentCommand: (session: string) => string | null;
37
+ /**
38
+ * Parse a `zeph-*` tmux session name into `{project, label}`. For
39
+ * Phase 1 the wrapper only emits `zeph-<project>` (no labels), so the
40
+ * whole tail becomes the project. When labels land in Phase 2 the
41
+ * wrapper will sidecar `{project, label}` so the listener doesn't need
42
+ * to guess from a name that allows dashes in project names.
43
+ */
44
+ export declare const parseSessionName: (name: string) => {
45
+ project: string;
46
+ label: string | null;
47
+ } | null;
48
+ /**
49
+ * Locate the most recent Claude Code session UUID for the working
50
+ * directory of a tmux pane. Mirrors `mcp-server/config.ts`'s
51
+ * detectClaudeSessionId: CC writes per-session jsonl files at
52
+ * `~/.claude/projects/<projectHash>/<UUID>.jsonl` where the hash is
53
+ * the cwd with `/` replaced by `-`.
54
+ */
55
+ export declare const detectClaudeSessionId: (cwd: string) => string | null;
56
+ export interface CollectResult {
57
+ sessions: AgentSession[];
58
+ /** Diagnostic notes per rejected session — surfaced under `--verbose`. */
59
+ rejected: Array<{
60
+ name: string;
61
+ reason: string;
62
+ }>;
63
+ }
64
+ /**
65
+ * Inventory pass that also records *why* each `zeph-*` session was
66
+ * skipped. The verbose log uses the rejection notes to explain empty
67
+ * pickers (most common cause: tmux pane lost its start_command after a
68
+ * re-attach, and the current command is `node` rather than `claude`).
69
+ */
70
+ export declare const collectSessionsVerbose: () => CollectResult;
71
+ /**
72
+ * Snapshot the live `zeph-*` tmux sessions on this machine, enriched
73
+ * with the running agent kind, CC session UUID (claude only), project,
74
+ * and tmux activity timestamps. Returns [] when tmux is unreachable
75
+ * or no agent sessions exist. Sessions whose pane is at a shell or
76
+ * running something other than claude/codex/gemini are filtered out
77
+ * — the phone can't usefully address them.
78
+ */
79
+ export declare const collectSessions: () => AgentSession[];
80
+ interface PushItem {
81
+ pushId: string;
82
+ type?: string;
83
+ body?: string;
84
+ title?: string;
85
+ createdAt?: string;
86
+ isEncrypted?: boolean;
87
+ /** Set when type='agent.command' — tmux session name to inject into. */
88
+ agentSessionName?: string;
89
+ }
90
+ interface HandlePushDeps {
91
+ paneCommand?: (session: string) => string | null;
92
+ inject?: (session: string, text: string) => boolean;
93
+ rateLimit?: (session: string) => boolean;
94
+ now?: () => number;
95
+ }
96
+ /**
97
+ * Process one push. Returns true when an injection actually fired.
98
+ * Exported for unit testing with mocked deps.
99
+ *
100
+ * Only acts on `type='agent.command'` pushes carrying both an
101
+ * `agentSessionName` (tmux session to inject into) and a non-empty
102
+ * `body`. Everything else (Stop-hook auto-pushes, zeph_ask responses,
103
+ * encrypted pushes, normal text/link/file notifications) is ignored.
104
+ */
105
+ export declare const handlePush: (push: PushItem, deps?: HandlePushDeps) => boolean;
106
+ /**
107
+ * Stable per-host device id for the listener. We hash the OS hostname so
108
+ * the same machine reuses the same DeviceRecord across listener restarts
109
+ * (otherwise the phone's session inventory grows a new ghost device every
110
+ * time `zeph listener` rebinds). `dev_listener_<sha8(hostname)>` keeps it
111
+ * human-recognisable in dev logs without leaking the raw hostname.
112
+ */
113
+ export declare const computeListenerDeviceId: (host?: string) => string;
114
+ export declare const handleListener: (args: Record<string, string | boolean>) => Promise<number>;
115
+ export {};
116
+ //# sourceMappingURL=listener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAuBH,KAAK,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAG/C,UAAU,YAAY;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AA2BD,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,EAAE,MAAK,MAAmB,KAAG,OAgB1E,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,MAAM,GAAG,IAO7D,CAAC;AA6QF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAK3F,CAAC;AAIF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAkB5D,CAAC;AAoEF,MAAM,WAAW,aAAa;IAC1B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAAO,aA0DzC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,QAAO,YAAY,EAAuC,CAAC;AAIvF,UAAU,QAAQ;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,UAAU,cAAc;IACpB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACjD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACpD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAgCD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GACnB,MAAM,QAAQ,EACd,OAAM,cAAmB,KAC1B,OAQF,CAAC;AA2BF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAAI,OAAM,MAAmB,KAAG,MAGnE,CAAC;AAyLF,eAAO,MAAM,cAAc,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CA6E3F,CAAC"}