@arbidocs/cli 0.4.32 → 0.4.33
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/CHANGELOG.md +149 -2
- package/SKILL.md +20 -0
- package/dist/index.js +281 -16
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,159 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## v0.4.
|
|
3
|
+
## v0.4.33
|
|
4
4
|
|
|
5
5
|
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.4.31...HEAD)
|
|
6
6
|
|
|
7
|
+
### 🚀 Enhancements
|
|
8
|
+
|
|
9
|
+
- **automations:** Separate editor and history with concise run results ([ececfaf59](https://github.com/arbicity/ARBI-frontend/commit/ececfaf59))
|
|
10
|
+
- **ui:** Unify automation tabs and sidebar with compact rows and inbox previews ([75b020457](https://github.com/arbicity/ARBI-frontend/commit/75b020457))
|
|
11
|
+
- **home:** Group workspaces under project headings in the table view ([#1391](https://github.com/arbicity/ARBI-frontend/pull/1391))
|
|
12
|
+
- **theme:** Premium Midnight & Cyan tokens - serif display, paper canvas, navy sidebar, ink shadows, tighter radius ([7743678ce](https://github.com/arbicity/ARBI-frontend/commit/7743678ce))
|
|
13
|
+
- **theme:** Raised white cards, eyebrow section labels, cyan active nav marker ([9d5a25f73](https://github.com/arbicity/ARBI-frontend/commit/9d5a25f73))
|
|
14
|
+
- **theme:** Finish premium look; session works without Web Crypto (memory-only) with visible warning ([182b9eb5d](https://github.com/arbicity/ARBI-frontend/commit/182b9eb5d))
|
|
15
|
+
- **theme:** Redesign for lawyers - Office/Fluent familiarity, brand arch on the login hero ([c584e0e4b](https://github.com/arbicity/ARBI-frontend/commit/c584e0e4b))
|
|
16
|
+
- **files:** Wider Title, inline status glyph, visible column resize ticks; square sidebar boxes and toasts ([368b03717](https://github.com/arbicity/ARBI-frontend/commit/368b03717))
|
|
17
|
+
- Mail folders use the Files folder control in the tab header; migrate saved layouts to hide the Status column ([ff205f57e](https://github.com/arbicity/ARBI-frontend/commit/ff205f57e))
|
|
18
|
+
- Automations and Mail behind developer-only Experimental switches, off by default ([a817df1f7](https://github.com/arbicity/ARBI-frontend/commit/a817df1f7))
|
|
19
|
+
- **e2e:** Persona think-aloud evals — simulated users in real browsers, recorded, with fixer hand-off ([1786856ff](https://github.com/arbicity/ARBI-frontend/commit/1786856ff))
|
|
20
|
+
- **personas:** Any agent harness (claude ([ external ](https://github.com/arbicity/ARBI-frontend/commit/ external ))
|
|
21
|
+
- **personas:** Six-persona cast + round 1 results in handoff ([1ce966912](https://github.com/arbicity/ARBI-frontend/commit/1ce966912))
|
|
22
|
+
- **personas:** Run on the Claude subscription, not API keys; label $ as list-price equivalents ([b914b6cb4](https://github.com/arbicity/ARBI-frontend/commit/b914b6cb4))
|
|
23
|
+
- **mail:** Mail header matches Files and Facts - icon + count, shared filter box with dropdown, no refresh ([d58156a3d](https://github.com/arbicity/ARBI-frontend/commit/d58156a3d))
|
|
24
|
+
- **mail:** Header button reads '+ Email' ([d048c885e](https://github.com/arbicity/ARBI-frontend/commit/d048c885e))
|
|
25
|
+
- **mail:** First-run setup in the main screen, ready greeting, refresh on new mail ([3d9ea7bb5](https://github.com/arbicity/ARBI-frontend/commit/3d9ea7bb5))
|
|
26
|
+
- **personas:** --baseline <run> compares a re-run against an earlier round ([f4e49ef22](https://github.com/arbicity/ARBI-frontend/commit/f4e49ef22))
|
|
27
|
+
- **sdk:** Typed mail module and arbi mail CLI (agents can draft) ([ed5366654](https://github.com/arbicity/ARBI-frontend/commit/ed5366654))
|
|
28
|
+
|
|
29
|
+
### 🩹 Fixes
|
|
30
|
+
|
|
31
|
+
- **react:** Show fractional credits and route all credit displays through formatCredits ([bcf12acbe](https://github.com/arbicity/ARBI-frontend/commit/bcf12acbe))
|
|
32
|
+
- **react:** Render italic and list markers when a citation link wraps them ([5fd043cf8](https://github.com/arbicity/ARBI-frontend/commit/5fd043cf8))
|
|
33
|
+
- **react:** Keep a citation link from ending inside an italic source note ([98b77be7f](https://github.com/arbicity/ARBI-frontend/commit/98b77be7f))
|
|
34
|
+
- **automations:** Use standard grids for rules and run history ([94f9da431](https://github.com/arbicity/ARBI-frontend/commit/94f9da431))
|
|
35
|
+
- **ui:** Compact sidebar menus and link run result badges to history ([381d63a42](https://github.com/arbicity/ARBI-frontend/commit/381d63a42))
|
|
36
|
+
- **automations:** Improve trigger badge legibility ([f2e247364](https://github.com/arbicity/ARBI-frontend/commit/f2e247364))
|
|
37
|
+
- **automations:** Simplify trigger labels to text and icon ([64929ee96](https://github.com/arbicity/ARBI-frontend/commit/64929ee96))
|
|
38
|
+
- **automations:** Preserve document rows and validate shared UI and clients ([b6b98bd18](https://github.com/arbicity/ARBI-frontend/commit/b6b98bd18))
|
|
39
|
+
- **notifications:** Open task alerts in their originating workspace ([7c8c05c9b](https://github.com/arbicity/ARBI-frontend/commit/7c8c05c9b))
|
|
40
|
+
- **theme:** Website skyline on the login hero, drop sparkle art and nav accent bar ([0ec8eeb07](https://github.com/arbicity/ARBI-frontend/commit/0ec8eeb07))
|
|
41
|
+
- **theme:** Consistency pass - one rule for fields, cards and chips; drop row accent bar ([3f34159bb](https://github.com/arbicity/ARBI-frontend/commit/3f34159bb))
|
|
42
|
+
- **theme:** Keep the open-document row accent bar in the files grid ([0da8b82f5](https://github.com/arbicity/ARBI-frontend/commit/0da8b82f5))
|
|
43
|
+
- **theme:** Square sidebar nav rows with a straight leading bar on the selected row ([7ca5777c5](https://github.com/arbicity/ARBI-frontend/commit/7ca5777c5))
|
|
44
|
+
- **theme:** Quiet entity labels - plain icon + text at rest, fill only on hover ([eeabe8e57](https://github.com/arbicity/ARBI-frontend/commit/eeabe8e57))
|
|
45
|
+
- Fresh browsers crash opening a workspace (grid migration clobbered gridStates) ([7e114ab08](https://github.com/arbicity/ARBI-frontend/commit/7e114ab08))
|
|
46
|
+
- **personas:** Count fixer commits against the resolved base, not the fix branch's HEAD ([283a8bfbe](https://github.com/arbicity/ARBI-frontend/commit/283a8bfbe))
|
|
47
|
+
- Fresh browsers crash opening a workspace (grid migration clobbered gridStates) ([4acdaaa6d](https://github.com/arbicity/ARBI-frontend/commit/4acdaaa6d))
|
|
48
|
+
- **ci:** Trust Let's Encrypt staging CA for the SDK/CLI integration tests ([103a4b20f](https://github.com/arbicity/ARBI-frontend/commit/103a4b20f))
|
|
49
|
+
- **react:** Text, Word, sheet and HTML files no longer get the PDF icon (persona smoke I01) ([c5d76f775](https://github.com/arbicity/ARBI-frontend/commit/c5d76f775))
|
|
50
|
+
- **mail:** Drop the header's own bottom border (the tab header already draws one) ([e330b2aa8](https://github.com/arbicity/ARBI-frontend/commit/e330b2aa8))
|
|
51
|
+
- **files:** Add menu no longer closes right after a hover-opened click (persona smoke I02) ([55066376b](https://github.com/arbicity/ARBI-frontend/commit/55066376b))
|
|
52
|
+
- **react:** Citation popover re-docks when the chat column narrows (persona smoke I05) ([24a262151](https://github.com/arbicity/ARBI-frontend/commit/24a262151))
|
|
53
|
+
- **viewer:** Show the zoom button on desktop so documents can be enlarged (persona ken-low-vision I01) ([ac4a0588c](https://github.com/arbicity/ARBI-frontend/commit/ac4a0588c))
|
|
54
|
+
- **messages:** Confirm copy of an answer with a toast, and report failures (persona maya-paralegal I05) ([22f4c5d8d](https://github.com/arbicity/ARBI-frontend/commit/22f4c5d8d))
|
|
55
|
+
- **search:** Label Smart Search passages found by meaning, not words (persona lena-legal-ops I02) ([7e5a79d53](https://github.com/arbicity/ARBI-frontend/commit/7e5a79d53))
|
|
56
|
+
- **search:** Explain quotes and relevance threshold in Smart Search results (persona lena-legal-ops I03) ([ed64d06fe](https://github.com/arbicity/ARBI-frontend/commit/ed64d06fe))
|
|
57
|
+
- **upload:** Default visibility to private and say who can see files (persona tom-first-timer I01) ([abfdec1ff](https://github.com/arbicity/ARBI-frontend/commit/abfdec1ff))
|
|
58
|
+
- **citations:** Readable hover passage preview (persona ken-low-vision I02) ([bf64b7a0a](https://github.com/arbicity/ARBI-frontend/commit/bf64b7a0a))
|
|
59
|
+
- **chat:** Offer backend follow-up as a chip instead of pre-filled ghost text (persona smoke I06) ([8859cbb4a](https://github.com/arbicity/ARBI-frontend/commit/8859cbb4a))
|
|
60
|
+
- **facts:** Chronology tables save as dated facts (persona maya-paralegal I07) ([a76dad930](https://github.com/arbicity/ARBI-frontend/commit/a76dad930))
|
|
61
|
+
- **ui:** Citation card closes on any press outside, even one that opens another menu (persona priya-mobile I05) ([4f99f2aff](https://github.com/arbicity/ARBI-frontend/commit/4f99f2aff))
|
|
62
|
+
- **upload:** Keep uploads shared with the workspace by default ([d62538b0c](https://github.com/arbicity/ARBI-frontend/commit/d62538b0c))
|
|
63
|
+
- **ci:** Trust the staging CA inside the deployment container too ([ede715fc2](https://github.com/arbicity/ARBI-frontend/commit/ede715fc2))
|
|
64
|
+
- **conversation:** Show a new chat's question while its answer generates (persona raj-partner I01) ([f05e2d0fd](https://github.com/arbicity/ARBI-frontend/commit/f05e2d0fd))
|
|
65
|
+
- **chat:** Show the passages an uncited answer read as its sources (persona tom-first-timer I03) ([3f1833640](https://github.com/arbicity/ARBI-frontend/commit/3f1833640))
|
|
66
|
+
- **a11y:** Thicker keyboard focus ring on controls (persona ken-low-vision I04) ([f40403d78](https://github.com/arbicity/ARBI-frontend/commit/f40403d78))
|
|
67
|
+
- **viewer:** Name a text file's preview tab Text, not PDF (persona lena-legal-ops I01) ([0195e80f6](https://github.com/arbicity/ARBI-frontend/commit/0195e80f6))
|
|
68
|
+
- **chronology:** State the sort key and how to date ranges (persona maya-paralegal I02) ([9a63cb6cb](https://github.com/arbicity/ARBI-frontend/commit/9a63cb6cb))
|
|
69
|
+
- **facts:** Empty Facts page offers a route to pull dates from documents (persona maya-paralegal I01) ([22124287e](https://github.com/arbicity/ARBI-frontend/commit/22124287e))
|
|
70
|
+
- **facts:** Saved answer fact no longer titled with the chat lead-in (persona maya-paralegal I06) ([3a6a7d701](https://github.com/arbicity/ARBI-frontend/commit/3a6a7d701))
|
|
71
|
+
- **sharing:** Close member suggestion list after adding an email (persona raj-partner I04) ([ed22db368](https://github.com/arbicity/ARBI-frontend/commit/ed22db368))
|
|
72
|
+
- **viewer:** Keep the HTML tab labelled on phones (persona priya-mobile I03) ([e153cac99](https://github.com/arbicity/ARBI-frontend/commit/e153cac99))
|
|
73
|
+
- **documents:** Larger default file tile so titles and thumbnails are readable (persona raj-partner I06) ([c83f28416](https://github.com/arbicity/ARBI-frontend/commit/c83f28416))
|
|
74
|
+
- **react:** Citation menus no longer pop up while scrolling (persona priya-mobile I04) ([c21a7bccc](https://github.com/arbicity/ARBI-frontend/commit/c21a7bccc))
|
|
75
|
+
- **personas:** Mask the demo cursor from agent screenshots; tell personas their OS ([48d6a1938](https://github.com/arbicity/ARBI-frontend/commit/48d6a1938))
|
|
76
|
+
- **workflows:** Name the agent picker 'Who this runs for' (persona tom-first-timer I04) ([666a9d03d](https://github.com/arbicity/ARBI-frontend/commit/666a9d03d))
|
|
77
|
+
- **markdown:** Table cells wrap between words, not mid-word (persona maya-paralegal I03) ([79196bbe9](https://github.com/arbicity/ARBI-frontend/commit/79196bbe9))
|
|
78
|
+
- **personas:** Retry seed documents that fail backend processing instead of testing on them ([ea793d446](https://github.com/arbicity/ARBI-frontend/commit/ea793d446))
|
|
79
|
+
- **chat:** Explain held messages in a task awaiting review (persona priya-mobile I03) ([fc723248c](https://github.com/arbicity/ARBI-frontend/commit/fc723248c))
|
|
80
|
+
- **messages:** Show backticked doc ids as document pills (persona lena-legal-ops I10) ([277501761](https://github.com/arbicity/ARBI-frontend/commit/277501761))
|
|
81
|
+
- **shell:** Bold navy focus ring on the Ask or search field (persona ken-low-vision I04) ([4d78a2480](https://github.com/arbicity/ARBI-frontend/commit/4d78a2480))
|
|
82
|
+
- **workspace:** Explain the common/members-only switch in plain words (persona tom-first-timer I03) ([9e97ceb8f](https://github.com/arbicity/ARBI-frontend/commit/9e97ceb8f))
|
|
83
|
+
- **annotations:** Say the AI has not run after creating an annotation (persona lena-legal-ops I02) ([7ab8cbeef](https://github.com/arbicity/ARBI-frontend/commit/7ab8cbeef))
|
|
84
|
+
- **documents:** Keep a newly created folder listed and selected in Move dialog (persona lena-legal-ops I08) ([3b02f0739](https://github.com/arbicity/ARBI-frontend/commit/3b02f0739))
|
|
85
|
+
- **facts:** Ask the assistant to report the count it actually saved (persona maya-paralegal I03) ([4bbd34e99](https://github.com/arbicity/ARBI-frontend/commit/4bbd34e99))
|
|
86
|
+
- **facts:** Keep the Find-dates prompt in plain words; handoff: round-2 fixes + drag-selection call ([10caf467c](https://github.com/arbicity/ARBI-frontend/commit/10caf467c))
|
|
87
|
+
- **thread:** Keep 'Started Task' / 'Answered' activity in the header, not the chat ([15ca6823b](https://github.com/arbicity/ARBI-frontend/commit/15ca6823b))
|
|
88
|
+
- **auth:** Hero text no longer jumps when switching Login/Register ([1cf652104](https://github.com/arbicity/ARBI-frontend/commit/1cf652104))
|
|
89
|
+
- **connectors:** Show Google (Gmail + Drive) connectors by default ([#1398](https://github.com/arbicity/ARBI-frontend/pull/1398))
|
|
90
|
+
|
|
91
|
+
### 📖 Documentation
|
|
92
|
+
|
|
93
|
+
- **changeset:** Include automation clients and final shared UI ([0dab73760](https://github.com/arbicity/ARBI-frontend/commit/0dab73760))
|
|
94
|
+
- **personas:** Handoff — fix pass, round 2 re-test, UX calls for a human ([fef6b99c1](https://github.com/arbicity/ARBI-frontend/commit/fef6b99c1))
|
|
95
|
+
|
|
7
96
|
### 🏡 Chore
|
|
8
97
|
|
|
9
|
-
-
|
|
98
|
+
- Drop incidental version and lockfile changes ([a1e735dca](https://github.com/arbicity/ARBI-frontend/commit/a1e735dca))
|
|
99
|
+
- **examples:** Let the react-chat example name the deployment domain behind a proxy ([c31409b35](https://github.com/arbicity/ARBI-frontend/commit/c31409b35))
|
|
100
|
+
|
|
101
|
+
### ✅ Tests
|
|
102
|
+
|
|
103
|
+
- **e2e:** Login specs follow the verified-link signup (code field hidden when the link carries a code) ([#1387](https://github.com/arbicity/ARBI-frontend/pull/1387))
|
|
104
|
+
- **e2e:** The saved workflow is found on the Active tab, not below 21 skills ([#1388](https://github.com/arbicity/ARBI-frontend/pull/1388))
|
|
105
|
+
- **e2e:** Goal task demo follows the one Threads list ([#1389](https://github.com/arbicity/ARBI-frontend/pull/1389))
|
|
106
|
+
|
|
107
|
+
### 🎨 Styles
|
|
108
|
+
|
|
109
|
+
- **upload:** Add button is white on cyan when the upload is shared ([72e1e810d](https://github.com/arbicity/ARBI-frontend/commit/72e1e810d))
|
|
110
|
+
- **upload:** Shared Add button uses the brand cyan (--secondary), matching the Shared switch ([f55aa8388](https://github.com/arbicity/ARBI-frontend/commit/f55aa8388))
|
|
111
|
+
- **upload:** Keep the Add button primary whether the upload is shared or private ([7ee51e2b2](https://github.com/arbicity/ARBI-frontend/commit/7ee51e2b2))
|
|
112
|
+
|
|
113
|
+
### 🤖 CI
|
|
114
|
+
|
|
115
|
+
- Give the SDK and CLI integration job 35 minutes ([#1384](https://github.com/arbicity/ARBI-frontend/pull/1384))
|
|
116
|
+
- Route remaining general jobs to disposable CPU runners ([d99a7d5df](https://github.com/arbicity/ARBI-frontend/commit/d99a7d5df))
|
|
117
|
+
- Configure software signing and public endpoints for CPU guests ([79fcac6b0](https://github.com/arbicity/ARBI-frontend/commit/79fcac6b0))
|
|
118
|
+
- Use isolated Redis for full-stack jobs ([484a2d6bc](https://github.com/arbicity/ARBI-frontend/commit/484a2d6bc))
|
|
119
|
+
- Isolate deployment identities across parallel VM jobs ([b4834b72a](https://github.com/arbicity/ARBI-frontend/commit/b4834b72a))
|
|
120
|
+
- Use the deployment CLI domain option ([535c3a208](https://github.com/arbicity/ARBI-frontend/commit/535c3a208))
|
|
121
|
+
- Preserve the remote parser queue endpoint ([d9275d599](https://github.com/arbicity/ARBI-frontend/commit/d9275d599))
|
|
122
|
+
|
|
123
|
+
## v0.4.31
|
|
124
|
+
|
|
125
|
+
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.4.28...HEAD)
|
|
126
|
+
|
|
127
|
+
### 🚀 Enhancements
|
|
128
|
+
|
|
129
|
+
- **mail:** Add native inbox and configurable external accounts ([e71907a43](https://github.com/arbicity/ARBI-frontend/commit/e71907a43))
|
|
130
|
+
- **mail:** Personal viewer and secure message claims with native brand colors ([63bf03f1b](https://github.com/arbicity/ARBI-frontend/commit/63bf03f1b))
|
|
131
|
+
- **notifications:** Present all toasts in the sidebar status area ([17d431d79](https://github.com/arbicity/ARBI-frontend/commit/17d431d79))
|
|
132
|
+
- **ui:** Use shared status styling and dismissible navigation badges ([54df99845](https://github.com/arbicity/ARBI-frontend/commit/54df99845))
|
|
133
|
+
- **sidebar:** Allow generation status badges to be dismissed ([e89234b9e](https://github.com/arbicity/ARBI-frontend/commit/e89234b9e))
|
|
134
|
+
- **mail:** Polish everyday mailbox flows and add basic rich text ([847c888cc](https://github.com/arbicity/ARBI-frontend/commit/847c888cc))
|
|
135
|
+
|
|
136
|
+
### 🩹 Fixes
|
|
137
|
+
|
|
138
|
+
- **mail:** Simplify folder navigation and verify live browser flows ([c92212891](https://github.com/arbicity/ARBI-frontend/commit/c92212891))
|
|
139
|
+
- **mail:** Verified invitation signup and compact Encrypt control ([b33275c72](https://github.com/arbicity/ARBI-frontend/commit/b33275c72))
|
|
140
|
+
- **mail:** Open secure messages automatically and recover per-tab sessions ([88a5765d1](https://github.com/arbicity/ARBI-frontend/commit/88a5765d1))
|
|
141
|
+
- **notifications:** Keep sidebar toast actions below readable message text ([ace7a2633](https://github.com/arbicity/ARBI-frontend/commit/ace7a2633))
|
|
142
|
+
- **ui:** Name conversations Threads and simplify Secure mail control ([ee3bbef12](https://github.com/arbicity/ARBI-frontend/commit/ee3bbef12))
|
|
143
|
+
- **mail:** Use canonical header and personal mailbox settings ([44d8f9db5](https://github.com/arbicity/ARBI-frontend/commit/44d8f9db5))
|
|
144
|
+
- **mail:** Retain header title alongside the message viewer ([7e19e9987](https://github.com/arbicity/ARBI-frontend/commit/7e19e9987))
|
|
145
|
+
- **mail:** Retain caret after links and close saved draft previews ([1f86d5bf5](https://github.com/arbicity/ARBI-frontend/commit/1f86d5bf5))
|
|
146
|
+
- **mail:** Protect the current draft when changing mailbox context ([27c994270](https://github.com/arbicity/ARBI-frontend/commit/27c994270))
|
|
147
|
+
- **mail:** Handle named recipients and prevent accidental sends ([83878c476](https://github.com/arbicity/ARBI-frontend/commit/83878c476))
|
|
148
|
+
- **mail:** Refresh read status after opening a message ([4e561f7e2](https://github.com/arbicity/ARBI-frontend/commit/4e561f7e2))
|
|
149
|
+
|
|
150
|
+
### 🏡 Chore
|
|
151
|
+
|
|
152
|
+
- **mail:** Regenerate client against current backend main ([974ed7dc6](https://github.com/arbicity/ARBI-frontend/commit/974ed7dc6))
|
|
153
|
+
|
|
154
|
+
### ✅ Tests
|
|
155
|
+
|
|
156
|
+
- **mail:** Verify extracted attachment reaches indexed terminal state ([32da203aa](https://github.com/arbicity/ARBI-frontend/commit/32da203aa))
|
|
10
157
|
|
|
11
158
|
## v0.4.28
|
|
12
159
|
|
package/SKILL.md
CHANGED
|
@@ -147,3 +147,23 @@ Footnote-style rendering at the end of the answer is currently not supported —
|
|
|
147
147
|
- **Listen side-effects**: `arbi listen --agent claude` writes `~/.claude/commands/arbi/SKILL.md` and sets a `defaultAgent` in the CLI config. Run it only on a machine you control.
|
|
148
148
|
- **Persistent agents**: `arbi agent create --name <n> -w <ws-id>` creates a child identity the parent can delegate to (printed email+password). Share workspace IDs via `-w` rather than the interactive picker when running non-interactively.
|
|
149
149
|
- **Agent-create errors**: `agent-create` rejects non-`agent-*` emails with a clear message. If you see "No verification record found" the account probably already exists — use `arbi login` instead.
|
|
150
|
+
|
|
151
|
+
## Workspace automations
|
|
152
|
+
|
|
153
|
+
`arbi automation` is an alias for `arbi workflow`. Triggers are run now (no trigger flags), a schedule (`--run-at` or `--rrule`), or a notification (`--event-kind`, optional `--event-filter` JSON). `run <wfl-id>` starts any saved action now. Scheduled document actions require an assistant with standing workspace access (`--agent <agt-id> --auth-mode scheduled_permanent`). Do not silently grant that access.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Daily annotation review of documents currently carrying a label.
|
|
157
|
+
arbi automation create --name 'Daily relevance review' --rrule 'FREQ=DAILY;BYHOUR=9;BYMINUTE=0;BYSECOND=0' --timezone Europe/London --action annotate_documents --labels lbl-needs-review --tags tag-relevance --agent agt-reviewer --auth-mode scheduled_permanent
|
|
158
|
+
# Daily email digest of documents uploaded since the last successful run.
|
|
159
|
+
arbi automation create --name 'Latest documents' --rrule 'FREQ=DAILY;BYHOUR=17;BYMINUTE=0;BYSECOND=0' --timezone Europe/London --action email_documents --latest --agent agt-reviewer --auth-mode scheduled_permanent
|
|
160
|
+
arbi automation run wfl-example --json
|
|
161
|
+
arbi automation runs wfl-example --json
|
|
162
|
+
arbi automation update wfl-example --file changes.json
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Document actions return `execution_id` and do not require a conversation. Execution history includes status, selected documents, a run label, errors and result metadata. Annotation answers/citations remain document annotation fields; emails report delivery metadata. Chat/prompt actions retain their linked conversation history. `--overwrite` regenerates existing annotation answers; the default preserves them. Label selection is resolved at execution time rather than frozen when creating the rule. `arbi task` still refers to local background ask requests, not workspace automations.
|
|
166
|
+
|
|
167
|
+
In the terminal UI: `/automations` lists rules; `/automation view|run|runs|pause|resume|delete <wfl-id>` manages them; `/automation create <JSON>` and `/automation update <wfl-id> <JSON>` accept the same request bodies as the SDK.
|
|
168
|
+
|
|
169
|
+
For latest-document digests, the first run covers the preceding 24 hours; later runs use the previous successful run cutoff. Failed delivery does not advance it. Emails contain document names and authenticated platform links, without attachments.
|
package/dist/index.js
CHANGED
|
@@ -3694,7 +3694,7 @@ function getLatestVersion(skipCache = false) {
|
|
|
3694
3694
|
}
|
|
3695
3695
|
}
|
|
3696
3696
|
function getCurrentVersion() {
|
|
3697
|
-
return "0.4.
|
|
3697
|
+
return "0.4.33";
|
|
3698
3698
|
}
|
|
3699
3699
|
function readChangelog(fromVersion, toVersion) {
|
|
3700
3700
|
try {
|
|
@@ -3747,17 +3747,17 @@ function showChangelog(fromVersion, toVersion) {
|
|
|
3747
3747
|
async function checkForUpdates(autoUpdate) {
|
|
3748
3748
|
try {
|
|
3749
3749
|
const latest = getLatestVersion();
|
|
3750
|
-
if (!latest || latest === "0.4.
|
|
3750
|
+
if (!latest || latest === "0.4.33") return;
|
|
3751
3751
|
if (autoUpdate) {
|
|
3752
3752
|
warn(`
|
|
3753
|
-
Your arbi version is out of date (${"0.4.
|
|
3753
|
+
Your arbi version is out of date (${"0.4.33"} \u2192 ${latest}). Updating...`);
|
|
3754
3754
|
child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
|
|
3755
|
-
showChangelog("0.4.
|
|
3755
|
+
showChangelog("0.4.33", latest);
|
|
3756
3756
|
console.log(`Updated to ${latest}.`);
|
|
3757
3757
|
} else {
|
|
3758
3758
|
warn(
|
|
3759
3759
|
`
|
|
3760
|
-
Your arbi version is out of date (${"0.4.
|
|
3760
|
+
Your arbi version is out of date (${"0.4.33"} \u2192 ${latest}).
|
|
3761
3761
|
Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
|
|
3762
3762
|
);
|
|
3763
3763
|
}
|
|
@@ -3789,10 +3789,10 @@ function markNagShown(latest) {
|
|
|
3789
3789
|
function hintUpdateOnError() {
|
|
3790
3790
|
try {
|
|
3791
3791
|
const cached = readCache();
|
|
3792
|
-
if (!cached || cached.latest === "0.4.
|
|
3792
|
+
if (!cached || cached.latest === "0.4.33") return;
|
|
3793
3793
|
if (!shouldShowNag(cached.latest)) return;
|
|
3794
3794
|
warn(
|
|
3795
|
-
`Your arbi version is out of date (${"0.4.
|
|
3795
|
+
`Your arbi version is out of date (${"0.4.33"} \u2192 ${cached.latest}). Run "arbi update".`
|
|
3796
3796
|
);
|
|
3797
3797
|
markNagShown(cached.latest);
|
|
3798
3798
|
} catch {
|
|
@@ -9583,7 +9583,7 @@ function resolveTaskId(taskIdArg) {
|
|
|
9583
9583
|
}
|
|
9584
9584
|
function statusColor2(s) {
|
|
9585
9585
|
if (s === "completed") return chalk2__default.default.green(s);
|
|
9586
|
-
if (s === "failed") return chalk2__default.default.red(s);
|
|
9586
|
+
if (s === "failed" || s === "cancelled") return chalk2__default.default.red(s);
|
|
9587
9587
|
if (s === "queued" || s === "in_progress") return chalk2__default.default.yellow(s);
|
|
9588
9588
|
return s;
|
|
9589
9589
|
}
|
|
@@ -9633,7 +9633,7 @@ function registerTaskCommand(program2) {
|
|
|
9633
9633
|
const id = resolveTaskId(taskId);
|
|
9634
9634
|
const { accessToken, config } = await resolveWorkspace(opts?.workspace);
|
|
9635
9635
|
const result = await sdk.responses.getResponse({ baseUrl: config.baseUrl, accessToken }, id);
|
|
9636
|
-
if (result.status === "completed" || result.status === "failed") {
|
|
9636
|
+
if (result.status === "completed" || result.status === "failed" || result.status === "cancelled") {
|
|
9637
9637
|
updateTaskStatus(id, result.status);
|
|
9638
9638
|
}
|
|
9639
9639
|
if (opts?.json) {
|
|
@@ -9653,7 +9653,7 @@ function registerTaskCommand(program2) {
|
|
|
9653
9653
|
const id = resolveTaskId(taskId);
|
|
9654
9654
|
const { accessToken, config } = await resolveWorkspace(opts?.workspace);
|
|
9655
9655
|
const result = await sdk.responses.getResponse({ baseUrl: config.baseUrl, accessToken }, id);
|
|
9656
|
-
if (result.status === "completed" || result.status === "failed") {
|
|
9656
|
+
if (result.status === "completed" || result.status === "failed" || result.status === "cancelled") {
|
|
9657
9657
|
updateTaskStatus(id, result.status);
|
|
9658
9658
|
}
|
|
9659
9659
|
if (opts?.json) {
|
|
@@ -9675,8 +9675,12 @@ function registerTaskCommand(program2) {
|
|
|
9675
9675
|
);
|
|
9676
9676
|
}
|
|
9677
9677
|
function registerWorkflowCommand(program2) {
|
|
9678
|
-
const workflow = program2.command("workflow").description("Workflows (/v1/workflow): create, list, resume, pause, run, delete");
|
|
9679
|
-
workflow.command("create").description("Create a workflow with exactly one trigger").requiredOption("--name <name>", "Workflow name (required)").option("--rrule <RRULE>", "Trigger: RFC-5545 recurrence rule").option("--run-at <ISO>", "Trigger: run once at this time (ISO-8601)").option("--event-kind <kind>", "Trigger: a notification type to react to").option("--after <con-id>", "Trigger: when this task (conversation) is done").option("--timezone <tz>", "IANA timezone for --rrule", "UTC").option("--
|
|
9678
|
+
const workflow = program2.command("workflow").alias("automation").description("Workflows (/v1/workflow): create, list, resume, pause, run, delete");
|
|
9679
|
+
workflow.command("create").description("Create a workflow with exactly one trigger").requiredOption("--name <name>", "Workflow name (required)").option("--rrule <RRULE>", "Trigger: RFC-5545 recurrence rule").option("--run-at <ISO>", "Trigger: run once at this time (ISO-8601)").option("--event-kind <kind>", "Trigger: a notification type to react to").option("--after <con-id>", "Trigger: when this task (conversation) is done").option("--timezone <tz>", "IANA timezone for --rrule", "UTC").option("--action <type>", "Action: annotate_documents or email_documents").option("--documents <ids>", "Comma-separated document IDs").option("--labels <ids>", "Select documents matching these label IDs at execution time").option("--latest", "Select documents uploaded since the previous successful run").option("--tags <ids>", "Annotation field IDs for AI review").option("--overwrite", "Regenerate existing annotation answers").option(
|
|
9680
|
+
"--auth-mode <mode>",
|
|
9681
|
+
"scheduled_require_auth or scheduled_permanent",
|
|
9682
|
+
"scheduled_require_auth"
|
|
9683
|
+
).option("--event-filter <json>", "Notification attribute filters as a JSON object").option("--prompt <text>", "Instruction the agent runs").option("--skill <ref>", "Skill reference to run").option("--agent <agt-id>", "Agent to run it as (external id)").option("--workspace <wrk-id>", "Workspace to scope the workflow to (default: the current one)").option("--shared", "Share it with the workspace").option("--json", "Output as JSON").action(
|
|
9680
9684
|
(opts) => runAction(async () => {
|
|
9681
9685
|
const { arbi, workspaceId } = await resolveWorkspace();
|
|
9682
9686
|
const body = {
|
|
@@ -9688,9 +9692,31 @@ function registerWorkflowCommand(program2) {
|
|
|
9688
9692
|
timezone: opts.timezone,
|
|
9689
9693
|
prompt: opts.prompt ?? "",
|
|
9690
9694
|
// Unattended runs ask the owner for access each time unless the workflow is made permanent.
|
|
9691
|
-
auth_mode:
|
|
9695
|
+
auth_mode: opts.authMode,
|
|
9692
9696
|
workspace_ext_id: opts.workspace ?? workspaceId
|
|
9693
9697
|
};
|
|
9698
|
+
if (!["scheduled_require_auth", "scheduled_permanent"].includes(opts.authMode)) {
|
|
9699
|
+
throw new Error(
|
|
9700
|
+
"Invalid --auth-mode: use scheduled_require_auth or scheduled_permanent"
|
|
9701
|
+
);
|
|
9702
|
+
}
|
|
9703
|
+
if (opts.action) {
|
|
9704
|
+
if (!["annotate_documents", "email_documents"].includes(opts.action)) {
|
|
9705
|
+
throw new Error("Invalid --action: use annotate_documents or email_documents");
|
|
9706
|
+
}
|
|
9707
|
+
const ids = (value) => value?.split(",").map((id) => id.trim()).filter(Boolean) ?? [];
|
|
9708
|
+
body.action = {
|
|
9709
|
+
type: opts.action,
|
|
9710
|
+
documents: {
|
|
9711
|
+
doc_ext_ids: ids(opts.documents),
|
|
9712
|
+
label_ext_ids: ids(opts.labels),
|
|
9713
|
+
latest: !!opts.latest
|
|
9714
|
+
},
|
|
9715
|
+
tag_ext_ids: ids(opts.tags),
|
|
9716
|
+
overwrite: !!opts.overwrite
|
|
9717
|
+
};
|
|
9718
|
+
}
|
|
9719
|
+
if (opts.eventFilter) body.event_filter = JSON.parse(opts.eventFilter);
|
|
9694
9720
|
if (opts.rrule) body.rrule = opts.rrule;
|
|
9695
9721
|
if (opts.runAt) body.run_at = opts.runAt;
|
|
9696
9722
|
if (opts.eventKind) body.event_kind = opts.eventKind;
|
|
@@ -9735,7 +9761,7 @@ function registerWorkflowCommand(program2) {
|
|
|
9735
9761
|
})()
|
|
9736
9762
|
);
|
|
9737
9763
|
}
|
|
9738
|
-
workflow.command("run <id>").description("
|
|
9764
|
+
workflow.command("run <id>").description("Start the saved action now (document actions do not create a thread)").option("--json", "Output as JSON").action(
|
|
9739
9765
|
(id, opts) => runAction(async () => {
|
|
9740
9766
|
const { arbi } = await resolveAuth();
|
|
9741
9767
|
const data = await sdk.workflows.runWorkflow(arbi, id);
|
|
@@ -9743,7 +9769,47 @@ function registerWorkflowCommand(program2) {
|
|
|
9743
9769
|
printJson(data);
|
|
9744
9770
|
return;
|
|
9745
9771
|
}
|
|
9746
|
-
|
|
9772
|
+
if (data.error) throw new Error(data.error);
|
|
9773
|
+
success(
|
|
9774
|
+
`${data.started ? "Started" : "Submitted"} automation ${ref(id)}${data.execution_id ? ` \u2014 execution ${data.execution_id}` : ""}${data.conversation_ext_id ? ` \u2014 thread ${ref(data.conversation_ext_id)}` : ""}`
|
|
9775
|
+
);
|
|
9776
|
+
})()
|
|
9777
|
+
);
|
|
9778
|
+
workflow.command("get <id>").description("Read the complete saved automation configuration").action(
|
|
9779
|
+
(id) => runAction(async () => {
|
|
9780
|
+
const { arbi } = await resolveAuth();
|
|
9781
|
+
printJson(await sdk.workflows.getWorkflow(arbi, id));
|
|
9782
|
+
})()
|
|
9783
|
+
);
|
|
9784
|
+
workflow.command("runs <id>").alias("executions").description("Show persisted document-action runs, results and failures").option("--json", "Output as JSON").action(
|
|
9785
|
+
(id, opts) => runAction(async () => {
|
|
9786
|
+
const { arbi } = await resolveAuth();
|
|
9787
|
+
const data = await sdk.workflows.listWorkflowRuns(arbi, id);
|
|
9788
|
+
if (!emitListOrTable(data, opts, "This automation has not run yet.")) return;
|
|
9789
|
+
printTable(
|
|
9790
|
+
[
|
|
9791
|
+
{ header: "RUN", width: 10, value: (r) => String(r.id) },
|
|
9792
|
+
{ header: "STATUS", width: 14, value: (r) => String(r.status) },
|
|
9793
|
+
{ header: "ACTION", width: 22, value: (r) => String(r.action_type) },
|
|
9794
|
+
{
|
|
9795
|
+
header: "DOCUMENTS",
|
|
9796
|
+
width: 12,
|
|
9797
|
+
value: (r) => String(r.document_ext_ids.length)
|
|
9798
|
+
},
|
|
9799
|
+
{ header: "CREATED", width: 26, value: (r) => String(r.created_at) },
|
|
9800
|
+
{ header: "ERROR", width: 40, value: (r) => String(r.error ?? "") }
|
|
9801
|
+
],
|
|
9802
|
+
data
|
|
9803
|
+
);
|
|
9804
|
+
})()
|
|
9805
|
+
);
|
|
9806
|
+
workflow.command("update <id>").description("Update any saved automation settings from a JSON file").requiredOption("--file <path>", "JSON UpdateWorkflowRequest file").option("--json", "Output as JSON").action(
|
|
9807
|
+
(id, opts) => runAction(async () => {
|
|
9808
|
+
const { arbi } = await resolveAuth();
|
|
9809
|
+
const body = JSON.parse(fs5.readFileSync(opts.file, "utf8"));
|
|
9810
|
+
const data = await sdk.workflows.updateWorkflow(arbi, id, body);
|
|
9811
|
+
if (opts.json) printJson(data);
|
|
9812
|
+
else success(`Updated automation ${ref(id)}`);
|
|
9747
9813
|
})()
|
|
9748
9814
|
);
|
|
9749
9815
|
workflow.command("delete <id>").description("Delete a workflow (tasks it already created stay)").action(
|
|
@@ -10045,6 +10111,204 @@ function registerSessionCommand(program2) {
|
|
|
10045
10111
|
await session.commands.find((c) => c.name() === "list").parseAsync([], { from: "user" });
|
|
10046
10112
|
});
|
|
10047
10113
|
}
|
|
10114
|
+
function parseAddress(value) {
|
|
10115
|
+
const match = /^\s*(.*?)\s*<([^<>\s]+)>\s*$/.exec(value);
|
|
10116
|
+
const email = (match ? match[2] : value).trim();
|
|
10117
|
+
if (!/^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/.test(email)) {
|
|
10118
|
+
throw new Error(`Not an email address: ${value}`);
|
|
10119
|
+
}
|
|
10120
|
+
const name = match?.[1].replace(/^"|"$/g, "");
|
|
10121
|
+
return name ? { email, name } : { email };
|
|
10122
|
+
}
|
|
10123
|
+
function collect(value, previous = []) {
|
|
10124
|
+
return [...previous, ...value.split(",").filter((v) => v.trim())];
|
|
10125
|
+
}
|
|
10126
|
+
var readTextFile = (path7) => fs5__default.default.readFileSync(path7 === "-" ? 0 : path7, "utf8");
|
|
10127
|
+
function buildCompose(options) {
|
|
10128
|
+
const read = options.readText ?? readTextFile;
|
|
10129
|
+
if (options.text !== void 0 && options.textFile) {
|
|
10130
|
+
throw new Error("Use either --text or --text-file, not both");
|
|
10131
|
+
}
|
|
10132
|
+
if (options.html !== void 0 && options.htmlFile) {
|
|
10133
|
+
throw new Error("Use either --html or --html-file, not both");
|
|
10134
|
+
}
|
|
10135
|
+
const html = options.html ?? (options.htmlFile ? read(options.htmlFile) : void 0);
|
|
10136
|
+
return {
|
|
10137
|
+
to: (options.to ?? []).map(parseAddress),
|
|
10138
|
+
cc: (options.cc ?? []).map(parseAddress),
|
|
10139
|
+
bcc: (options.bcc ?? []).map(parseAddress),
|
|
10140
|
+
subject: options.subject ?? "",
|
|
10141
|
+
text: options.text ?? (options.textFile ? read(options.textFile) : ""),
|
|
10142
|
+
...html ? { html } : {},
|
|
10143
|
+
secure_delivery: false,
|
|
10144
|
+
attachments: (options.attach ?? []).map((file) => sdk.mailNode.attachmentFromFile(file))
|
|
10145
|
+
};
|
|
10146
|
+
}
|
|
10147
|
+
function addComposeOptions(command) {
|
|
10148
|
+
return command.option("--to <addresses>", "Recipient(s), comma-separated or repeated", collect).option("--cc <addresses>", "Cc recipient(s)", collect).option("--bcc <addresses>", "Bcc recipient(s)", collect).option("-s, --subject <subject>", "Subject").option("--text <text>", "Plain-text body").option("--text-file <path>", "Read the plain-text body from a file (- for stdin)").option("--html <html>", "HTML body (the plain text stays as the fallback)").option("--html-file <path>", "Read the HTML body from a file (- for stdin)").option("-a, --attach <path>", "Attach a file (repeatable)", (v, prev = []) => [
|
|
10149
|
+
...prev,
|
|
10150
|
+
v
|
|
10151
|
+
]).option("--json", "Output as JSON (recommended for scripting / agents)");
|
|
10152
|
+
}
|
|
10153
|
+
function registerMailCommand(program2) {
|
|
10154
|
+
const mail = program2.command("mail").enablePositionalOptions().description("Your ARBI mailbox: read, draft and send (an agent can only draft)");
|
|
10155
|
+
async function connect() {
|
|
10156
|
+
const { loginResult, config } = await resolveAuth();
|
|
10157
|
+
return {
|
|
10158
|
+
fetch: sdk.mail.createMailFetch({
|
|
10159
|
+
baseUrl: config.baseUrl,
|
|
10160
|
+
accessToken: loginResult.accessToken
|
|
10161
|
+
}),
|
|
10162
|
+
login: loginResult,
|
|
10163
|
+
isAgent: Boolean(loginResult.parentExtId)
|
|
10164
|
+
};
|
|
10165
|
+
}
|
|
10166
|
+
async function connectToRead() {
|
|
10167
|
+
const ctx = await connect();
|
|
10168
|
+
if (ctx.isAgent) {
|
|
10169
|
+
error("Agents can only create drafts. Use: arbi mail draft --to <address> ...");
|
|
10170
|
+
process.exit(1);
|
|
10171
|
+
}
|
|
10172
|
+
await sdk.mail.unlockNativeMail(ctx.fetch, {
|
|
10173
|
+
signingPrivateKey: ctx.login.signingPrivateKey,
|
|
10174
|
+
serverSessionKey: ctx.login.serverSessionKey
|
|
10175
|
+
});
|
|
10176
|
+
return ctx;
|
|
10177
|
+
}
|
|
10178
|
+
mail.command("alias <name>").description("Claim your ARBI address, name@<deployment domain> (one per user)").action(
|
|
10179
|
+
(name) => runAction(async () => {
|
|
10180
|
+
const { fetch: fetch2 } = await connect();
|
|
10181
|
+
success(`Your ARBI email is ${await sdk.mail.claimNativeAlias(fetch2, name.toLowerCase())}`);
|
|
10182
|
+
})()
|
|
10183
|
+
);
|
|
10184
|
+
mail.command("folders").description("List folders with unread counts").option("--json", "Output as JSON").action(
|
|
10185
|
+
(opts) => runAction(async () => {
|
|
10186
|
+
const { fetch: fetch2 } = await connectToRead();
|
|
10187
|
+
const folders = await sdk.mail.listFolders(fetch2);
|
|
10188
|
+
if (opts.json) return printJson(folders);
|
|
10189
|
+
printTable(
|
|
10190
|
+
[
|
|
10191
|
+
{ header: "ID", width: 14, value: (f) => f.id },
|
|
10192
|
+
{ header: "NAME", width: 20, value: (f) => f.name },
|
|
10193
|
+
{ header: "UNREAD", width: 8, value: (f) => String(f.unread ?? 0) }
|
|
10194
|
+
],
|
|
10195
|
+
folders
|
|
10196
|
+
);
|
|
10197
|
+
})()
|
|
10198
|
+
);
|
|
10199
|
+
mail.command("list").description("List messages in a folder (default: inbox)").option("-f, --folder <id>", "Folder id: inbox, sent, drafts, archive, trash", "inbox").option("-q, --query <text>", "Filter by subject, sender or recipient").option("-l, --limit <n>", "Messages per page", (v) => parseInt(v, 10), 30).option("--cursor <cursor>", "Continue from a previous page (its next_cursor)").option("--json", "Output as JSON (includes next_cursor)").action(
|
|
10200
|
+
(opts) => runAction(async () => {
|
|
10201
|
+
const { fetch: fetch2 } = await connectToRead();
|
|
10202
|
+
const page = await sdk.mail.listMessages(fetch2, {
|
|
10203
|
+
folderId: opts.folder,
|
|
10204
|
+
query: opts.query,
|
|
10205
|
+
limit: opts.limit,
|
|
10206
|
+
cursor: opts.cursor
|
|
10207
|
+
});
|
|
10208
|
+
if (opts.json) return printJson(page);
|
|
10209
|
+
if (page.messages.length === 0) {
|
|
10210
|
+
process.stderr.write("No messages.\n");
|
|
10211
|
+
return;
|
|
10212
|
+
}
|
|
10213
|
+
const people = (m) => (["sent", "drafts"].includes(opts.folder) ? m.to : m.sender).map((a) => a.name || a.email).join(", ");
|
|
10214
|
+
printTable(
|
|
10215
|
+
[
|
|
10216
|
+
{ header: "ID", width: 38, value: (m) => m.id },
|
|
10217
|
+
{ header: "WHO", width: 24, value: (m) => truncate(people(m), 23) },
|
|
10218
|
+
{
|
|
10219
|
+
header: "SUBJECT",
|
|
10220
|
+
width: 40,
|
|
10221
|
+
value: (m) => truncate(m.subject || "(no subject)", 39)
|
|
10222
|
+
},
|
|
10223
|
+
{
|
|
10224
|
+
header: "FLAGS",
|
|
10225
|
+
width: 14,
|
|
10226
|
+
value: (m) => [
|
|
10227
|
+
m.unread ? "unread" : "",
|
|
10228
|
+
m.attachments.length ? "attach" : "",
|
|
10229
|
+
m.drafted_by ? `by ${m.drafted_by}` : ""
|
|
10230
|
+
].filter(Boolean).join(" ")
|
|
10231
|
+
}
|
|
10232
|
+
],
|
|
10233
|
+
page.messages
|
|
10234
|
+
);
|
|
10235
|
+
if (page.next_cursor) dim(`More: --cursor ${page.next_cursor}`);
|
|
10236
|
+
})()
|
|
10237
|
+
);
|
|
10238
|
+
mail.command("read <id>").description("Read a message, or save one of its attachments with --attachment").option("--attachment <id>", "Save this attachment (id from the attachment list) instead").option("-o, --output <path>", "Where to save the attachment (default: its file name)").option("--json", "Output the full message as JSON").action(
|
|
10239
|
+
(id, opts) => runAction(async () => {
|
|
10240
|
+
const { fetch: fetch2 } = await connectToRead();
|
|
10241
|
+
const message = await sdk.mail.getMessage(fetch2, id);
|
|
10242
|
+
if (opts.attachment !== void 0) {
|
|
10243
|
+
const meta = message.attachments.find((a) => a.id === opts.attachment);
|
|
10244
|
+
if (!meta) throw new Error(`No attachment ${opts.attachment} on this message`);
|
|
10245
|
+
const bytes = await sdk.mail.downloadAttachment(fetch2, id, meta.id);
|
|
10246
|
+
const target = opts.output ?? meta.name;
|
|
10247
|
+
fs5__default.default.writeFileSync(target, bytes);
|
|
10248
|
+
success(`Saved ${target} (${bytes.length} bytes)`);
|
|
10249
|
+
return;
|
|
10250
|
+
}
|
|
10251
|
+
if (opts.json) return printJson(message);
|
|
10252
|
+
const who = (list) => list.map((a) => a.name ? `${a.name} <${a.email}>` : a.email).join(", ");
|
|
10253
|
+
console.log(`From: ${who(message.sender)}`);
|
|
10254
|
+
console.log(`To: ${who(message.to)}`);
|
|
10255
|
+
if (message.cc.length) console.log(`Cc: ${who(message.cc)}`);
|
|
10256
|
+
console.log(`Subject: ${message.subject}`);
|
|
10257
|
+
if (message.received_at) console.log(`Date: ${message.received_at}`);
|
|
10258
|
+
if (message.drafted_by) console.log(`Drafted by: ${message.drafted_by}`);
|
|
10259
|
+
if (message.attachments.length) {
|
|
10260
|
+
console.log(
|
|
10261
|
+
`Attachments: ${message.attachments.map((a) => `${a.name} (id ${a.id}, ${a.size} bytes)`).join("; ")}`
|
|
10262
|
+
);
|
|
10263
|
+
}
|
|
10264
|
+
console.log(`
|
|
10265
|
+
${message.text}`);
|
|
10266
|
+
})()
|
|
10267
|
+
);
|
|
10268
|
+
addComposeOptions(
|
|
10269
|
+
mail.command("draft").description(
|
|
10270
|
+
"Save a draft. Run by an agent, it goes to its owner's Drafts, from their address, for them to review and send"
|
|
10271
|
+
)
|
|
10272
|
+
).action(
|
|
10273
|
+
(opts) => runAction(async () => {
|
|
10274
|
+
const compose = buildCompose(opts);
|
|
10275
|
+
const { fetch: fetch2, isAgent } = await connect();
|
|
10276
|
+
const saved = await sdk.mail.saveDraft(fetch2, compose);
|
|
10277
|
+
if (opts.json) return printJson(saved);
|
|
10278
|
+
success(
|
|
10279
|
+
isAgent ? `Draft ${saved.id} saved to your owner's Drafts. They review it and send.` : `Draft ${saved.id} saved to Drafts.`
|
|
10280
|
+
);
|
|
10281
|
+
})()
|
|
10282
|
+
);
|
|
10283
|
+
addComposeOptions(
|
|
10284
|
+
mail.command("send").description("Send a message from your ARBI address (not available to agents)")
|
|
10285
|
+
).option("--request-id <id>", "Idempotency key: retrying with the same id never sends twice").action(
|
|
10286
|
+
(opts) => runAction(async () => {
|
|
10287
|
+
const compose = buildCompose(opts);
|
|
10288
|
+
if (compose.to?.length === 0 && compose.cc?.length === 0 && compose.bcc?.length === 0) {
|
|
10289
|
+
throw new Error("Add at least one recipient with --to, --cc or --bcc");
|
|
10290
|
+
}
|
|
10291
|
+
const { fetch: fetch2, isAgent } = await connect();
|
|
10292
|
+
if (isAgent) {
|
|
10293
|
+
error("Agents cannot send mail. Save a draft instead: arbi mail draft ...");
|
|
10294
|
+
process.exit(1);
|
|
10295
|
+
}
|
|
10296
|
+
const result = await sdk.mail.sendMessage(fetch2, { ...compose, request_id: opts.requestId });
|
|
10297
|
+
if (opts.json) return printJson(result);
|
|
10298
|
+
success(`Sent (${result.id}).`);
|
|
10299
|
+
})()
|
|
10300
|
+
);
|
|
10301
|
+
mail.arguments("[maybeSubcommand]").action((maybe) => {
|
|
10302
|
+
if (maybe) {
|
|
10303
|
+
suggestSubcommandAndExit(
|
|
10304
|
+
"mail",
|
|
10305
|
+
maybe,
|
|
10306
|
+
mail.commands.map((c) => c.name())
|
|
10307
|
+
);
|
|
10308
|
+
}
|
|
10309
|
+
mail.outputHelp();
|
|
10310
|
+
});
|
|
10311
|
+
}
|
|
10048
10312
|
function registerNotificationsCommand(program2) {
|
|
10049
10313
|
const notif = program2.command("notifications").enablePositionalOptions().description("Non-DM notifications");
|
|
10050
10314
|
notif.command("list").description("List non-DM notifications (workspace invites, contact accepts, \u2026)").option("--unread", "Only show unread notifications").option("--type <comma-list>", "Filter to specific type(s), e.g. workspaceuser_invited").option("-l, --limit <n>", "Cap to N most-recent", (v) => parseInt(v, 10)).option("--json", "Output as JSON (recommended for scripting / agents)").action(
|
|
@@ -10610,7 +10874,7 @@ console.info = (...args) => {
|
|
|
10610
10874
|
_origInfo(...args);
|
|
10611
10875
|
};
|
|
10612
10876
|
var program = new commander.Command();
|
|
10613
|
-
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.4.
|
|
10877
|
+
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.4.33").showHelpAfterError(true).showSuggestionAfterError(true);
|
|
10614
10878
|
registerConfigCommand(program);
|
|
10615
10879
|
registerLoginCommand(program);
|
|
10616
10880
|
registerRegisterCommand(program);
|
|
@@ -10645,6 +10909,7 @@ registerListenCommand(program);
|
|
|
10645
10909
|
registerSessionCommand(program);
|
|
10646
10910
|
registerLocalCommand(program);
|
|
10647
10911
|
registerNotificationsCommand(program);
|
|
10912
|
+
registerMailCommand(program);
|
|
10648
10913
|
registerProjectCommand(program);
|
|
10649
10914
|
registerFilesCommand(program);
|
|
10650
10915
|
registerUsageCommand(program);
|