deepvista-cli 0.2.0__tar.gz → 0.4.0__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.
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/.github/workflows/ci.yml +26 -0
- deepvista_cli-0.4.0/.release-please-manifest.json +3 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/CHANGELOG.md +20 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/PKG-INFO +39 -1
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/README.md +38 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/auth.py +33 -0
- deepvista_cli-0.4.0/deepvista_cli/commands/schedule.py +169 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/main.py +3 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/output/formatter.py +2 -2
- deepvista_cli-0.4.0/install.ps1 +401 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- deepvista_cli-0.4.0/plugins/claude-code/commands/deepvista.md +115 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/pyproject.toml +1 -1
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/uv.lock +1 -1
- deepvista_cli-0.2.0/.release-please-manifest.json +0 -3
- deepvista_cli-0.2.0/plugins/claude-code/commands/deepvista.md +0 -129
- deepvista_cli-0.2.0/plugins/claude-code/skills/daily-planning/SKILL.md +0 -161
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/.claude-plugin/marketplace.json +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/.github/workflows/publish.yml +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/.github/workflows/release-please.yml +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/.gitignore +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/.pre-commit-config.yaml +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/CLAUDE.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/CONTRIBUTING.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/LICENSE +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/__init__.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/agent_catalog.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/auth/__init__.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/auth/callback_server.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/auth/login.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/auth/tokens.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/client/__init__.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/client/http.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/client/origin.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/__init__.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/agents.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/card.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/chat.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/config.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/lint.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/memory.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/notes.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/session.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/skill.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/upgrade.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/commands/vistabase.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/config.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/output/__init__.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/resources/__init__.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/resources/workflow_host_runtime.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/session_note.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/skill_catalog.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/tui/__init__.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/tui/app.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/deepvista_cli/workflow_doc.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/docs/assets/deepvista-banner.png +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/install.sh +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/README.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/README.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/agents/.gitignore +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/commands/refresh-skills.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/hooks/hooks.json +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/scripts/deepvista-session-end.sh +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/scripts/deepvista-session-start.sh +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/scripts/deepvista-session-turn.sh +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/scripts/deepvista-skill-url.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/scripts/deepvista-sync.sh +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/skills/.gitignore +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/plugins/claude-code/skills/install-deepvista-cli/SKILL.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/release-please-config.json +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/scripts/check_plugin_version.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/SKILL.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/chat.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/lint.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/memory.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/notes.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/openclaw.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/session.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/shared.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/skill-analyze-notes.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/skill-create-from-note.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/skill-import-files.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/skill-research-to-skill.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/skill.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/vistabase-card.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/deepvista/reference/vistabase.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/skills/dv-workflow/SKILL.md +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/tests/__init__.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/tests/test_agent_id_tagging.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/tests/test_session_note_format.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/tests/test_skill_catalog.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/tests/test_skill_commands.py +0 -0
- {deepvista_cli-0.2.0 → deepvista_cli-0.4.0}/uninstall.sh +0 -0
|
@@ -47,3 +47,29 @@ jobs:
|
|
|
47
47
|
env:
|
|
48
48
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
49
49
|
run: gh skill publish --dry-run
|
|
50
|
+
|
|
51
|
+
windows-smoke:
|
|
52
|
+
runs-on: windows-latest
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
- name: Parse install.ps1 (syntax check)
|
|
57
|
+
shell: pwsh
|
|
58
|
+
run: |
|
|
59
|
+
$errors = $null
|
|
60
|
+
[System.Management.Automation.Language.Parser]::ParseFile("$PWD/install.ps1", [ref]$null, [ref]$errors) | Out-Null
|
|
61
|
+
if ($errors.Count -gt 0) {
|
|
62
|
+
$errors | ForEach-Object { Write-Error $_.Message }
|
|
63
|
+
exit 1
|
|
64
|
+
}
|
|
65
|
+
Write-Host "install.ps1 parses cleanly"
|
|
66
|
+
|
|
67
|
+
- uses: astral-sh/setup-uv@v6
|
|
68
|
+
with:
|
|
69
|
+
enable-cache: true
|
|
70
|
+
|
|
71
|
+
- name: Install deepvista CLI from checkout
|
|
72
|
+
run: uv tool install ".[ui]"
|
|
73
|
+
|
|
74
|
+
- name: Smoke test - deepvista --help
|
|
75
|
+
run: deepvista --help
|
|
@@ -37,6 +37,26 @@ users what's new between the version they have installed and the latest release.
|
|
|
37
37
|
adopts a pre-existing server-side row instead of failing when the local
|
|
38
38
|
file is missing.
|
|
39
39
|
|
|
40
|
+
## [0.4.0](https://github.com/DeepVista-AI/deepvista-cli/compare/v0.3.0...v0.4.0) (2026-06-03)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### Features
|
|
44
|
+
|
|
45
|
+
* **DV-941:** add windows install script and trampoline troubleshooting docs ([#156](https://github.com/DeepVista-AI/deepvista-cli/issues/156)) ([eed7335](https://github.com/DeepVista-AI/deepvista-cli/commit/eed7335ffdc1dfcfd84523ed0e77be066b7fe9c3))
|
|
46
|
+
* **DV-942:** print next-step hints after auth login ([#157](https://github.com/DeepVista-AI/deepvista-cli/issues/157)) ([0fca6c9](https://github.com/DeepVista-AI/deepvista-cli/commit/0fca6c9309623ee690c2c9e16870d528b558fd80))
|
|
47
|
+
|
|
48
|
+
## [0.3.0](https://github.com/DeepVista-AI/deepvista-cli/compare/v0.2.0...v0.3.0) (2026-05-31)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
### Features
|
|
52
|
+
|
|
53
|
+
* **DV-871:** move daily-planning to server; add schedule command ([#151](https://github.com/DeepVista-AI/deepvista-cli/issues/151)) ([7c317e7](https://github.com/DeepVista-AI/deepvista-cli/commit/7c317e7d6f71763f6622354b8581ead8b10ef8ea))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
### Bug Fixes
|
|
57
|
+
|
|
58
|
+
* **types:** mark output_error as NoReturn to fix Pyright errors in schedule.py ([#153](https://github.com/DeepVista-AI/deepvista-cli/issues/153)) ([7ac8b12](https://github.com/DeepVista-AI/deepvista-cli/commit/7ac8b12f1b10a94cd6dbe8533b122a2cf8489228))
|
|
59
|
+
|
|
40
60
|
## [0.2.0](https://github.com/DeepVista-AI/deepvista-cli/compare/v0.1.18...v0.2.0) (2026-05-28)
|
|
41
61
|
|
|
42
62
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepvista-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: CLI for DeepVista — chat, notes, skills, and memory from your terminal.
|
|
5
5
|
Project-URL: Homepage, https://deepvista.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/DeepVista-AI/deepvista-cli
|
|
@@ -164,14 +164,52 @@ then `deepvista auth login`).
|
|
|
164
164
|
|
|
165
165
|
### For non-Claude-Code agents (Cursor, OpenCode, OpenClaw, …)
|
|
166
166
|
|
|
167
|
+
**macOS / Linux (bash):**
|
|
168
|
+
|
|
167
169
|
```bash
|
|
168
170
|
curl -sSL https://raw.githubusercontent.com/DeepVista-AI/deepvista-cli/main/install.sh | bash
|
|
169
171
|
```
|
|
170
172
|
|
|
173
|
+
**Windows (PowerShell):**
|
|
174
|
+
|
|
175
|
+
```powershell
|
|
176
|
+
powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/DeepVista-AI/deepvista-cli/main/install.ps1 | iex"
|
|
177
|
+
```
|
|
178
|
+
|
|
171
179
|
The script auto-detects your package manager (`uv`, `pipx`, or `pip`) and copies the consolidated `deepvista` skill into your agent's skill directory (Cursor, OpenCode, OpenClaw, and Claude Code as a fallback). If you upgraded from an earlier release, it also sweeps out the 12 legacy `deepvista-*` skills so you don't end up with both.
|
|
172
180
|
|
|
173
181
|
Prefer GitHub's CLI? `gh skill install DeepVista-AI/deepvista-cli` works too (GitHub CLI ≥ 2.90, preview).
|
|
174
182
|
|
|
183
|
+
#### Windows troubleshooting: `uv trampoline failed to canonicalize script path`
|
|
184
|
+
|
|
185
|
+
On Windows, running `deepvista` may fail with:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
error: uv trampoline failed to canonicalize script path
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
This is a [known uv-on-Windows issue](https://github.com/astral-sh/uv/issues): the launcher (trampoline) that `uv tool install` creates can fail to resolve its own path. It is aggravated by working directories that contain **spaces** (e.g. `C:\Users\you\Claude Folder`) or are inside **OneDrive**-synced folders.
|
|
192
|
+
|
|
193
|
+
Fixes, in order of preference:
|
|
194
|
+
|
|
195
|
+
1. **Update uv and reinstall the launcher:**
|
|
196
|
+
|
|
197
|
+
```powershell
|
|
198
|
+
uv self update
|
|
199
|
+
uv tool install --reinstall "deepvista-cli[ui]"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
2. **Run via `uv tool run` as a fallback** (bypasses the broken trampoline entirely):
|
|
203
|
+
|
|
204
|
+
```powershell
|
|
205
|
+
uv tool run deepvista auth login
|
|
206
|
+
uv tool run deepvista notes +quick "My first note"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
3. **Avoid spaces / OneDrive in your working directory.** Run from a path without spaces, e.g. `C:\dev`, rather than `C:\Users\you\Claude Folder`.
|
|
210
|
+
|
|
211
|
+
The `install.ps1` script performs this check automatically: after installing it runs `deepvista --version`, and if it hits the trampoline error it falls back to `uv tool run deepvista` and prints the guidance above. It also adds `%USERPROFILE%\.local\bin` (uv's tool bin directory) to your user PATH if it isn't already there — restart your shell afterward so new terminals pick it up.
|
|
212
|
+
|
|
175
213
|
### Get Started
|
|
176
214
|
|
|
177
215
|
Open your agent and paste:
|
|
@@ -135,14 +135,52 @@ then `deepvista auth login`).
|
|
|
135
135
|
|
|
136
136
|
### For non-Claude-Code agents (Cursor, OpenCode, OpenClaw, …)
|
|
137
137
|
|
|
138
|
+
**macOS / Linux (bash):**
|
|
139
|
+
|
|
138
140
|
```bash
|
|
139
141
|
curl -sSL https://raw.githubusercontent.com/DeepVista-AI/deepvista-cli/main/install.sh | bash
|
|
140
142
|
```
|
|
141
143
|
|
|
144
|
+
**Windows (PowerShell):**
|
|
145
|
+
|
|
146
|
+
```powershell
|
|
147
|
+
powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/DeepVista-AI/deepvista-cli/main/install.ps1 | iex"
|
|
148
|
+
```
|
|
149
|
+
|
|
142
150
|
The script auto-detects your package manager (`uv`, `pipx`, or `pip`) and copies the consolidated `deepvista` skill into your agent's skill directory (Cursor, OpenCode, OpenClaw, and Claude Code as a fallback). If you upgraded from an earlier release, it also sweeps out the 12 legacy `deepvista-*` skills so you don't end up with both.
|
|
143
151
|
|
|
144
152
|
Prefer GitHub's CLI? `gh skill install DeepVista-AI/deepvista-cli` works too (GitHub CLI ≥ 2.90, preview).
|
|
145
153
|
|
|
154
|
+
#### Windows troubleshooting: `uv trampoline failed to canonicalize script path`
|
|
155
|
+
|
|
156
|
+
On Windows, running `deepvista` may fail with:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
error: uv trampoline failed to canonicalize script path
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
This is a [known uv-on-Windows issue](https://github.com/astral-sh/uv/issues): the launcher (trampoline) that `uv tool install` creates can fail to resolve its own path. It is aggravated by working directories that contain **spaces** (e.g. `C:\Users\you\Claude Folder`) or are inside **OneDrive**-synced folders.
|
|
163
|
+
|
|
164
|
+
Fixes, in order of preference:
|
|
165
|
+
|
|
166
|
+
1. **Update uv and reinstall the launcher:**
|
|
167
|
+
|
|
168
|
+
```powershell
|
|
169
|
+
uv self update
|
|
170
|
+
uv tool install --reinstall "deepvista-cli[ui]"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
2. **Run via `uv tool run` as a fallback** (bypasses the broken trampoline entirely):
|
|
174
|
+
|
|
175
|
+
```powershell
|
|
176
|
+
uv tool run deepvista auth login
|
|
177
|
+
uv tool run deepvista notes +quick "My first note"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
3. **Avoid spaces / OneDrive in your working directory.** Run from a path without spaces, e.g. `C:\dev`, rather than `C:\Users\you\Claude Folder`.
|
|
181
|
+
|
|
182
|
+
The `install.ps1` script performs this check automatically: after installing it runs `deepvista --version`, and if it hits the trampoline error it falls back to `uv tool run deepvista` and prints the guidance above. It also adds `%USERPROFILE%\.local\bin` (uv's tool bin directory) to your user PATH if it isn't already there — restart your shell afterward so new terminals pick it up.
|
|
183
|
+
|
|
146
184
|
### Get Started
|
|
147
185
|
|
|
148
186
|
Open your agent and paste:
|
|
@@ -14,6 +14,7 @@ from deepvista_cli.auth.tokens import (
|
|
|
14
14
|
remove_account,
|
|
15
15
|
switch_active_account,
|
|
16
16
|
)
|
|
17
|
+
from deepvista_cli.client.origin import detect_agent_tool
|
|
17
18
|
from deepvista_cli.config import credentials_path
|
|
18
19
|
from deepvista_cli.output.formatter import format_output, output_error
|
|
19
20
|
|
|
@@ -23,6 +24,37 @@ def auth_group() -> None:
|
|
|
23
24
|
"""Authenticate with DeepVista."""
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
def _print_next_steps() -> None:
|
|
28
|
+
"""Print actionable next-step options after a successful login (DV-942).
|
|
29
|
+
|
|
30
|
+
Written to stderr so the JSON result on stdout stays machine-parseable.
|
|
31
|
+
Suggestions adapt to whoever is driving the CLI (agent vs. terminal).
|
|
32
|
+
"""
|
|
33
|
+
tool, _version = detect_agent_tool()
|
|
34
|
+
if tool == "claude-code":
|
|
35
|
+
steps = [
|
|
36
|
+
"/refresh-skills — sync the DeepVista skill catalog",
|
|
37
|
+
'say "Help me get started with DeepVista."',
|
|
38
|
+
'deepvista notes +quick "<fact>" — capture your first note',
|
|
39
|
+
]
|
|
40
|
+
elif tool == "deepvista-cli": # direct terminal usage
|
|
41
|
+
steps = [
|
|
42
|
+
'deepvista notes +quick "My first note" — capture a note',
|
|
43
|
+
"deepvista skill list — browse your workflow skills",
|
|
44
|
+
"deepvista ui — launch the terminal UI",
|
|
45
|
+
"deepvista chat — talk to your DeepVista agent",
|
|
46
|
+
]
|
|
47
|
+
else: # some other AI agent is driving us
|
|
48
|
+
steps = [
|
|
49
|
+
'deepvista notes +quick "<fact>" — capture a note for the user',
|
|
50
|
+
"deepvista skill list — discover available workflow skills",
|
|
51
|
+
'deepvista vistabase +search "<topic>" — recall the user\'s stored context',
|
|
52
|
+
]
|
|
53
|
+
click.echo("\n What's next? Pick one:", err=True)
|
|
54
|
+
for step in steps:
|
|
55
|
+
click.echo(f" - {step}", err=True)
|
|
56
|
+
|
|
57
|
+
|
|
26
58
|
@auth_group.command("login")
|
|
27
59
|
@click.option("--code", default=None, help="One-time auth code from the browser.")
|
|
28
60
|
@click.option("--dry-run", is_flag=True, default=False, help="Preview what would happen without making any changes.")
|
|
@@ -64,6 +96,7 @@ def auth_login(ctx: click.Context, code: str | None, dry_run: bool) -> None:
|
|
|
64
96
|
}
|
|
65
97
|
format_output(result, ctx.obj.output_format)
|
|
66
98
|
click.echo(f" Logged in as {tokens.email or tokens.user_id}", err=True)
|
|
99
|
+
_print_next_steps()
|
|
67
100
|
|
|
68
101
|
|
|
69
102
|
@auth_group.command("status")
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""deepvista schedule — opt-in recurring runs of the daily-planning skill.
|
|
2
|
+
|
|
3
|
+
Daily planning generation lives on the DeepVista server (the
|
|
4
|
+
``deepvista-daily-planning`` skill). This command lets the user *explicitly*
|
|
5
|
+
activate a recurring server job that generates today's planning note on a cron
|
|
6
|
+
schedule — nothing runs automatically until the user opts in here, which keeps
|
|
7
|
+
token spend under their control.
|
|
8
|
+
|
|
9
|
+
Under the hood each "activation" is a row in the server's ``scheduled_jobs``
|
|
10
|
+
table whose ``prompt`` asks the agent to run the daily-planning skill. The
|
|
11
|
+
heartbeat dispatcher drains due rows and runs the agent.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import click
|
|
17
|
+
|
|
18
|
+
from deepvista_cli.client.http import DeepVistaClient
|
|
19
|
+
from deepvista_cli.output.formatter import format_output, output_error
|
|
20
|
+
|
|
21
|
+
# The server-side workflow skill that generates the planning note.
|
|
22
|
+
DAILY_PLANNING_SKILL = "deepvista-daily-planning"
|
|
23
|
+
# Stable title used to find this job again (activate is idempotent on it).
|
|
24
|
+
JOB_TITLE = "Daily Planning"
|
|
25
|
+
# Cron is evaluated in UTC server-side (no per-user timezone yet — see DV-879).
|
|
26
|
+
DEFAULT_DAILY_CRON = "0 8 * * *"
|
|
27
|
+
DEFAULT_WEEKLY_CRON = "0 8 * * 1"
|
|
28
|
+
|
|
29
|
+
# Columns shown in `--format table`.
|
|
30
|
+
_JOB_COLUMNS = ["id", "title", "cron_schedule", "enabled", "next_run_at", "last_run_at"]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _client(ctx: click.Context) -> DeepVistaClient:
|
|
34
|
+
return ctx.obj._client
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _find_daily_planning_job(ctx: click.Context) -> dict | None:
|
|
38
|
+
"""Return the existing daily-planning job for this user, or None.
|
|
39
|
+
|
|
40
|
+
Matches on the stable ``JOB_TITLE`` so repeated activations re-use the same
|
|
41
|
+
row instead of stacking duplicates.
|
|
42
|
+
"""
|
|
43
|
+
data = _client(ctx).get("/scheduled-jobs")
|
|
44
|
+
for job in data.get("jobs", []):
|
|
45
|
+
if job.get("title") == JOB_TITLE:
|
|
46
|
+
return job
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@click.group("schedule")
|
|
51
|
+
def schedule_group() -> None:
|
|
52
|
+
"""Manage the recurring daily-planning job (opt-in)."""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@schedule_group.command("activate")
|
|
56
|
+
@click.option("--cron", "cron_schedule", default=None, help="5-field cron in UTC (default: daily 08:00 UTC).")
|
|
57
|
+
@click.option("--weekly", is_flag=True, default=False, help="Run weekly (Mon 08:00 UTC) instead of daily.")
|
|
58
|
+
@click.pass_context
|
|
59
|
+
def schedule_activate(ctx: click.Context, cron_schedule: str | None, weekly: bool) -> None:
|
|
60
|
+
"""Activate the recurring daily-planning job.
|
|
61
|
+
|
|
62
|
+
Idempotent: if a daily-planning job already exists it is re-enabled rather
|
|
63
|
+
than duplicated. To change the cron of an existing job, deactivate + delete
|
|
64
|
+
it first, then activate again with a new --cron.
|
|
65
|
+
"""
|
|
66
|
+
cadence = "weekly" if weekly else "daily"
|
|
67
|
+
if cron_schedule is None:
|
|
68
|
+
cron_schedule = DEFAULT_WEEKLY_CRON if weekly else DEFAULT_DAILY_CRON
|
|
69
|
+
|
|
70
|
+
existing = _find_daily_planning_job(ctx)
|
|
71
|
+
if existing is not None:
|
|
72
|
+
if existing.get("enabled"):
|
|
73
|
+
format_output(
|
|
74
|
+
{"status": "already_active", "job": existing},
|
|
75
|
+
ctx.obj.output_format,
|
|
76
|
+
title="Daily planning already active",
|
|
77
|
+
)
|
|
78
|
+
return
|
|
79
|
+
resp = _client(ctx).patch(f"/scheduled-jobs/{existing['id']}", {"enabled": True})
|
|
80
|
+
format_output(
|
|
81
|
+
{"status": "reactivated", "job": resp.get("job", resp)},
|
|
82
|
+
ctx.obj.output_format,
|
|
83
|
+
title="Daily planning reactivated",
|
|
84
|
+
)
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
prompt = (
|
|
88
|
+
f"Run the {DAILY_PLANNING_SKILL} skill to generate today's daily "
|
|
89
|
+
f"planning note (cadence: {cadence}). List the workflow Skills that "
|
|
90
|
+
f"should run today as context-card chips in the note's Planning section."
|
|
91
|
+
)
|
|
92
|
+
resp = _client(ctx).post(
|
|
93
|
+
"/scheduled-jobs",
|
|
94
|
+
{
|
|
95
|
+
"prompt": prompt,
|
|
96
|
+
"cron_schedule": cron_schedule,
|
|
97
|
+
"title": JOB_TITLE,
|
|
98
|
+
"enabled": True,
|
|
99
|
+
},
|
|
100
|
+
)
|
|
101
|
+
if not resp.get("success"):
|
|
102
|
+
output_error(1, "Failed to activate daily planning", resp.get("error", ""))
|
|
103
|
+
format_output(
|
|
104
|
+
{"status": "activated", "cadence": cadence, "job": resp.get("job", resp)},
|
|
105
|
+
ctx.obj.output_format,
|
|
106
|
+
title="Daily planning activated",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@schedule_group.command("deactivate")
|
|
111
|
+
@click.pass_context
|
|
112
|
+
def schedule_deactivate(ctx: click.Context) -> None:
|
|
113
|
+
"""Disable the daily-planning job (keeps the row so it can be re-activated)."""
|
|
114
|
+
existing = _find_daily_planning_job(ctx)
|
|
115
|
+
if existing is None:
|
|
116
|
+
output_error(1, "No daily-planning job found", "Run: deepvista schedule activate")
|
|
117
|
+
if not existing.get("enabled"):
|
|
118
|
+
format_output(
|
|
119
|
+
{"status": "already_inactive", "job": existing},
|
|
120
|
+
ctx.obj.output_format,
|
|
121
|
+
title="Daily planning already inactive",
|
|
122
|
+
)
|
|
123
|
+
return
|
|
124
|
+
resp = _client(ctx).patch(f"/scheduled-jobs/{existing['id']}", {"enabled": False})
|
|
125
|
+
format_output(
|
|
126
|
+
{"status": "deactivated", "job": resp.get("job", resp)},
|
|
127
|
+
ctx.obj.output_format,
|
|
128
|
+
title="Daily planning deactivated",
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@schedule_group.command("list")
|
|
133
|
+
@click.pass_context
|
|
134
|
+
def schedule_list(ctx: click.Context) -> None:
|
|
135
|
+
"""List the caller's scheduled jobs (read-only)."""
|
|
136
|
+
data = _client(ctx).get("/scheduled-jobs")
|
|
137
|
+
jobs = data.get("jobs", [])
|
|
138
|
+
format_output(
|
|
139
|
+
{"jobs": jobs, "count": len(jobs)},
|
|
140
|
+
ctx.obj.output_format,
|
|
141
|
+
columns=_JOB_COLUMNS,
|
|
142
|
+
title="Scheduled Jobs",
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@schedule_group.command("delete")
|
|
147
|
+
@click.argument("job_id", required=False)
|
|
148
|
+
@click.pass_context
|
|
149
|
+
def schedule_delete(ctx: click.Context, job_id: str | None) -> None:
|
|
150
|
+
"""Delete a scheduled job permanently.
|
|
151
|
+
|
|
152
|
+
With no JOB_ID, deletes the daily-planning job. Use this (then ``activate``)
|
|
153
|
+
to change a job's cron, which PATCH can't edit. Pass ``--dry-run`` on the
|
|
154
|
+
root command to preview without deleting.
|
|
155
|
+
"""
|
|
156
|
+
if job_id is None:
|
|
157
|
+
existing = _find_daily_planning_job(ctx)
|
|
158
|
+
if existing is None:
|
|
159
|
+
output_error(1, "No daily-planning job found", "Pass a JOB_ID, or run: deepvista schedule list")
|
|
160
|
+
job_id = existing["id"]
|
|
161
|
+
|
|
162
|
+
resp = _client(ctx).delete(f"/scheduled-jobs/{job_id}")
|
|
163
|
+
if not resp.get("success"):
|
|
164
|
+
output_error(1, "Failed to delete scheduled job", resp.get("error", ""))
|
|
165
|
+
format_output(
|
|
166
|
+
{"status": "deleted", "job_id": job_id},
|
|
167
|
+
ctx.obj.output_format,
|
|
168
|
+
title="Scheduled job deleted",
|
|
169
|
+
)
|
|
@@ -31,6 +31,7 @@ from deepvista_cli.commands.config import config_group
|
|
|
31
31
|
from deepvista_cli.commands.lint import lint_command
|
|
32
32
|
from deepvista_cli.commands.memory import vistabase_group
|
|
33
33
|
from deepvista_cli.commands.notes import notes_group
|
|
34
|
+
from deepvista_cli.commands.schedule import schedule_group
|
|
34
35
|
from deepvista_cli.commands.session import session_group
|
|
35
36
|
from deepvista_cli.commands.skill import skill_group
|
|
36
37
|
from deepvista_cli.commands.upgrade import upgrade_command
|
|
@@ -87,6 +88,8 @@ for _name, _cmd in card_group.commands.items():
|
|
|
87
88
|
cli.add_command(vistabase_group, name="memory")
|
|
88
89
|
# Agent orchestration
|
|
89
90
|
cli.add_command(agents_group)
|
|
91
|
+
# Opt-in recurring daily-planning job
|
|
92
|
+
cli.add_command(schedule_group)
|
|
90
93
|
# Agent session transcripts (DV-742) — `init` / `tick` / `finalize`
|
|
91
94
|
cli.add_command(session_group)
|
|
92
95
|
# Supporting commands
|
|
@@ -8,7 +8,7 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
10
|
import sys
|
|
11
|
-
from typing import Any
|
|
11
|
+
from typing import Any, NoReturn
|
|
12
12
|
|
|
13
13
|
import click
|
|
14
14
|
|
|
@@ -170,7 +170,7 @@ def output_table(data: Any, columns: list[str] | None = None, title: str | None
|
|
|
170
170
|
output_json(data)
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
def output_error(code: int, message: str, detail: str = "") ->
|
|
173
|
+
def output_error(code: int, message: str, detail: str = "") -> NoReturn:
|
|
174
174
|
"""Write structured error to stderr and exit."""
|
|
175
175
|
err = {"error": {"code": code, "message": message}}
|
|
176
176
|
if detail:
|