teams-cli 0.2.0__tar.gz → 0.2.1__tar.gz
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.
- {teams_cli-0.2.0 → teams_cli-0.2.1}/CHANGELOG.md +24 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/Cargo.lock +1 -1
- {teams_cli-0.2.0 → teams_cli-0.2.1}/Cargo.toml +3 -2
- {teams_cli-0.2.0 → teams_cli-0.2.1}/PKG-INFO +44 -11
- {teams_cli-0.2.0 → teams_cli-0.2.1}/README.md +43 -10
- {teams_cli-0.2.0 → teams_cli-0.2.1}/docs/releases.md +39 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/auth.rs +12 -2
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/backend.rs +13 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/cli.rs +23 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/browser.rs +251 -34
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/connection.ps1 +34 -13
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/connection.rs +23 -7
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/helper.rs +3 -1
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/owner.rs +98 -5
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/session.rs +56 -8
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/windows.rs +57 -1
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop.rs +278 -14
- teams_cli-0.2.1/src/desktop_people.js +362 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/error.rs +1 -1
- teams_cli-0.2.1/src/graph.rs +777 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/main.rs +150 -14
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/schema.rs +65 -5
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/tui.rs +211 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/cli.rs +76 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/connection.test.ps1 +50 -14
- teams_cli-0.2.1/tests/js/people.test.mjs +37 -0
- teams_cli-0.2.0/src/graph.rs +0 -376
- {teams_cli-0.2.0 → teams_cli-0.2.1}/.github/workflows/ci.yml +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/.github/workflows/dependencies.yml +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/.github/workflows/release.yml +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/.gitignore +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/.mise.toml +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/LICENSE +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/Makefile +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/build.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/examples/validate_schema.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/pyproject.toml +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/scripts/smoke-release.py +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/config.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/delivery.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/avatars.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/browser_core.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/browser_install.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/cdp.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/install.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop/macos.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop.js +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop_cache.js +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop_core.js +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/desktop_send.js +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/lib.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/output.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/render.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/src/teams_cli_alias.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/connection.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/desktop.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/desktop_scripts.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/desktop_scripts.test.cjs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/fixtures/clispec-v0.3.json +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/package_alias.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/tests/release_smoke.rs +0 -0
- {teams_cli-0.2.0 → teams_cli-0.2.1}/vership.toml +0 -0
|
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.1](https://github.com/rvben/teams-cli/compare/v0.2.0...v0.2.1) - 2026-10-15
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **desktop**: add `teams desktop clear-flags` and a confirmed TUI cleanup that remove remote-debugging flags from the user-wide WebView2 setting while keeping its other arguments.
|
|
15
|
+
- Search people by name or email and create or reuse a one-to-one conversation with `people search` and `chats create --recipient ID --yes`. Opening a conversation never sends a message.
|
|
16
|
+
- Support these operations through the selected personal or work/school desktop account and through Microsoft Graph. Graph search requires a new sign-in to consent to `User.ReadBasic.All`.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Windows desktop helpers use protocol 4. WSL requires the helper from the same CLI release.
|
|
21
|
+
- Ambiguous conversation-creation outcomes remain unconfirmed and are never automatically retried.
|
|
22
|
+
- Personal-account searches put verified live matches first and filter unrelated recent-contact suggestions before applying the result limit.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **desktop**: pass the debugging flags only to the Teams launch on Windows and WSL, so other WebView2 apps such as Outlook no longer open the debugging port.
|
|
27
|
+
- **desktop**: name the application that holds a refused port and report a user-wide debugging setting as the cause.
|
|
28
|
+
- **desktop**: recognise the dedicated browser on Linux and WSL when Chrome rewrites its process title, so setup no longer stops with "did not open its debugging endpoint"; recovery hints now name the browser mode and port in use.
|
|
29
|
+
- **desktop**: keep the work/school browser visible when the organisation's sign-in (such as AD FS with Windows sign-in) does not let Teams stay signed in headless, instead of reporting success and then losing the session; reads now say when Teams was sent back to sign-in, and setup reports whether the browser runs headless or visible.
|
|
30
|
+
- **desktop**: stop a verified dedicated browser that hangs after closing its debugging port, so disconnect and recover no longer leave it running.
|
|
31
|
+
- **desktop**: refuse sign-in success when the browser closes or loses verified ownership during the sign-in check, and verify reads again after observing work-account sign-in.
|
|
32
|
+
- **desktop**: separate email lookup from name search ([b0647f1](https://github.com/rvben/teams-cli/commit/b0647f177c3f4cb5f73e74f42aed11078832e632))
|
|
33
|
+
|
|
10
34
|
## [0.2.0](https://github.com/rvben/teams-cli/compare/v0.1.13...v0.2.0) - 2026-10-14
|
|
11
35
|
|
|
12
36
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "teams-cli"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
rust-version = "1.90"
|
|
6
6
|
description = "A Microsoft Teams CLI and TUI designed equally for humans and agents"
|
|
@@ -56,10 +56,11 @@ windows-sys = { version = "0.61", features = [
|
|
|
56
56
|
"Win32_Security",
|
|
57
57
|
"Win32_Storage_Packaging_Appx",
|
|
58
58
|
"Win32_System_Diagnostics_ToolHelp",
|
|
59
|
+
"Win32_System_Registry",
|
|
59
60
|
"Win32_System_Threading",
|
|
60
61
|
] }
|
|
61
62
|
|
|
62
|
-
[target.'cfg(
|
|
63
|
+
[target.'cfg(unix)'.dependencies]
|
|
63
64
|
libc = "0.2"
|
|
64
65
|
|
|
65
66
|
[dev-dependencies]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: teams-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
License-File: LICENSE
|
|
@@ -81,8 +81,8 @@ for sending, reconnecting, and experimental compatibility limits.
|
|
|
81
81
|
Browser PKCE is the human-friendly default. The browser talks directly to Microsoft, and the CLI never receives or stores your password. Normal sign-in requests these delegated scopes:
|
|
82
82
|
|
|
83
83
|
```text
|
|
84
|
-
openid profile offline_access User.Read
|
|
85
|
-
Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send
|
|
84
|
+
openid profile offline_access User.Read User.ReadBasic.All
|
|
85
|
+
Team.ReadBasic.All Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send
|
|
86
86
|
ChannelMessage.Send
|
|
87
87
|
```
|
|
88
88
|
|
|
@@ -163,6 +163,8 @@ For short-lived automation, `TEAMS_ACCESS_TOKEN` overrides the stored credential
|
|
|
163
163
|
teams list
|
|
164
164
|
teams channels list TEAM_ID
|
|
165
165
|
teams chats list --limit 25
|
|
166
|
+
teams people search "Alex" --limit 20
|
|
167
|
+
teams chats create --recipient PERSON_ID --yes # no message is sent
|
|
166
168
|
teams messages list --chat CHAT_ID
|
|
167
169
|
teams auth login --channel-history # once, with administrator approval
|
|
168
170
|
teams messages list --team TEAM_ID --channel CHANNEL_ID
|
|
@@ -178,7 +180,21 @@ teams config path
|
|
|
178
180
|
teams doctor --offline
|
|
179
181
|
```
|
|
180
182
|
|
|
181
|
-
|
|
183
|
+
Chat, message, team and channel collections expose `--limit` and `--fields`; Graph-native collections use `--cursor`, while joined teams and channels use `--offset` because those endpoints do not accept `$top`. With a terminal they render concise text; when stdout is piped they emit JSON envelopes with continuation metadata and `truncated`.
|
|
184
|
+
|
|
185
|
+
To message someone for the first time, use `people search` to find their verified
|
|
186
|
+
identity in the active profile. Search accepts a name or email prefix of 2–256
|
|
187
|
+
characters and returns at most 50 people; refine the query if `truncated` is true.
|
|
188
|
+
Pass the exact returned ID to `chats create`, then pass the resulting chat ID to
|
|
189
|
+
`messages send`. Creating a conversation reuses an existing one-to-one chat when
|
|
190
|
+
available and sends no message. It requires a writable profile and confirmation
|
|
191
|
+
(`--yes` for automation). Recipient IDs belong to their selected account/backend.
|
|
192
|
+
If creation is unconfirmed, inspect your chats before trying again.
|
|
193
|
+
|
|
194
|
+
Graph recipient search needs delegated `User.ReadBasic.All` consent. Existing
|
|
195
|
+
sign-ins can keep reading chats; run `teams auth login` again to enable directory
|
|
196
|
+
search. Your organization may restrict consent, directory guest access, external
|
|
197
|
+
recipients or chat creation. Personal accounts use the desktop backend.
|
|
182
198
|
|
|
183
199
|
Profiles can block every remote write while keeping reads, sign-in, diagnostics, and the TUI available:
|
|
184
200
|
|
|
@@ -273,7 +289,9 @@ paste; `r` checks delivery, `s` offers an explicit second-copy confirmation, and
|
|
|
273
289
|
`esc` keeps the draft and uncertainty together in memory. Reopening it does not
|
|
274
290
|
unlock ordinary sending. Queued results are labelled queued rather than sent.
|
|
275
291
|
|
|
276
|
-
Desktop
|
|
292
|
+
Desktop supports people search and one-to-one chat creation through the selected
|
|
293
|
+
Teams client's own session. Creation requires a profile with `--allow-send` and
|
|
294
|
+
sends no message. Teams, channels, identity commands, subscriptions,
|
|
277
295
|
replies, mentions, attachments and edits return `unsupported` on desktop. The TUI
|
|
278
296
|
reads chats from the same cache and sends through the same path as `messages send`.
|
|
279
297
|
Existing profiles without a backend field
|
|
@@ -295,15 +313,22 @@ Added auxiliary processes are left alone. If Teams was
|
|
|
295
313
|
restarted independently, quit and relaunch it normally, then disconnect again to
|
|
296
314
|
clear the old record. No command automatically restarts Teams on exit.
|
|
297
315
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
316
|
+
Debugging flags apply only to the managed Teams launch; other apps and the user
|
|
317
|
+
environment are left unchanged. On Windows/WSL, Teams starts through its
|
|
318
|
+
`ms-teams.exe` app execution alias, which must be enabled (Settings > Apps >
|
|
319
|
+
Advanced app settings > App execution aliases). Connect refuses a user-wide
|
|
320
|
+
`WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS` that already has debugging flags: such a
|
|
321
|
+
setting opens the port in every WebView2 app, for example Outlook, and the
|
|
322
|
+
listener is then refused because Teams does not own it. Errors name those apps.
|
|
323
|
+
`teams desktop clear-flags` removes only the debugging flags from that setting
|
|
324
|
+
after confirmation (`--yes` when scripted); quit and reopen the named apps
|
|
325
|
+
afterwards. The TUI offers the same cleanup.
|
|
301
326
|
Windows and WSL share a recovery record and lock. WSL finds PowerShell in its normal
|
|
302
327
|
Windows system directory even when Windows PATH entries are disabled; Windows
|
|
303
328
|
executable interop must still be enabled.
|
|
304
329
|
|
|
305
|
-
If setup is interrupted, run `teams --profile local desktop recover`. It
|
|
306
|
-
|
|
330
|
+
If setup is interrupted, run `teams --profile local desktop recover`. It clears the
|
|
331
|
+
interrupted record (and restores settings left by older versions) without restarting Teams or requiring the Windows helper; it does
|
|
307
332
|
not claim ownership of an unrecorded Teams process. Use `desktop status` to inspect
|
|
308
333
|
the endpoint and saved session. Recovery cannot close an already-running debugging
|
|
309
334
|
endpoint: quit Teams and relaunch it normally if its ownership was not recorded.
|
|
@@ -403,6 +428,13 @@ A sign-in timeout leaves the visible window open; finish signing in and retry
|
|
|
403
428
|
`desktop login`. Interrupting login preserves the browser and its saved profile.
|
|
404
429
|
On WSL2, the visible step needs WSLg or another graphical display.
|
|
405
430
|
|
|
431
|
+
Some organisations sign in through their own identity provider (for example AD FS
|
|
432
|
+
with Windows sign-in) and do not let Teams renew its sign-in in a headless browser.
|
|
433
|
+
For work/school accounts, login therefore watches the headless browser for up to a
|
|
434
|
+
minute; when Teams is sent back to sign-in, the visible browser is reopened and stays
|
|
435
|
+
open instead. Minimise that window, but keep it open. When a headless session is sent
|
|
436
|
+
back to sign-in later, reads report it; run `desktop login` again.
|
|
437
|
+
|
|
406
438
|
Use `--desktop-account personal` for a personal Microsoft account. Sending still
|
|
407
439
|
requires an explicit `init --allow-send` and the existing send confirmation.
|
|
408
440
|
`init --no-login` only saves configuration. `desktop connect --visible` remains
|
|
@@ -413,7 +445,8 @@ The browser uses its own profile under the local data directory at
|
|
|
413
445
|
profile. Different ports use different browser profiles. Disconnect closes this
|
|
414
446
|
browser and keeps its sign-in data. To switch between visible and headless operation,
|
|
415
447
|
disconnect first. `desktop recover` closes a verified managed browser or clears a
|
|
416
|
-
stale record when no listener remains.
|
|
448
|
+
stale record when no listener remains. A verified browser that does not exit after
|
|
449
|
+
closing its debugging port is stopped; unverifiable processes are left untouched.
|
|
417
450
|
|
|
418
451
|
The CLI checks that every listener is loopback-only and belongs to the recorded
|
|
419
452
|
browser process, running as you with the expected executable, debugging port and
|
|
@@ -65,8 +65,8 @@ for sending, reconnecting, and experimental compatibility limits.
|
|
|
65
65
|
Browser PKCE is the human-friendly default. The browser talks directly to Microsoft, and the CLI never receives or stores your password. Normal sign-in requests these delegated scopes:
|
|
66
66
|
|
|
67
67
|
```text
|
|
68
|
-
openid profile offline_access User.Read
|
|
69
|
-
Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send
|
|
68
|
+
openid profile offline_access User.Read User.ReadBasic.All
|
|
69
|
+
Team.ReadBasic.All Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send
|
|
70
70
|
ChannelMessage.Send
|
|
71
71
|
```
|
|
72
72
|
|
|
@@ -147,6 +147,8 @@ For short-lived automation, `TEAMS_ACCESS_TOKEN` overrides the stored credential
|
|
|
147
147
|
teams list
|
|
148
148
|
teams channels list TEAM_ID
|
|
149
149
|
teams chats list --limit 25
|
|
150
|
+
teams people search "Alex" --limit 20
|
|
151
|
+
teams chats create --recipient PERSON_ID --yes # no message is sent
|
|
150
152
|
teams messages list --chat CHAT_ID
|
|
151
153
|
teams auth login --channel-history # once, with administrator approval
|
|
152
154
|
teams messages list --team TEAM_ID --channel CHANNEL_ID
|
|
@@ -162,7 +164,21 @@ teams config path
|
|
|
162
164
|
teams doctor --offline
|
|
163
165
|
```
|
|
164
166
|
|
|
165
|
-
|
|
167
|
+
Chat, message, team and channel collections expose `--limit` and `--fields`; Graph-native collections use `--cursor`, while joined teams and channels use `--offset` because those endpoints do not accept `$top`. With a terminal they render concise text; when stdout is piped they emit JSON envelopes with continuation metadata and `truncated`.
|
|
168
|
+
|
|
169
|
+
To message someone for the first time, use `people search` to find their verified
|
|
170
|
+
identity in the active profile. Search accepts a name or email prefix of 2–256
|
|
171
|
+
characters and returns at most 50 people; refine the query if `truncated` is true.
|
|
172
|
+
Pass the exact returned ID to `chats create`, then pass the resulting chat ID to
|
|
173
|
+
`messages send`. Creating a conversation reuses an existing one-to-one chat when
|
|
174
|
+
available and sends no message. It requires a writable profile and confirmation
|
|
175
|
+
(`--yes` for automation). Recipient IDs belong to their selected account/backend.
|
|
176
|
+
If creation is unconfirmed, inspect your chats before trying again.
|
|
177
|
+
|
|
178
|
+
Graph recipient search needs delegated `User.ReadBasic.All` consent. Existing
|
|
179
|
+
sign-ins can keep reading chats; run `teams auth login` again to enable directory
|
|
180
|
+
search. Your organization may restrict consent, directory guest access, external
|
|
181
|
+
recipients or chat creation. Personal accounts use the desktop backend.
|
|
166
182
|
|
|
167
183
|
Profiles can block every remote write while keeping reads, sign-in, diagnostics, and the TUI available:
|
|
168
184
|
|
|
@@ -257,7 +273,9 @@ paste; `r` checks delivery, `s` offers an explicit second-copy confirmation, and
|
|
|
257
273
|
`esc` keeps the draft and uncertainty together in memory. Reopening it does not
|
|
258
274
|
unlock ordinary sending. Queued results are labelled queued rather than sent.
|
|
259
275
|
|
|
260
|
-
Desktop
|
|
276
|
+
Desktop supports people search and one-to-one chat creation through the selected
|
|
277
|
+
Teams client's own session. Creation requires a profile with `--allow-send` and
|
|
278
|
+
sends no message. Teams, channels, identity commands, subscriptions,
|
|
261
279
|
replies, mentions, attachments and edits return `unsupported` on desktop. The TUI
|
|
262
280
|
reads chats from the same cache and sends through the same path as `messages send`.
|
|
263
281
|
Existing profiles without a backend field
|
|
@@ -279,15 +297,22 @@ Added auxiliary processes are left alone. If Teams was
|
|
|
279
297
|
restarted independently, quit and relaunch it normally, then disconnect again to
|
|
280
298
|
clear the old record. No command automatically restarts Teams on exit.
|
|
281
299
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
300
|
+
Debugging flags apply only to the managed Teams launch; other apps and the user
|
|
301
|
+
environment are left unchanged. On Windows/WSL, Teams starts through its
|
|
302
|
+
`ms-teams.exe` app execution alias, which must be enabled (Settings > Apps >
|
|
303
|
+
Advanced app settings > App execution aliases). Connect refuses a user-wide
|
|
304
|
+
`WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS` that already has debugging flags: such a
|
|
305
|
+
setting opens the port in every WebView2 app, for example Outlook, and the
|
|
306
|
+
listener is then refused because Teams does not own it. Errors name those apps.
|
|
307
|
+
`teams desktop clear-flags` removes only the debugging flags from that setting
|
|
308
|
+
after confirmation (`--yes` when scripted); quit and reopen the named apps
|
|
309
|
+
afterwards. The TUI offers the same cleanup.
|
|
285
310
|
Windows and WSL share a recovery record and lock. WSL finds PowerShell in its normal
|
|
286
311
|
Windows system directory even when Windows PATH entries are disabled; Windows
|
|
287
312
|
executable interop must still be enabled.
|
|
288
313
|
|
|
289
|
-
If setup is interrupted, run `teams --profile local desktop recover`. It
|
|
290
|
-
|
|
314
|
+
If setup is interrupted, run `teams --profile local desktop recover`. It clears the
|
|
315
|
+
interrupted record (and restores settings left by older versions) without restarting Teams or requiring the Windows helper; it does
|
|
291
316
|
not claim ownership of an unrecorded Teams process. Use `desktop status` to inspect
|
|
292
317
|
the endpoint and saved session. Recovery cannot close an already-running debugging
|
|
293
318
|
endpoint: quit Teams and relaunch it normally if its ownership was not recorded.
|
|
@@ -387,6 +412,13 @@ A sign-in timeout leaves the visible window open; finish signing in and retry
|
|
|
387
412
|
`desktop login`. Interrupting login preserves the browser and its saved profile.
|
|
388
413
|
On WSL2, the visible step needs WSLg or another graphical display.
|
|
389
414
|
|
|
415
|
+
Some organisations sign in through their own identity provider (for example AD FS
|
|
416
|
+
with Windows sign-in) and do not let Teams renew its sign-in in a headless browser.
|
|
417
|
+
For work/school accounts, login therefore watches the headless browser for up to a
|
|
418
|
+
minute; when Teams is sent back to sign-in, the visible browser is reopened and stays
|
|
419
|
+
open instead. Minimise that window, but keep it open. When a headless session is sent
|
|
420
|
+
back to sign-in later, reads report it; run `desktop login` again.
|
|
421
|
+
|
|
390
422
|
Use `--desktop-account personal` for a personal Microsoft account. Sending still
|
|
391
423
|
requires an explicit `init --allow-send` and the existing send confirmation.
|
|
392
424
|
`init --no-login` only saves configuration. `desktop connect --visible` remains
|
|
@@ -397,7 +429,8 @@ The browser uses its own profile under the local data directory at
|
|
|
397
429
|
profile. Different ports use different browser profiles. Disconnect closes this
|
|
398
430
|
browser and keeps its sign-in data. To switch between visible and headless operation,
|
|
399
431
|
disconnect first. `desktop recover` closes a verified managed browser or clears a
|
|
400
|
-
stale record when no listener remains.
|
|
432
|
+
stale record when no listener remains. A verified browser that does not exit after
|
|
433
|
+
closing its debugging port is stopped; unverifiable processes are left untouched.
|
|
401
434
|
|
|
402
435
|
The CLI checks that every listener is loopback-only and belongs to the recorded
|
|
403
436
|
browser process, running as you with the expected executable, debugging port and
|
|
@@ -23,6 +23,45 @@ do not bump again. Its tag starts the release workflow.
|
|
|
23
23
|
|
|
24
24
|
Cargo and Python package versions are kept synchronized as one release unit.
|
|
25
25
|
|
|
26
|
+
## Release 0.2.1
|
|
27
|
+
|
|
28
|
+
The version is prepared. Do not bump it again. This release adds `people search`
|
|
29
|
+
and `chats create`; opening a conversation does not send a message. Personal
|
|
30
|
+
desktop search separates exact email lookup from name search and excludes
|
|
31
|
+
off-network invitations. A recipient must resolve to a Teams identity before
|
|
32
|
+
chat creation. Graph directory search requires renewed consent to
|
|
33
|
+
`User.ReadBasic.All`.
|
|
34
|
+
|
|
35
|
+
The Windows helper uses protocol 4 and must match the CLI version and build.
|
|
36
|
+
Validate the Windows helper and WSL client together. Conversation requests and
|
|
37
|
+
sends with an uncertain outcome must never be automatically retried.
|
|
38
|
+
|
|
39
|
+
Teams Companion 0.1.1 downloads CLI 0.2.1. Publish and verify the CLI archives and
|
|
40
|
+
checksums before distributing the extension so its built-in download works.
|
|
41
|
+
Older stable CLIs from 0.1.11 retain reading and replies; New Message offers an
|
|
42
|
+
update when the required commands are missing. Vership prepares the extension's
|
|
43
|
+
version, while its VSIX package check validates the installable artifact.
|
|
44
|
+
Vership does not publish or verify a VS Code Marketplace target.
|
|
45
|
+
|
|
46
|
+
Personal-account search, existing-chat reuse and one-shot send/readback passed
|
|
47
|
+
on Windows and WSL; macOS reads and recipient search also passed. First-contact
|
|
48
|
+
creation and work/school New Message runtime coverage remain unverified. Keep
|
|
49
|
+
these limits separate from the earlier work-account read/send reports.
|
|
50
|
+
|
|
51
|
+
Distinguish existing-chat reuse from first-contact coverage.
|
|
52
|
+
For an approved, discoverable recipient with no existing conversation, resolve
|
|
53
|
+
their exact identity, create the chat once, send one labelled message and verify
|
|
54
|
+
its exact ID and body. A second successful create must return the same chat ID.
|
|
55
|
+
An invite-only search result does not establish a supported recipient and must
|
|
56
|
+
not trigger a message or invitation. Record account/backend/platform limitations
|
|
57
|
+
separately from successful runtime tests.
|
|
58
|
+
|
|
59
|
+
After approved publication workflows finish, verify every CLI target:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
vership verify 0.2.1 --targets tag,release,crates,pypi
|
|
63
|
+
```
|
|
64
|
+
|
|
26
65
|
## Release 0.2.0
|
|
27
66
|
|
|
28
67
|
The managed lightweight browser is an experimental personal-account option on
|
|
@@ -12,9 +12,9 @@ use crate::config::Profile;
|
|
|
12
12
|
use crate::error::AppError;
|
|
13
13
|
use crate::output::Output;
|
|
14
14
|
|
|
15
|
-
pub const BASE_SCOPES: &str = "openid profile offline_access User.Read Team.ReadBasic.All Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send ChannelMessage.Send";
|
|
15
|
+
pub const BASE_SCOPES: &str = "openid profile offline_access User.Read User.ReadBasic.All Team.ReadBasic.All Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send ChannelMessage.Send";
|
|
16
16
|
pub const CHANNEL_HISTORY_SCOPE: &str = "ChannelMessage.Read.All";
|
|
17
|
-
pub const CHANNEL_HISTORY_SCOPES: &str = "openid profile offline_access User.Read Team.ReadBasic.All Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send ChannelMessage.Send ChannelMessage.Read.All";
|
|
17
|
+
pub const CHANNEL_HISTORY_SCOPES: &str = "openid profile offline_access User.Read User.ReadBasic.All Team.ReadBasic.All Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send ChannelMessage.Send ChannelMessage.Read.All";
|
|
18
18
|
const SERVICE: &str = "teams-cli";
|
|
19
19
|
|
|
20
20
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
@@ -397,6 +397,16 @@ mod tests {
|
|
|
397
397
|
#[test]
|
|
398
398
|
fn default_login_is_least_privilege() {
|
|
399
399
|
assert!(!BASE_SCOPES.contains(CHANNEL_HISTORY_SCOPE));
|
|
400
|
+
assert!(
|
|
401
|
+
BASE_SCOPES
|
|
402
|
+
.split_whitespace()
|
|
403
|
+
.any(|scope| scope == "User.ReadBasic.All")
|
|
404
|
+
);
|
|
405
|
+
assert!(
|
|
406
|
+
!BASE_SCOPES
|
|
407
|
+
.split_whitespace()
|
|
408
|
+
.any(|scope| scope == "User.Read.All")
|
|
409
|
+
);
|
|
400
410
|
assert_eq!(scopes(false), BASE_SCOPES);
|
|
401
411
|
}
|
|
402
412
|
|
|
@@ -51,6 +51,19 @@ impl TeamsBackend {
|
|
|
51
51
|
Self::Desktop(client) => client.chats(limit, cursor).await,
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
pub async fn search_people(&self, query: &str, limit: u16) -> Result<Page, AppError> {
|
|
55
|
+
crate::graph::validate_people_query(query, usize::from(limit))?;
|
|
56
|
+
match self {
|
|
57
|
+
Self::Graph(client) => client.search_people(query, usize::from(limit)).await,
|
|
58
|
+
Self::Desktop(client) => client.search_people(query, limit).await,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
pub async fn create_chat(&self, recipient: &str) -> Result<Value, AppError> {
|
|
62
|
+
match self {
|
|
63
|
+
Self::Graph(client) => client.create_chat(recipient).await,
|
|
64
|
+
Self::Desktop(client) => client.create_chat(recipient).await,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
54
67
|
pub async fn messages(
|
|
55
68
|
&self,
|
|
56
69
|
chat: Option<&str>,
|
|
@@ -66,6 +66,11 @@ pub enum Command {
|
|
|
66
66
|
#[command(subcommand)]
|
|
67
67
|
command: ChatsCommand,
|
|
68
68
|
},
|
|
69
|
+
/// Find people to start a conversation with
|
|
70
|
+
People {
|
|
71
|
+
#[command(subcommand)]
|
|
72
|
+
command: PeopleCommand,
|
|
73
|
+
},
|
|
69
74
|
/// Read and send messages
|
|
70
75
|
Messages {
|
|
71
76
|
#[command(subcommand)]
|
|
@@ -187,6 +192,22 @@ pub enum ChannelsCommand {
|
|
|
187
192
|
#[derive(Debug, Subcommand)]
|
|
188
193
|
pub enum ChatsCommand {
|
|
189
194
|
List(PageArgs),
|
|
195
|
+
/// Create or reuse a one-to-one conversation; does not send a message
|
|
196
|
+
Create {
|
|
197
|
+
/// Exact person ID returned by `people search`
|
|
198
|
+
#[arg(long)]
|
|
199
|
+
recipient: String,
|
|
200
|
+
},
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
#[derive(Debug, Subcommand)]
|
|
204
|
+
pub enum PeopleCommand {
|
|
205
|
+
/// Search people by name or email, without sending anything
|
|
206
|
+
Search {
|
|
207
|
+
query: String,
|
|
208
|
+
#[arg(long, default_value_t = 20, value_parser = clap::value_parser!(u16).range(1..=50))]
|
|
209
|
+
limit: u16,
|
|
210
|
+
},
|
|
190
211
|
}
|
|
191
212
|
|
|
192
213
|
#[derive(Debug, Args, Clone)]
|
|
@@ -275,6 +296,8 @@ pub enum DesktopCommand {
|
|
|
275
296
|
Disconnect(DesktopArgs),
|
|
276
297
|
/// Recover interrupted native settings or close a managed browser session
|
|
277
298
|
Recover(DesktopArgs),
|
|
299
|
+
/// Remove remote-debugging flags from the user-wide WebView2 setting (Windows/WSL)
|
|
300
|
+
ClearFlags(DesktopArgs),
|
|
278
301
|
}
|
|
279
302
|
|
|
280
303
|
#[derive(Debug, Args)]
|