crisp-tui 0.0.0-stage → 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 solcreek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,269 @@
1
- # Temporary Holding Version
1
+ # crisp-tui
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Crisp support inbox built with OpenTUI, SolidJS and Bun. People use the TUI;
4
+ agents use JSON commands and can prepare drafts in the same running screen.
5
+ [crispctl](https://github.com/solcreek/crisp-cli) v0.2.0 provides all REST and RTM
6
+ access. Both profile-based and 1Password sessions use its JSON interface;
7
+ this project has no separate HTTP or Socket.IO implementation.
8
+
9
+ ## Install
10
+
11
+ Requires [Bun](https://bun.sh) 1.4.2 or newer and Node.js 20 or newer on macOS or Linux.
12
+ The npm package installs the `crisp-tui` command; Bun must also be on PATH.
13
+
14
+ ```sh
15
+ npm install -g crisp-tui
16
+ crisp-tui --demo
17
+ ```
18
+
19
+ For a Crisp workspace, use `crisp-tui --read-only --profile sandbox --poll 0`
20
+ with a crispctl profile configured, or `crisp-tui live --item 'Crisp development'` with
21
+ 1Password. `crisp-tui check --item 'Crisp development'` runs a bounded read-only
22
+ connection check. Add `--rtm-timeout 60` to require RTM authentication and an
23
+ actual event within 60 seconds. The npm package includes crispctl as a dependency.
24
+ The following `bun run` examples are for a source checkout.
25
+
26
+ ## Run from source
27
+
28
+ Requires Bun 1.4.2 or newer on macOS or Linux. Demo mode needs no credentials.
29
+
30
+ ```sh
31
+ git clone https://github.com/solcreek/crisp-tui.git
32
+ cd crisp-tui
33
+ bun install
34
+ bun run demo
35
+ ```
36
+
37
+ Demo mode is explicit, in-memory, and never contacts Crisp. In another terminal:
38
+
39
+ ```sh
40
+ bun run src/index.ts ctl state
41
+ bun run src/index.ts ctl goto session_demo_2
42
+ bun run src/index.ts ctl draft session_demo_2 '我來協助你確認設定。'
43
+ bun run src/index.ts ctl screen
44
+ ```
45
+
46
+ The draft appears in the composer. Review it and press Enter to send. Demo
47
+ messages and drafts disappear on exit. Live mode never falls back to demo data.
48
+
49
+ ## Read real data with 1Password
50
+
51
+ With `op` connected to the unlocked 1Password desktop app, create an item with
52
+ `API Identifier`, `API Key` and `website_id` fields. Choose its name explicitly:
53
+
54
+ ```sh
55
+ bun run live:check --item 'Crisp development' # connection + rendering check
56
+ bun run live:readonly --item 'Crisp development' # interactive read-only TUI
57
+ ```
58
+
59
+ `--website UUID` optionally overrides the item's website ID.
60
+ The credential fields are passed to crispctl through the child environment; no
61
+ config file, token file or customer-data capture is written. Errors omit raw
62
+ API response bodies and headers. The check prints website ID, counts,
63
+ message types and command names, without customer names or message text.
64
+
65
+ The session passes both `--read-only` and `CRISPCTL_READ_ONLY=1` to crispctl.
66
+ Its REST layer rejects non-GET/HEAD requests, and its listener only subscribes to
67
+ events. The TUI adapter also rejects
68
+ reply/note, resolve/reopen and mark-read before any HTTP request. The TUI displays
69
+ `READ ONLY` and hides its composer; agent drafts are disabled too. Automatic
70
+ polling is off in this mode: RTM events trigger refreshes, and Ctrl+R refreshes
71
+ manually. Opening a conversation does not mark it read.
72
+
73
+ `live:check` normally uses three REST commands: the first conversation page,
74
+ details of the first conversation, and its messages (one if the inbox is empty).
75
+ With `--rtm-timeout N`, it additionally listens until an event is received or the
76
+ deadline expires. It never sends a test message to generate that event.
77
+
78
+ For a crispctl-backed TUI, the same client/UI protection is available as:
79
+
80
+ ```sh
81
+ bun run dev --read-only --profile sandbox --poll 0
82
+ ```
83
+
84
+ The flag applies to that TUI instance. The independent `cli` bridge retains
85
+ crispctl's own capabilities. To control the 1Password TUI, use `ctl` with
86
+ `--profile onepassword-readonly --website UUID` (or the same
87
+ `CRISP_TUI_SOCKET` override).
88
+
89
+ ## Website token setup
90
+
91
+ This TUI uses **website tokens**. As specified in the
92
+ [Crisp website token documentation](https://docs.crisp.chat/guides/rest-api/authentication/website-token/),
93
+ requests use Basic auth with `identifier:key` and `X-Crisp-Tier: website`.
94
+ The token belongs to one workspace. `crispctl` supplies these headers; this
95
+ project never includes the secret in UI state or stores a second copy.
96
+
97
+ The npm installation includes crispctl v0.2.0. To configure it separately on PATH:
98
+
99
+ ```sh
100
+ npm install -g crispctl@0.2.0
101
+ ```
102
+
103
+ Alternatively, build [crisp-cli from source](https://github.com/solcreek/crisp-cli#install)
104
+ in an adjacent checkout. For the read/write workflow below, configure a sandbox
105
+ profile using environment variables in your shell. Use a development workspace
106
+ for write testing, or the GET-only workflow above when inspecting real data.
107
+
108
+ ```sh
109
+ export CRISP_IDENTIFIER='your-website-token-identifier'
110
+ export CRISP_KEY='your-website-token-key'
111
+ export CRISP_WEBSITE_ID='your-sandbox-website-id'
112
+ export CRISP_TIER=website
113
+
114
+ bun run src/index.ts cli auth set --profile sandbox
115
+ bun run dev --profile sandbox
116
+ ```
117
+
118
+ The TUI defaults to `sandbox` (or `CRISPCTL_PROFILE`) and checks `auth show`
119
+ before starting. This is a local configuration check, not an API authentication
120
+ probe. It requires `tier=website`, identifier, key and website ID. An API error
121
+ appears in the status bar. The active website ID is visible in the header.
122
+
123
+ All crispctl config and environment precedence still applies, including
124
+ `CRISPCTL_CONFIG` and `CRISPCTL_*` credential overrides. `--website ID` is forwarded
125
+ to crispctl. Select the same `--profile` / `--website` when issuing `ctl` commands.
126
+
127
+ Executable lookup: `CRISPCTL_BIN` (one executable path, not a shell command),
128
+ then the installed crispctl dependency, then `crispctl` on PATH, then
129
+ `../crisp-cli/dist/index.js` relative to this source
130
+ checkout. The last option requires Node. A compiled TUI should use PATH or
131
+ `CRISPCTL_BIN`. Credentials stay in the subprocess environment/config; commands
132
+ are spawned as argument arrays, never shell strings.
133
+
134
+ ## Human workflow
135
+
136
+ The inbox supports paged conversations, server-side search, messages, text and
137
+ file-link display, replies, internal notes, resolve/reopen and explicit mark read.
138
+ Opening or polling a conversation does not mark it read. Drafts and reply/note
139
+ mode are kept separately for each conversation during this process.
140
+
141
+ | Key | Action |
142
+ | --- | --- |
143
+ | Tab / Shift+Tab | Cycle inbox, messages, composer |
144
+ | ↑↓ / j k | Select inbox row or scroll messages |
145
+ | Enter in inbox | Open conversation |
146
+ | Click inbox row | Open conversation |
147
+ | / in inbox/messages | Search; Enter submits; empty search returns to all |
148
+ | [ / ] in inbox/messages | Previous / next inbox page |
149
+ | Enter in composer | Send reply or internal note |
150
+ | Shift+Enter / Alt+Enter / Ctrl+J | Newline |
151
+ | Ctrl+N | Toggle reply / internal note |
152
+ | Ctrl+E | Resolve / reopen active conversation |
153
+ | Ctrl+U | Mark active conversation read |
154
+ | Ctrl+R | Refresh inbox and active conversation |
155
+ | Esc | Focus inbox |
156
+ | Ctrl+C | Quit |
157
+
158
+ A failed send keeps the draft; writes are never retried automatically. A timeout
159
+ can leave the send outcome unknown, so refresh before resending. Once a send is
160
+ acknowledged, a failed follow-up refresh does not restore the draft.
161
+
162
+ ## Agent workflow
163
+
164
+ Direct API operations work without a TUI. This is a verbatim bridge to crispctl;
165
+ pass its profile and `--json` flags explicitly:
166
+
167
+ ```sh
168
+ bun run src/index.ts cli conversations list --profile sandbox --json
169
+ bun run src/index.ts cli messages list SESSION --profile sandbox --json
170
+ bun run src/index.ts cli reply SESSION --text 'Hello!' --profile sandbox --json
171
+ bun run src/index.ts cli assign SESSION --user OPERATOR_ID --profile sandbox --json
172
+ bun run src/index.ts cli segments SESSION --set billing,followup --profile sandbox --json
173
+ ```
174
+
175
+ All other crispctl commands are available through `cli`, including people,
176
+ operators, resolve and reopen. Direct write commands act immediately.
177
+
178
+ The control commands work against the running TUI:
179
+
180
+ ```sh
181
+ bun run src/index.ts ctl state
182
+ bun run src/index.ts ctl conversations
183
+ bun run src/index.ts ctl messages
184
+ bun run src/index.ts ctl goto SESSION
185
+ bun run src/index.ts ctl draft SESSION 'Proposed reply'
186
+ bun run src/index.ts ctl draft SESSION 'Internal context' --note
187
+ bun run src/index.ts ctl draft SESSION 'Revised draft' --replace
188
+ bun run src/index.ts ctl refresh
189
+ bun run src/index.ts ctl screen
190
+ ```
191
+
192
+ `state` includes protocol version, source, current page/query, active conversation,
193
+ loaded messages, per-session drafts and status. `messages` and `conversations`
194
+ return the currently loaded page, without an API call. `screen` is a semantic
195
+ text view of the loaded content, not an exact terminal screenshot. All other
196
+ successful control results are JSON; errors are JSON on stderr. Exit codes are
197
+ 0 success, 1 operation error, 2 usage error, 3 no running TUI. `cli` preserves
198
+ crispctl's own output and exit code.
199
+
200
+ `draft` never sends or replaces an existing nonempty draft without `--replace`.
201
+ It switches to the target conversation and focuses the composer. There is no
202
+ control-socket send method; direct automated writes belong to crispctl.
203
+
204
+ ### Control protocol
205
+
206
+ Unix socket in `/tmp/crisp-tui-<uid>/<profile-and-website-hash>.sock`.
207
+ Directory mode 0700, socket mode 0600. One TUI per socket; stale sockets are
208
+ recovered. Override with `CRISP_TUI_SOCKET` in both processes, using a
209
+ private parent directory. Demo and live share the selected profile socket, so
210
+ inspect `state.source` before acting. Processes using different config files
211
+ under the same profile name should use different socket overrides.
212
+
213
+ One newline-delimited JSON request per connection:
214
+
215
+ ```json
216
+ {"id":1,"method":"draft","params":{"session":"session_demo_1","text":"Hello","note":false}}
217
+ ```
218
+
219
+ Response: `{"id":1,"ok":true,"result":…}` or
220
+ `{"id":1,"ok":false,"error":"…"}`. Methods match `ctl` verbs. Screen-changing
221
+ agent requests are serialized. No TCP server, daemon or MCP server is started.
222
+
223
+ ## Refresh and current boundaries
224
+
225
+ The TUI starts `crispctl listen --json --read-only` and subscribes to message
226
+ send/receive/update/removal and conversation-state events. The header shows
227
+ `RTM live`, connecting, reconnecting or error. Crispctl handles endpoint discovery,
228
+ Socket.IO authentication and reconnects. The TUI coalesces event bursts into REST
229
+ refreshes, at most once every five seconds, and refreshes after authentication to
230
+ reconcile changes missed during a disconnected interval. This is event-triggered
231
+ REST reconciliation, not a local cache of every event.
232
+
233
+ Profile-based sessions also poll every 60 seconds by default. `--poll 0` disables
234
+ that periodic polling; it does not disable RTM. `--poll N` accepts at least 30
235
+ seconds. Polling failures back off exponentially to 15 minutes. A normal refresh
236
+ makes three REST requests. A quiet TUI polling every 60 seconds uses approximately
237
+ 4,320 requests/day, with additional calls for RTM-triggered refreshes, searches
238
+ and writes. Consider this alongside the website token's documented daily quota.
239
+
240
+ Conversation history is the latest page exposed by crispctl; there is no older
241
+ message pagination, background daemon, push notifications, attachment upload or
242
+ preview, persisted drafts, or MCP in this first version. Assignment and segments
243
+ are available via the CLI bridge. The default tests use demo data, fake
244
+ subprocesses and local sockets; they never read 1Password or contact Crisp.
245
+ Real read-only checks are separate, explicitly invoked commands.
246
+
247
+ ## Verification and binary
248
+
249
+ ```sh
250
+ bun run typecheck
251
+ bun test
252
+ bun run build
253
+ ./dist/crisp-tui-darwin-arm64 --demo # filename follows OS / architecture
254
+ ```
255
+
256
+ The standalone binary embeds Bun and the TUI renderer and needs crispctl on PATH
257
+ or `CRISPCTL_BIN`. The npm package includes crispctl and needs Bun and Node on PATH.
258
+ Tests exercise the UI with OpenTUI's
259
+ headless renderer, send failures, concurrent navigation, draft isolation,
260
+ subprocess argument handling and the Unix control protocol.
261
+
262
+ ## Development data and license
263
+
264
+ Demo contacts, email addresses and test credentials are synthetic. Tests do not
265
+ load 1Password, use a real Crisp profile or contact the Crisp API. Build outputs,
266
+ local environment files, logs and captures are excluded from version control.
267
+ Use synthetic data when sharing screenshots, test fixtures and bug reports.
268
+
269
+ MIT — see [LICENSE](LICENSE). This is an independent community project.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bun
2
+ // Register Solid's client runtime before loading the precompiled application.
3
+ import "@opentui/solid/preload"
4
+ await import("../dist/cli.js")