@opvs-ai/cli 0.1.4 → 0.2.1
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/README.md +73 -2
- package/dist/commands/auth.js +43 -26
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/boards.js +9 -6
- package/dist/commands/boards.js.map +1 -1
- package/dist/commands/comments.js +6 -4
- package/dist/commands/comments.js.map +1 -1
- package/dist/commands/config.js +99 -28
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/docs.js +14 -9
- package/dist/commands/docs.js.map +1 -1
- package/dist/commands/session.js +4 -5
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/tasks.js +11 -7
- package/dist/commands/tasks.js.map +1 -1
- package/dist/commands/workspace.d.ts +5 -0
- package/dist/commands/workspace.js +65 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +3 -3
- package/dist/lib/api.js +6 -6
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/config.d.ts +52 -3
- package/dist/lib/config.js +208 -15
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/fingerprint.js +6 -1
- package/dist/lib/fingerprint.js.map +1 -1
- package/dist/types.d.ts +22 -2
- package/dist/types.js +7 -2
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,68 @@ Admin clicks: [Approve] button in email
|
|
|
48
48
|
|
|
49
49
|
No passwords, no copy-pasting tokens. The human stays in control.
|
|
50
50
|
|
|
51
|
+
## Multi-Workspace Support
|
|
52
|
+
|
|
53
|
+
The CLI supports multiple workspaces (brands) with kubectl-style context switching. Each workspace has its own token, brand, and API URL.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Authenticate to multiple workspaces
|
|
57
|
+
opvs auth request -w my-company -e admin@mycompany.com
|
|
58
|
+
opvs auth request -w other-brand -e admin@other.com
|
|
59
|
+
|
|
60
|
+
# List all workspaces (* = current)
|
|
61
|
+
opvs workspace list
|
|
62
|
+
|
|
63
|
+
# Switch workspace
|
|
64
|
+
opvs workspace use other-brand
|
|
65
|
+
|
|
66
|
+
# Run a command against a specific workspace (without switching)
|
|
67
|
+
opvs -w my-company boards list
|
|
68
|
+
|
|
69
|
+
# Show current workspace details
|
|
70
|
+
opvs workspace current
|
|
71
|
+
|
|
72
|
+
# Remove a workspace
|
|
73
|
+
opvs workspace remove old-brand
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Config File
|
|
77
|
+
|
|
78
|
+
All workspaces are stored in `~/.opvs/config.json`:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"version": 2,
|
|
83
|
+
"current_workspace": "my-company",
|
|
84
|
+
"format": "yaml",
|
|
85
|
+
"workspaces": {
|
|
86
|
+
"my-company": {
|
|
87
|
+
"api_url": "https://app.opvs.ai",
|
|
88
|
+
"token": "pat_...",
|
|
89
|
+
"brand_id": 1,
|
|
90
|
+
"brand_name": "My Company"
|
|
91
|
+
},
|
|
92
|
+
"other-brand": {
|
|
93
|
+
"api_url": "https://app.opvs.ai",
|
|
94
|
+
"token": "pat_...",
|
|
95
|
+
"brand_id": 11,
|
|
96
|
+
"brand_name": "Other Brand"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Environment Variables
|
|
103
|
+
|
|
104
|
+
Override workspace selection and settings without modifying config:
|
|
105
|
+
|
|
106
|
+
| Variable | Description |
|
|
107
|
+
|----------|-------------|
|
|
108
|
+
| `OPVS_WORKSPACE` | Workspace slug to use |
|
|
109
|
+
| `OPVS_API_URL` | Override API base URL |
|
|
110
|
+
| `OPVS_TOKEN` | Override PAT token (useful in CI/CD) |
|
|
111
|
+
| `OPVS_FORMAT` | Override output format |
|
|
112
|
+
|
|
51
113
|
## Commands
|
|
52
114
|
|
|
53
115
|
### Boards
|
|
@@ -67,7 +129,6 @@ opvs tasks get <id> # Task details
|
|
|
67
129
|
opvs tasks create --board <id> -t "Title" # Create task
|
|
68
130
|
opvs tasks update <id> --status review # Update status
|
|
69
131
|
opvs tasks update <id> --result-file out.md # Attach result from file
|
|
70
|
-
opvs tasks delete <id> # Delete task
|
|
71
132
|
```
|
|
72
133
|
|
|
73
134
|
### Comments
|
|
@@ -100,7 +161,8 @@ opvs session get --board <id> # Board overview
|
|
|
100
161
|
```bash
|
|
101
162
|
opvs config set api_url https://app.opvs.ai
|
|
102
163
|
opvs config set format yaml # yaml | json | md
|
|
103
|
-
opvs config get # Show current config
|
|
164
|
+
opvs config get # Show current workspace config
|
|
165
|
+
opvs config get --all # Show all workspaces
|
|
104
166
|
opvs config path # Config file location
|
|
105
167
|
opvs init # Print CLAUDE.md snippet
|
|
106
168
|
```
|
|
@@ -114,6 +176,15 @@ opvs auth revoke # Revoke token
|
|
|
114
176
|
opvs auth list # List agent tokens (admin)
|
|
115
177
|
```
|
|
116
178
|
|
|
179
|
+
### Workspace
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
opvs workspace list # List all workspaces
|
|
183
|
+
opvs workspace use <slug> # Switch current workspace
|
|
184
|
+
opvs workspace current # Show current workspace details
|
|
185
|
+
opvs workspace remove <slug> # Remove a saved workspace
|
|
186
|
+
```
|
|
187
|
+
|
|
117
188
|
## YAML Output
|
|
118
189
|
|
|
119
190
|
All read commands return YAML by default for token-efficient AI agent consumption (40-76% fewer tokens than JSON). Set format with:
|
package/dist/commands/auth.js
CHANGED
|
@@ -1,32 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* opvs auth — AI-native token provisioning + management
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { getEffectiveConfig, saveWorkspace, setCurrentWorkspace, loadRawConfig, } from "../lib/config.js";
|
|
5
5
|
import { apiUnauthPost, createClient } from "../lib/api.js";
|
|
6
6
|
import { buildFingerprint } from "../lib/fingerprint.js";
|
|
7
7
|
import { pollForApproval } from "../lib/auth-poll.js";
|
|
8
8
|
import { printJson } from "../lib/format.js";
|
|
9
|
+
import { DEFAULT_WORKSPACE } from "../types.js";
|
|
9
10
|
export function registerAuthCommands(program) {
|
|
10
11
|
const auth = program.command("auth").description("Token authentication");
|
|
11
12
|
auth
|
|
12
13
|
.command("request")
|
|
13
14
|
.description("Request a PAT token (sends approval email to workspace owner)")
|
|
14
|
-
.requiredOption("-w, --workspace <slug>", "Workspace slug")
|
|
15
15
|
.requiredOption("-e, --email <email>", "Owner email (admin who approves)")
|
|
16
16
|
.option("-p, --project <name>", "Project name (shown in approval email)")
|
|
17
17
|
.option("-s, --scopes <scopes>", "Comma-separated scopes", "board:read,board:write")
|
|
18
18
|
.option("-t, --ttl <hours>", "Token TTL in hours", "72")
|
|
19
19
|
.option("--api-url <url>", "API base URL (overrides config)")
|
|
20
20
|
.action(async (opts) => {
|
|
21
|
-
|
|
22
|
-
const
|
|
21
|
+
// Workspace comes from global -w flag
|
|
22
|
+
const wsSlug = program.opts().workspace;
|
|
23
|
+
if (!wsSlug) {
|
|
24
|
+
console.error("Workspace required. Use: opvs -w <slug> auth request -e <email>");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
// Resolve API URL: explicit flag > existing workspace > default
|
|
28
|
+
const config = loadRawConfig();
|
|
29
|
+
const existing = config.workspaces[wsSlug];
|
|
30
|
+
const baseUrl = opts.apiUrl || existing?.api_url || DEFAULT_WORKSPACE.api_url;
|
|
23
31
|
const fingerprint = buildFingerprint();
|
|
24
32
|
const scopes = opts.scopes.split(",").map((s) => s.trim());
|
|
25
|
-
console.log(`Requesting access to workspace "${
|
|
33
|
+
console.log(`Requesting access to workspace "${wsSlug}"...`);
|
|
26
34
|
console.log(`Approval email will be sent to ${opts.email}`);
|
|
27
35
|
try {
|
|
28
36
|
const res = await apiUnauthPost(baseUrl, "/api/v1/auth/pat/request", {
|
|
29
|
-
workspace_slug:
|
|
37
|
+
workspace_slug: wsSlug,
|
|
30
38
|
owner_email: opts.email,
|
|
31
39
|
project_name: opts.project || null,
|
|
32
40
|
requested_scopes: scopes,
|
|
@@ -40,14 +48,15 @@ export function registerAuthCommands(program) {
|
|
|
40
48
|
// Start polling
|
|
41
49
|
const result = await pollForApproval(baseUrl, request_id, poll_token);
|
|
42
50
|
if (result.status === "active" && result.token) {
|
|
43
|
-
// Save token
|
|
44
|
-
|
|
51
|
+
// Save token to workspace-scoped config
|
|
52
|
+
saveWorkspace(wsSlug, {
|
|
45
53
|
api_url: baseUrl,
|
|
46
54
|
token: result.token,
|
|
47
55
|
brand_id: result.brand_id ?? null,
|
|
48
56
|
brand_name: result.brand_name ?? "",
|
|
49
57
|
});
|
|
50
|
-
|
|
58
|
+
setCurrentWorkspace(wsSlug);
|
|
59
|
+
console.log(`\nAuthenticated! Token saved to workspace "${wsSlug}".`);
|
|
51
60
|
console.log(`Brand: ${result.brand_name} (ID: ${result.brand_id})`);
|
|
52
61
|
console.log(`Scopes: ${result.scopes?.join(", ")}`);
|
|
53
62
|
}
|
|
@@ -74,13 +83,14 @@ export function registerAuthCommands(program) {
|
|
|
74
83
|
.command("status")
|
|
75
84
|
.description("Show current authentication status")
|
|
76
85
|
.action(async () => {
|
|
77
|
-
const
|
|
78
|
-
if (!cfg.token) {
|
|
79
|
-
console.log("Not authenticated. Run `opvs auth request` to get a token.");
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
86
|
+
const wsSlug = program.opts().workspace;
|
|
82
87
|
try {
|
|
83
|
-
const
|
|
88
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
89
|
+
if (!cfg.token) {
|
|
90
|
+
console.log("Not authenticated. Run `opvs auth request` to get a token.");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const client = createClient(wsSlug);
|
|
84
94
|
const res = await client.get("/api/v1/auth/me");
|
|
85
95
|
const data = await res.json();
|
|
86
96
|
printJson(data);
|
|
@@ -98,15 +108,16 @@ export function registerAuthCommands(program) {
|
|
|
98
108
|
});
|
|
99
109
|
auth
|
|
100
110
|
.command("revoke")
|
|
101
|
-
.description("Revoke the current
|
|
111
|
+
.description("Revoke the token for the current workspace")
|
|
102
112
|
.action(async () => {
|
|
103
|
-
const
|
|
104
|
-
if (!cfg.token) {
|
|
105
|
-
console.log("Not authenticated — nothing to revoke.");
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
113
|
+
const wsSlug = program.opts().workspace;
|
|
108
114
|
try {
|
|
109
|
-
const
|
|
115
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
116
|
+
if (!cfg.token) {
|
|
117
|
+
console.log("Not authenticated — nothing to revoke.");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const client = createClient(wsSlug);
|
|
110
121
|
// Find the token ID by matching prefix from the tokens list
|
|
111
122
|
const prefix = cfg.token.slice(0, 16);
|
|
112
123
|
const listRes = await client.get("/api/v1/tokens");
|
|
@@ -119,13 +130,18 @@ export function registerAuthCommands(program) {
|
|
|
119
130
|
else {
|
|
120
131
|
console.log("Token not found on server (may already be revoked).");
|
|
121
132
|
}
|
|
122
|
-
|
|
123
|
-
|
|
133
|
+
// Clear token in workspace config
|
|
134
|
+
saveWorkspace(cfg.workspace_slug, { token: "", brand_id: null, brand_name: "" });
|
|
135
|
+
console.log(`Local config cleared for workspace "${cfg.workspace_slug}".`);
|
|
124
136
|
}
|
|
125
137
|
catch (err) {
|
|
126
138
|
const e = err;
|
|
127
139
|
// Clear local config even if server revoke fails
|
|
128
|
-
|
|
140
|
+
try {
|
|
141
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
142
|
+
saveWorkspace(cfg.workspace_slug, { token: "", brand_id: null, brand_name: "" });
|
|
143
|
+
}
|
|
144
|
+
catch { /* ignore */ }
|
|
129
145
|
console.error(`Server revoke failed (${e.detail}), but local config cleared.`);
|
|
130
146
|
}
|
|
131
147
|
});
|
|
@@ -133,8 +149,9 @@ export function registerAuthCommands(program) {
|
|
|
133
149
|
.command("list")
|
|
134
150
|
.description("List all agent tokens for the workspace (admin)")
|
|
135
151
|
.action(async () => {
|
|
152
|
+
const wsSlug = program.opts().workspace;
|
|
136
153
|
try {
|
|
137
|
-
const client = createClient();
|
|
154
|
+
const client = createClient(wsSlug);
|
|
138
155
|
const res = await client.get("/api/v1/auth/pat/agents");
|
|
139
156
|
const data = await res.json();
|
|
140
157
|
printJson(data);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/boards.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* opvs boards — board CRUD
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { getEffectiveConfig } from "../lib/config.js";
|
|
5
5
|
import { createClient } from "../lib/api.js";
|
|
6
6
|
import { buildUrl, printResponse, printJson } from "../lib/format.js";
|
|
7
7
|
export function registerBoardCommands(program) {
|
|
@@ -11,9 +11,10 @@ export function registerBoardCommands(program) {
|
|
|
11
11
|
.description("List boards")
|
|
12
12
|
.option("--status <status>", "Filter by status")
|
|
13
13
|
.action(async (opts) => {
|
|
14
|
-
const
|
|
14
|
+
const wsSlug = program.opts().workspace;
|
|
15
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
15
16
|
try {
|
|
16
|
-
const client = createClient();
|
|
17
|
+
const client = createClient(wsSlug);
|
|
17
18
|
const params = {};
|
|
18
19
|
if (opts.status)
|
|
19
20
|
params.status = opts.status;
|
|
@@ -31,9 +32,10 @@ export function registerBoardCommands(program) {
|
|
|
31
32
|
.command("get <id>")
|
|
32
33
|
.description("Get board details")
|
|
33
34
|
.action(async (id) => {
|
|
34
|
-
const
|
|
35
|
+
const wsSlug = program.opts().workspace;
|
|
36
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
35
37
|
try {
|
|
36
|
-
const client = createClient();
|
|
38
|
+
const client = createClient(wsSlug);
|
|
37
39
|
const url = buildUrl(`/api/v1/board/boards/${id}`, undefined, cfg.format);
|
|
38
40
|
const res = await client.get(url);
|
|
39
41
|
await printResponse(res);
|
|
@@ -50,8 +52,9 @@ export function registerBoardCommands(program) {
|
|
|
50
52
|
.requiredOption("-n, --name <name>", "Board name")
|
|
51
53
|
.option("-d, --description <desc>", "Board description")
|
|
52
54
|
.action(async (opts) => {
|
|
55
|
+
const wsSlug = program.opts().workspace;
|
|
53
56
|
try {
|
|
54
|
-
const client = createClient();
|
|
57
|
+
const client = createClient(wsSlug);
|
|
55
58
|
const body = { name: opts.name };
|
|
56
59
|
if (opts.description)
|
|
57
60
|
body.description = opts.description;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boards.js","sourceRoot":"","sources":["../../src/commands/boards.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"boards.js","sourceRoot":"","sources":["../../src/commands/boards.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* opvs comments — task comments (activity feed)
|
|
3
3
|
*/
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
|
-
import {
|
|
5
|
+
import { getEffectiveConfig } from "../lib/config.js";
|
|
6
6
|
import { createClient } from "../lib/api.js";
|
|
7
7
|
import { buildUrl, printResponse, printJson } from "../lib/format.js";
|
|
8
8
|
export function registerCommentCommands(program) {
|
|
@@ -12,9 +12,10 @@ export function registerCommentCommands(program) {
|
|
|
12
12
|
.description("List comments on a task")
|
|
13
13
|
.option("--limit <n>", "Max results", "25")
|
|
14
14
|
.action(async (taskId, opts) => {
|
|
15
|
-
const
|
|
15
|
+
const wsSlug = program.opts().workspace;
|
|
16
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
16
17
|
try {
|
|
17
|
-
const client = createClient();
|
|
18
|
+
const client = createClient(wsSlug);
|
|
18
19
|
const params = {};
|
|
19
20
|
if (opts.limit)
|
|
20
21
|
params.limit = opts.limit;
|
|
@@ -33,8 +34,9 @@ export function registerCommentCommands(program) {
|
|
|
33
34
|
.description("Add a comment to a task")
|
|
34
35
|
.option("-f, --file <path>", "Read comment body from file")
|
|
35
36
|
.action(async (taskId, message, opts) => {
|
|
37
|
+
const wsSlug = program.opts().workspace;
|
|
36
38
|
try {
|
|
37
|
-
const client = createClient();
|
|
39
|
+
const client = createClient(wsSlug);
|
|
38
40
|
let body;
|
|
39
41
|
if (opts.file) {
|
|
40
42
|
body = readFileSync(opts.file, "utf-8");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/commands/comments.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/commands/comments.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEtE,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;IAE1E,QAAQ;SACL,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,CAAC;SAC1C,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,IAAI,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC;QACxC,MAAM,GAAG,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YACpC,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,KAAK;gBAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YAC1C,MAAM,GAAG,GAAG,QAAQ,CAAC,uBAAuB,MAAM,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;YACnF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,GAA0B,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,IAAI,yBAAyB,EAAE,CAAC,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,QAAQ;SACL,OAAO,CAAC,wBAAwB,CAAC;SACjC,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,mBAAmB,EAAE,6BAA6B,CAAC;SAC1D,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,OAA2B,EAAE,IAAI,EAAE,EAAE;QAClE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,IAAY,CAAC;YACjB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1C,CAAC;iBAAM,IAAI,OAAO,EAAE,CAAC;gBACnB,IAAI,GAAG,OAAO,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;gBACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,uBAAuB,MAAM,WAAW,EAAE;gBACtE,OAAO,EAAE,IAAK;aACf,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,SAAS,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,GAA0B,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,IAAI,uBAAuB,EAAE,CAAC,CAAC;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/commands/config.js
CHANGED
|
@@ -1,45 +1,99 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* opvs config — manage CLI configuration + opvs init
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { getEffectiveConfig, saveWorkspace, saveGlobal, resetConfig, getConfigPath, loadRawConfig, } from "../lib/config.js";
|
|
5
|
+
const GLOBAL_KEYS = ["format"];
|
|
6
|
+
const WORKSPACE_KEYS = ["api_url", "token", "brand_id", "brand_name"];
|
|
7
|
+
const ALL_KEYS = [...GLOBAL_KEYS, ...WORKSPACE_KEYS];
|
|
5
8
|
export function registerConfigCommands(program) {
|
|
6
9
|
const config = program.command("config").description("Manage CLI configuration");
|
|
7
10
|
config
|
|
8
11
|
.command("set <key> <value>")
|
|
9
12
|
.description("Set a config value (api_url, token, brand_id, brand_name, format)")
|
|
10
13
|
.action((key, value) => {
|
|
11
|
-
|
|
12
|
-
if (!valid.includes(key)) {
|
|
14
|
+
if (!ALL_KEYS.includes(key)) {
|
|
13
15
|
console.error(`Unknown config key: ${key}`);
|
|
14
|
-
console.error(`Valid keys: ${
|
|
16
|
+
console.error(`Valid keys: ${ALL_KEYS.join(", ")}`);
|
|
15
17
|
process.exit(1);
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
if (GLOBAL_KEYS.includes(key)) {
|
|
20
|
+
// Global setting
|
|
21
|
+
if (key === "format") {
|
|
22
|
+
const valid = ["yaml", "json", "md"];
|
|
23
|
+
if (!valid.includes(value)) {
|
|
24
|
+
console.error(`Invalid format. Choose: ${valid.join(", ")}`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
saveGlobal({ format: value });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// Workspace-scoped setting
|
|
32
|
+
const wsSlug = program.opts().workspace;
|
|
33
|
+
let cfg;
|
|
34
|
+
try {
|
|
35
|
+
cfg = getEffectiveConfig(wsSlug);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
console.error("No workspace selected. Use -w <slug> or run `opvs workspace use <slug>` first.");
|
|
39
|
+
process.exit(1);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const parsed = key === "brand_id" ? Number(value) : value;
|
|
43
|
+
saveWorkspace(cfg.workspace_slug, { [key]: parsed });
|
|
44
|
+
}
|
|
19
45
|
console.log(`${key} = ${value}`);
|
|
20
46
|
});
|
|
21
47
|
config
|
|
22
48
|
.command("get [key]")
|
|
23
49
|
.description("Show current config (or a specific key)")
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
.option("--all", "Show full config with all workspaces")
|
|
51
|
+
.action((key, opts) => {
|
|
52
|
+
if (opts.all) {
|
|
53
|
+
const raw = loadRawConfig();
|
|
54
|
+
// Mask tokens in all workspaces
|
|
55
|
+
const display = {
|
|
56
|
+
...raw,
|
|
57
|
+
workspaces: Object.fromEntries(Object.entries(raw.workspaces).map(([slug, ws]) => [
|
|
58
|
+
slug,
|
|
59
|
+
{ ...ws, token: ws.token ? `${ws.token.slice(0, 12)}...` : "(not set)" },
|
|
60
|
+
])),
|
|
61
|
+
};
|
|
62
|
+
console.log(JSON.stringify(display, null, 2));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const wsSlug = program.opts().workspace;
|
|
67
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
68
|
+
if (key) {
|
|
69
|
+
const val = cfg[key];
|
|
70
|
+
if (val === undefined) {
|
|
71
|
+
console.error(`Unknown config key: ${key}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
console.log(val);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const display = {
|
|
78
|
+
workspace: cfg.workspace_slug,
|
|
79
|
+
api_url: cfg.api_url,
|
|
80
|
+
brand_name: cfg.brand_name || "(not set)",
|
|
81
|
+
brand_id: cfg.brand_id,
|
|
82
|
+
token: cfg.token ? `${cfg.token.slice(0, 12)}...` : "(not set)",
|
|
83
|
+
format: cfg.format,
|
|
84
|
+
};
|
|
85
|
+
console.log(JSON.stringify(display, null, 2));
|
|
31
86
|
}
|
|
32
|
-
console.log(val);
|
|
33
87
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
88
|
+
catch (err) {
|
|
89
|
+
const e = err;
|
|
90
|
+
console.error(e.message);
|
|
91
|
+
process.exit(1);
|
|
38
92
|
}
|
|
39
93
|
});
|
|
40
94
|
config
|
|
41
95
|
.command("reset")
|
|
42
|
-
.description("Reset config to defaults")
|
|
96
|
+
.description("Reset config to defaults (removes all workspaces)")
|
|
43
97
|
.action(() => {
|
|
44
98
|
resetConfig();
|
|
45
99
|
console.log("Config reset to defaults.");
|
|
@@ -55,29 +109,46 @@ export function registerConfigCommands(program) {
|
|
|
55
109
|
.command("init")
|
|
56
110
|
.description("Print a CLAUDE.md snippet for AI agent integration")
|
|
57
111
|
.action(() => {
|
|
58
|
-
|
|
112
|
+
let wsInfo = "";
|
|
113
|
+
try {
|
|
114
|
+
const wsSlug = program.opts().workspace;
|
|
115
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
116
|
+
wsInfo = `
|
|
117
|
+
## Config
|
|
118
|
+
- Workspace: ${cfg.workspace_slug}
|
|
119
|
+
- API: ${cfg.api_url}
|
|
120
|
+
- Brand: ${cfg.brand_name || "(not set)"}
|
|
121
|
+
- Format: ${cfg.format}
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
wsInfo = `
|
|
126
|
+
## Config
|
|
127
|
+
- Run \`opvs auth request -w <slug> -e <admin-email>\` to authenticate first.
|
|
128
|
+
`;
|
|
129
|
+
}
|
|
59
130
|
const snippet = `# OPVS AgentBoard + Docs
|
|
60
131
|
|
|
61
132
|
## Setup
|
|
62
133
|
Run \`opvs auth request --workspace <slug> --email <your-email>\` if not authenticated.
|
|
63
134
|
|
|
135
|
+
## Workspace
|
|
136
|
+
- \`opvs workspace list\` — List configured workspaces
|
|
137
|
+
- \`opvs workspace use <slug>\` — Switch workspace
|
|
138
|
+
- \`opvs -w <slug> <command>\` — Run a command against a specific workspace
|
|
139
|
+
|
|
64
140
|
## Board Commands
|
|
65
141
|
- \`opvs session get --self\` — Board context + assigned tasks
|
|
66
142
|
- \`opvs tasks list --self --status pending\` — Pending tasks
|
|
67
|
-
- \`opvs
|
|
68
|
-
- \`opvs
|
|
143
|
+
- \`opvs tasks update <id> --status review --result-file ./output.md\` — Complete a task
|
|
144
|
+
- \`opvs comments add <id> "message"\` — Add a comment
|
|
69
145
|
|
|
70
146
|
## Docs Commands
|
|
71
147
|
- \`opvs docs list\` — List doc projects
|
|
72
148
|
- \`opvs docs get <project> <slug>\` — Read a page
|
|
73
149
|
- \`opvs docs update <project> <slug> --file ./output.md\` — Update a page
|
|
74
150
|
- \`opvs docs search "query"\` — Search docs
|
|
75
|
-
|
|
76
|
-
## Config
|
|
77
|
-
- API: ${cfg.api_url}
|
|
78
|
-
- Brand: ${cfg.brand_name || "(not set)"}
|
|
79
|
-
- Format: ${cfg.format}
|
|
80
|
-
`;
|
|
151
|
+
${wsInfo}`;
|
|
81
152
|
console.log(snippet);
|
|
82
153
|
});
|
|
83
154
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/docs.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* opvs docs — AgentDocs versioned documentation
|
|
3
3
|
*/
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
|
-
import {
|
|
5
|
+
import { getEffectiveConfig } from "../lib/config.js";
|
|
6
6
|
import { createClient } from "../lib/api.js";
|
|
7
7
|
import { buildUrl, printResponse, printJson } from "../lib/format.js";
|
|
8
8
|
export function registerDocsCommands(program) {
|
|
@@ -11,9 +11,10 @@ export function registerDocsCommands(program) {
|
|
|
11
11
|
.command("list")
|
|
12
12
|
.description("List documentation projects")
|
|
13
13
|
.action(async () => {
|
|
14
|
-
const
|
|
14
|
+
const wsSlug = program.opts().workspace;
|
|
15
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
15
16
|
try {
|
|
16
|
-
const client = createClient();
|
|
17
|
+
const client = createClient(wsSlug);
|
|
17
18
|
const url = buildUrl("/api/v1/docs/projects", undefined, cfg.format);
|
|
18
19
|
const res = await client.get(url);
|
|
19
20
|
await printResponse(res);
|
|
@@ -29,9 +30,10 @@ export function registerDocsCommands(program) {
|
|
|
29
30
|
.description("Get a documentation page by project and slug")
|
|
30
31
|
.option("--version <version>", "Specific version")
|
|
31
32
|
.action(async (project, slug, opts) => {
|
|
32
|
-
const
|
|
33
|
+
const wsSlug = program.opts().workspace;
|
|
34
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
33
35
|
try {
|
|
34
|
-
const client = createClient();
|
|
36
|
+
const client = createClient(wsSlug);
|
|
35
37
|
const params = {};
|
|
36
38
|
if (opts.version)
|
|
37
39
|
params.version = opts.version;
|
|
@@ -54,8 +56,9 @@ export function registerDocsCommands(program) {
|
|
|
54
56
|
.option("-c, --content <text>", "Inline content")
|
|
55
57
|
.option("-m, --message <msg>", "Commit message", "Created via CLI")
|
|
56
58
|
.action(async (project, opts) => {
|
|
59
|
+
const wsSlug = program.opts().workspace;
|
|
57
60
|
try {
|
|
58
|
-
const client = createClient();
|
|
61
|
+
const client = createClient(wsSlug);
|
|
59
62
|
let content = "";
|
|
60
63
|
if (opts.file) {
|
|
61
64
|
content = readFileSync(opts.file, "utf-8");
|
|
@@ -88,8 +91,9 @@ export function registerDocsCommands(program) {
|
|
|
88
91
|
.option("-c, --content <text>", "Inline content")
|
|
89
92
|
.option("-m, --message <msg>", "Commit message", "Updated via CLI")
|
|
90
93
|
.action(async (project, slug, opts) => {
|
|
94
|
+
const wsSlug = program.opts().workspace;
|
|
91
95
|
try {
|
|
92
|
-
const client = createClient();
|
|
96
|
+
const client = createClient(wsSlug);
|
|
93
97
|
let content_md = "";
|
|
94
98
|
if (opts.file) {
|
|
95
99
|
content_md = readFileSync(opts.file, "utf-8");
|
|
@@ -123,9 +127,10 @@ export function registerDocsCommands(program) {
|
|
|
123
127
|
.option("--project <project>", "Filter by project")
|
|
124
128
|
.option("--limit <n>", "Max results", "10")
|
|
125
129
|
.action(async (query, opts) => {
|
|
126
|
-
const
|
|
130
|
+
const wsSlug = program.opts().workspace;
|
|
131
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
127
132
|
try {
|
|
128
|
-
const client = createClient();
|
|
133
|
+
const client = createClient(wsSlug);
|
|
129
134
|
const params = { q: query };
|
|
130
135
|
if (opts.project)
|
|
131
136
|
params.project = opts.project;
|