@opvs-ai/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/auth.d.ts +5 -0
- package/dist/commands/auth.js +149 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/boards.d.ts +5 -0
- package/dist/commands/boards.js +69 -0
- package/dist/commands/boards.js.map +1 -0
- package/dist/commands/comments.d.ts +5 -0
- package/dist/commands/comments.js +62 -0
- package/dist/commands/comments.js.map +1 -0
- package/dist/commands/config.d.ts +5 -0
- package/dist/commands/config.js +84 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/docs.d.ts +5 -0
- package/dist/commands/docs.js +145 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/session.d.ts +5 -0
- package/dist/commands/session.js +43 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/tasks.d.ts +5 -0
- package/dist/commands/tasks.js +139 -0
- package/dist/commands/tasks.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +27 -0
- package/dist/lib/api.js +128 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/auth-poll.d.ts +15 -0
- package/dist/lib/auth-poll.js +46 -0
- package/dist/lib/auth-poll.js.map +1 -0
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.js +39 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/fingerprint.d.ts +8 -0
- package/dist/lib/fingerprint.js +32 -0
- package/dist/lib/fingerprint.js.map +1 -0
- package/dist/lib/format.d.ts +19 -0
- package/dist/lib/format.js +55 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opvs auth — AI-native token provisioning + management
|
|
3
|
+
*/
|
|
4
|
+
import { loadConfig, saveConfig } from "../lib/config.js";
|
|
5
|
+
import { apiUnauthPost, createClient } from "../lib/api.js";
|
|
6
|
+
import { buildFingerprint } from "../lib/fingerprint.js";
|
|
7
|
+
import { pollForApproval } from "../lib/auth-poll.js";
|
|
8
|
+
import { printJson } from "../lib/format.js";
|
|
9
|
+
export function registerAuthCommands(program) {
|
|
10
|
+
const auth = program.command("auth").description("Token authentication");
|
|
11
|
+
auth
|
|
12
|
+
.command("request")
|
|
13
|
+
.description("Request a PAT token (sends approval email to workspace owner)")
|
|
14
|
+
.requiredOption("-w, --workspace <slug>", "Workspace slug")
|
|
15
|
+
.requiredOption("-e, --email <email>", "Owner email (admin who approves)")
|
|
16
|
+
.option("-p, --project <name>", "Project name (shown in approval email)")
|
|
17
|
+
.option("-s, --scopes <scopes>", "Comma-separated scopes", "board:read,board:write")
|
|
18
|
+
.option("-t, --ttl <hours>", "Token TTL in hours", "72")
|
|
19
|
+
.option("--api-url <url>", "API base URL (overrides config)")
|
|
20
|
+
.action(async (opts) => {
|
|
21
|
+
const cfg = loadConfig();
|
|
22
|
+
const baseUrl = opts.apiUrl || cfg.api_url;
|
|
23
|
+
const fingerprint = buildFingerprint();
|
|
24
|
+
const scopes = opts.scopes.split(",").map((s) => s.trim());
|
|
25
|
+
console.log(`Requesting access to workspace "${opts.workspace}"...`);
|
|
26
|
+
console.log(`Approval email will be sent to ${opts.email}`);
|
|
27
|
+
try {
|
|
28
|
+
const res = await apiUnauthPost(baseUrl, "/api/v1/auth/pat/request", {
|
|
29
|
+
workspace_slug: opts.workspace,
|
|
30
|
+
owner_email: opts.email,
|
|
31
|
+
project_name: opts.project || null,
|
|
32
|
+
requested_scopes: scopes,
|
|
33
|
+
ttl_hours: parseInt(opts.ttl, 10),
|
|
34
|
+
fingerprint,
|
|
35
|
+
});
|
|
36
|
+
const data = await res.json();
|
|
37
|
+
const { request_id, poll_token, expires_at } = data;
|
|
38
|
+
console.log(`Request ID: ${request_id}`);
|
|
39
|
+
console.log(`Expires: ${expires_at}`);
|
|
40
|
+
// Start polling
|
|
41
|
+
const result = await pollForApproval(baseUrl, request_id, poll_token);
|
|
42
|
+
if (result.status === "active" && result.token) {
|
|
43
|
+
// Save token + brand info to config
|
|
44
|
+
saveConfig({
|
|
45
|
+
api_url: baseUrl,
|
|
46
|
+
token: result.token,
|
|
47
|
+
brand_id: result.brand_id ?? null,
|
|
48
|
+
brand_name: result.brand_name ?? "",
|
|
49
|
+
});
|
|
50
|
+
console.log(`\nAuthenticated! Token saved to config.`);
|
|
51
|
+
console.log(`Brand: ${result.brand_name} (ID: ${result.brand_id})`);
|
|
52
|
+
console.log(`Scopes: ${result.scopes?.join(", ")}`);
|
|
53
|
+
}
|
|
54
|
+
else if (result.status === "denied") {
|
|
55
|
+
console.error("\nAccess denied by workspace owner.");
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
else if (result.status === "expired") {
|
|
59
|
+
console.error("\nRequest expired. Try again.");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
console.error("\nRequest timed out. The owner may not have seen the email.");
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const e = err;
|
|
69
|
+
console.error(`Error: ${e.detail || "Request failed"}`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
auth
|
|
74
|
+
.command("status")
|
|
75
|
+
.description("Show current authentication status")
|
|
76
|
+
.action(async () => {
|
|
77
|
+
const cfg = loadConfig();
|
|
78
|
+
if (!cfg.token) {
|
|
79
|
+
console.log("Not authenticated. Run `opvs auth request` to get a token.");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const client = createClient();
|
|
84
|
+
const res = await client.get("/api/v1/auth/me");
|
|
85
|
+
const data = await res.json();
|
|
86
|
+
printJson(data);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
const e = err;
|
|
90
|
+
if (e.status === 401) {
|
|
91
|
+
console.error("Token is invalid or expired. Run `opvs auth request` to re-authenticate.");
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.error(`Error: ${e.detail || "Failed to check status"}`);
|
|
95
|
+
}
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
auth
|
|
100
|
+
.command("revoke")
|
|
101
|
+
.description("Revoke the current token")
|
|
102
|
+
.action(async () => {
|
|
103
|
+
const cfg = loadConfig();
|
|
104
|
+
if (!cfg.token) {
|
|
105
|
+
console.log("Not authenticated — nothing to revoke.");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const client = createClient();
|
|
110
|
+
// Find the token ID by matching prefix from the tokens list
|
|
111
|
+
const prefix = cfg.token.slice(0, 16);
|
|
112
|
+
const listRes = await client.get("/api/v1/tokens");
|
|
113
|
+
const listData = await listRes.json();
|
|
114
|
+
const match = listData.tokens?.find((t) => t.token_prefix === prefix && t.is_active);
|
|
115
|
+
if (match) {
|
|
116
|
+
await client.delete(`/api/v1/tokens/${match.id}`);
|
|
117
|
+
console.log("Token revoked on server.");
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
console.log("Token not found on server (may already be revoked).");
|
|
121
|
+
}
|
|
122
|
+
saveConfig({ token: "", brand_id: null, brand_name: "" });
|
|
123
|
+
console.log("Local config cleared.");
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
const e = err;
|
|
127
|
+
// Clear local config even if server revoke fails
|
|
128
|
+
saveConfig({ token: "", brand_id: null, brand_name: "" });
|
|
129
|
+
console.error(`Server revoke failed (${e.detail}), but local config cleared.`);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
auth
|
|
133
|
+
.command("list")
|
|
134
|
+
.description("List all agent tokens for the workspace (admin)")
|
|
135
|
+
.action(async () => {
|
|
136
|
+
try {
|
|
137
|
+
const client = createClient();
|
|
138
|
+
const res = await client.get("/api/v1/auth/pat/agents");
|
|
139
|
+
const data = await res.json();
|
|
140
|
+
printJson(data);
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
const e = err;
|
|
144
|
+
console.error(`Error: ${e.detail || "Failed to list agents"}`);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opvs boards — board CRUD
|
|
3
|
+
*/
|
|
4
|
+
import { loadConfig } from "../lib/config.js";
|
|
5
|
+
import { createClient } from "../lib/api.js";
|
|
6
|
+
import { buildUrl, printResponse, printJson } from "../lib/format.js";
|
|
7
|
+
export function registerBoardCommands(program) {
|
|
8
|
+
const boards = program.command("boards").description("AgentBoard management");
|
|
9
|
+
boards
|
|
10
|
+
.command("list")
|
|
11
|
+
.description("List boards")
|
|
12
|
+
.option("--status <status>", "Filter by status")
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
const cfg = loadConfig();
|
|
15
|
+
try {
|
|
16
|
+
const client = createClient();
|
|
17
|
+
const params = {};
|
|
18
|
+
if (opts.status)
|
|
19
|
+
params.status = opts.status;
|
|
20
|
+
const url = buildUrl("/api/v1/board/boards", params, cfg.format);
|
|
21
|
+
const res = await client.get(url);
|
|
22
|
+
await printResponse(res);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const e = err;
|
|
26
|
+
console.error(`Error: ${e.detail || "Failed to list boards"}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
boards
|
|
31
|
+
.command("get <id>")
|
|
32
|
+
.description("Get board details")
|
|
33
|
+
.action(async (id) => {
|
|
34
|
+
const cfg = loadConfig();
|
|
35
|
+
try {
|
|
36
|
+
const client = createClient();
|
|
37
|
+
const url = buildUrl(`/api/v1/board/boards/${id}`, undefined, cfg.format);
|
|
38
|
+
const res = await client.get(url);
|
|
39
|
+
await printResponse(res);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const e = err;
|
|
43
|
+
console.error(`Error: ${e.detail || "Failed to get board"}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
boards
|
|
48
|
+
.command("create")
|
|
49
|
+
.description("Create a new board")
|
|
50
|
+
.requiredOption("-n, --name <name>", "Board name")
|
|
51
|
+
.option("-d, --description <desc>", "Board description")
|
|
52
|
+
.action(async (opts) => {
|
|
53
|
+
try {
|
|
54
|
+
const client = createClient();
|
|
55
|
+
const body = { name: opts.name };
|
|
56
|
+
if (opts.description)
|
|
57
|
+
body.description = opts.description;
|
|
58
|
+
const res = await client.post("/api/v1/board/boards", body);
|
|
59
|
+
const data = await res.json();
|
|
60
|
+
printJson(data);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const e = err;
|
|
64
|
+
console.error(`Error: ${e.detail || "Failed to create board"}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=boards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boards.js","sourceRoot":"","sources":["../../src/commands/boards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opvs comments — task comments (activity feed)
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { loadConfig } from "../lib/config.js";
|
|
6
|
+
import { createClient } from "../lib/api.js";
|
|
7
|
+
import { buildUrl, printResponse, printJson } from "../lib/format.js";
|
|
8
|
+
export function registerCommentCommands(program) {
|
|
9
|
+
const comments = program.command("comments").description("Task comments");
|
|
10
|
+
comments
|
|
11
|
+
.command("list <taskId>")
|
|
12
|
+
.description("List comments on a task")
|
|
13
|
+
.option("--limit <n>", "Max results", "25")
|
|
14
|
+
.action(async (taskId, opts) => {
|
|
15
|
+
const cfg = loadConfig();
|
|
16
|
+
try {
|
|
17
|
+
const client = createClient();
|
|
18
|
+
const params = {};
|
|
19
|
+
if (opts.limit)
|
|
20
|
+
params.limit = opts.limit;
|
|
21
|
+
const url = buildUrl(`/api/v1/board/tasks/${taskId}/comments`, params, cfg.format);
|
|
22
|
+
const res = await client.get(url);
|
|
23
|
+
await printResponse(res);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
const e = err;
|
|
27
|
+
console.error(`Error: ${e.detail || "Failed to list comments"}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
comments
|
|
32
|
+
.command("add <taskId> [message]")
|
|
33
|
+
.description("Add a comment to a task")
|
|
34
|
+
.option("-f, --file <path>", "Read comment body from file")
|
|
35
|
+
.action(async (taskId, message, opts) => {
|
|
36
|
+
try {
|
|
37
|
+
const client = createClient();
|
|
38
|
+
let body;
|
|
39
|
+
if (opts.file) {
|
|
40
|
+
body = readFileSync(opts.file, "utf-8");
|
|
41
|
+
}
|
|
42
|
+
else if (message) {
|
|
43
|
+
body = message;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
console.error("Provide a message or --file <path>");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const res = await client.post(`/api/v1/board/tasks/${taskId}/comments`, {
|
|
50
|
+
content: body,
|
|
51
|
+
});
|
|
52
|
+
const data = await res.json();
|
|
53
|
+
printJson(data);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
const e = err;
|
|
57
|
+
console.error(`Error: ${e.detail || "Failed to add comment"}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=comments.js.map
|
|
@@ -0,0 +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,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,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,GAAG,GAAG,UAAU,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;YAC9B,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,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;YAC9B,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,IAAI;aACd,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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opvs config — manage CLI configuration + opvs init
|
|
3
|
+
*/
|
|
4
|
+
import { loadConfig, saveConfig, resetConfig, getConfigPath } from "../lib/config.js";
|
|
5
|
+
export function registerConfigCommands(program) {
|
|
6
|
+
const config = program.command("config").description("Manage CLI configuration");
|
|
7
|
+
config
|
|
8
|
+
.command("set <key> <value>")
|
|
9
|
+
.description("Set a config value (api_url, token, brand_id, brand_name, format)")
|
|
10
|
+
.action((key, value) => {
|
|
11
|
+
const valid = ["api_url", "token", "brand_id", "brand_name", "format"];
|
|
12
|
+
if (!valid.includes(key)) {
|
|
13
|
+
console.error(`Unknown config key: ${key}`);
|
|
14
|
+
console.error(`Valid keys: ${valid.join(", ")}`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const parsed = key === "brand_id" ? Number(value) : value;
|
|
18
|
+
saveConfig({ [key]: parsed });
|
|
19
|
+
console.log(`${key} = ${value}`);
|
|
20
|
+
});
|
|
21
|
+
config
|
|
22
|
+
.command("get [key]")
|
|
23
|
+
.description("Show current config (or a specific key)")
|
|
24
|
+
.action((key) => {
|
|
25
|
+
const cfg = loadConfig();
|
|
26
|
+
if (key) {
|
|
27
|
+
const val = cfg[key];
|
|
28
|
+
if (val === undefined) {
|
|
29
|
+
console.error(`Unknown config key: ${key}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
console.log(val);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Mask token for display
|
|
36
|
+
const display = { ...cfg, token: cfg.token ? `${cfg.token.slice(0, 12)}...` : "(not set)" };
|
|
37
|
+
console.log(JSON.stringify(display, null, 2));
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
config
|
|
41
|
+
.command("reset")
|
|
42
|
+
.description("Reset config to defaults")
|
|
43
|
+
.action(() => {
|
|
44
|
+
resetConfig();
|
|
45
|
+
console.log("Config reset to defaults.");
|
|
46
|
+
});
|
|
47
|
+
config
|
|
48
|
+
.command("path")
|
|
49
|
+
.description("Show config file path")
|
|
50
|
+
.action(() => {
|
|
51
|
+
console.log(getConfigPath());
|
|
52
|
+
});
|
|
53
|
+
// opvs init — generate a CLAUDE.md snippet
|
|
54
|
+
program
|
|
55
|
+
.command("init")
|
|
56
|
+
.description("Print a CLAUDE.md snippet for AI agent integration")
|
|
57
|
+
.action(() => {
|
|
58
|
+
const cfg = loadConfig();
|
|
59
|
+
const snippet = `# OPVS AgentBoard + Docs
|
|
60
|
+
|
|
61
|
+
## Setup
|
|
62
|
+
Run \`opvs auth request --workspace <slug> --email <your-email>\` if not authenticated.
|
|
63
|
+
|
|
64
|
+
## Board Commands
|
|
65
|
+
- \`opvs session get --self\` — Board context + assigned tasks
|
|
66
|
+
- \`opvs tasks list --self --status pending\` — Pending tasks
|
|
67
|
+
- \`opvs task update <id> --status review --result-file ./output.md\` — Complete a task
|
|
68
|
+
- \`opvs comment add <id> "message"\` — Add a comment
|
|
69
|
+
|
|
70
|
+
## Docs Commands
|
|
71
|
+
- \`opvs docs list\` — List doc projects
|
|
72
|
+
- \`opvs docs get <project> <slug>\` — Read a page
|
|
73
|
+
- \`opvs docs update <project> <slug> --file ./output.md\` — Update a page
|
|
74
|
+
- \`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
|
+
`;
|
|
81
|
+
console.log(snippet);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opvs docs — AgentDocs versioned documentation
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { loadConfig } from "../lib/config.js";
|
|
6
|
+
import { createClient } from "../lib/api.js";
|
|
7
|
+
import { buildUrl, printResponse, printJson } from "../lib/format.js";
|
|
8
|
+
export function registerDocsCommands(program) {
|
|
9
|
+
const docs = program.command("docs").description("AgentDocs documentation");
|
|
10
|
+
docs
|
|
11
|
+
.command("list")
|
|
12
|
+
.description("List documentation projects")
|
|
13
|
+
.action(async () => {
|
|
14
|
+
const cfg = loadConfig();
|
|
15
|
+
try {
|
|
16
|
+
const client = createClient();
|
|
17
|
+
const url = buildUrl("/api/v1/docs/projects", undefined, cfg.format);
|
|
18
|
+
const res = await client.get(url);
|
|
19
|
+
await printResponse(res);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
const e = err;
|
|
23
|
+
console.error(`Error: ${e.detail || "Failed to list projects"}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
docs
|
|
28
|
+
.command("get <project> <slug>")
|
|
29
|
+
.description("Get a documentation page by project and slug")
|
|
30
|
+
.option("--version <version>", "Specific version")
|
|
31
|
+
.action(async (project, slug, opts) => {
|
|
32
|
+
const cfg = loadConfig();
|
|
33
|
+
try {
|
|
34
|
+
const client = createClient();
|
|
35
|
+
const params = {};
|
|
36
|
+
if (opts.version)
|
|
37
|
+
params.version = opts.version;
|
|
38
|
+
const url = buildUrl(`/api/v1/docs/projects/${project}/pages/${slug}`, params, cfg.format);
|
|
39
|
+
const res = await client.get(url);
|
|
40
|
+
await printResponse(res);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
const e = err;
|
|
44
|
+
console.error(`Error: ${e.detail || "Failed to get page"}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
docs
|
|
49
|
+
.command("create <project>")
|
|
50
|
+
.description("Create a documentation page")
|
|
51
|
+
.requiredOption("-t, --title <title>", "Page title")
|
|
52
|
+
.requiredOption("-s, --slug <slug>", "Page slug")
|
|
53
|
+
.option("-f, --file <path>", "Read content from file")
|
|
54
|
+
.option("-c, --content <text>", "Inline content")
|
|
55
|
+
.option("-m, --message <msg>", "Commit message", "Created via CLI")
|
|
56
|
+
.action(async (project, opts) => {
|
|
57
|
+
try {
|
|
58
|
+
const client = createClient();
|
|
59
|
+
let content = "";
|
|
60
|
+
if (opts.file) {
|
|
61
|
+
content = readFileSync(opts.file, "utf-8");
|
|
62
|
+
}
|
|
63
|
+
else if (opts.content) {
|
|
64
|
+
content = opts.content;
|
|
65
|
+
}
|
|
66
|
+
const body = {
|
|
67
|
+
title: opts.title,
|
|
68
|
+
slug: opts.slug,
|
|
69
|
+
commit_message: opts.message,
|
|
70
|
+
};
|
|
71
|
+
if (content)
|
|
72
|
+
body.content_md = content;
|
|
73
|
+
const res = await client.post(`/api/v1/docs/projects/${project}/pages`, body);
|
|
74
|
+
const data = await res.json();
|
|
75
|
+
printJson(data);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
const e = err;
|
|
79
|
+
console.error(`Error: ${e.detail || "Failed to create page"}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
docs
|
|
84
|
+
.command("update <project> <slug>")
|
|
85
|
+
.description("Update a documentation page")
|
|
86
|
+
.option("-t, --title <title>", "New title")
|
|
87
|
+
.option("-f, --file <path>", "Read content from file")
|
|
88
|
+
.option("-c, --content <text>", "Inline content")
|
|
89
|
+
.option("-m, --message <msg>", "Commit message", "Updated via CLI")
|
|
90
|
+
.action(async (project, slug, opts) => {
|
|
91
|
+
try {
|
|
92
|
+
const client = createClient();
|
|
93
|
+
let content_md = "";
|
|
94
|
+
if (opts.file) {
|
|
95
|
+
content_md = readFileSync(opts.file, "utf-8");
|
|
96
|
+
}
|
|
97
|
+
else if (opts.content) {
|
|
98
|
+
content_md = opts.content;
|
|
99
|
+
}
|
|
100
|
+
if (!content_md) {
|
|
101
|
+
console.error("Content required. Provide --content or --file");
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
const body = {
|
|
105
|
+
content_md,
|
|
106
|
+
commit_message: opts.message,
|
|
107
|
+
};
|
|
108
|
+
if (opts.title)
|
|
109
|
+
body.title = opts.title;
|
|
110
|
+
const res = await client.put(`/api/v1/docs/projects/${project}/pages/${slug}`, body);
|
|
111
|
+
const data = await res.json();
|
|
112
|
+
printJson(data);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
const e = err;
|
|
116
|
+
console.error(`Error: ${e.detail || "Failed to update page"}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
docs
|
|
121
|
+
.command("search <query>")
|
|
122
|
+
.description("Search documentation")
|
|
123
|
+
.option("--project <project>", "Filter by project")
|
|
124
|
+
.option("--limit <n>", "Max results", "10")
|
|
125
|
+
.action(async (query, opts) => {
|
|
126
|
+
const cfg = loadConfig();
|
|
127
|
+
try {
|
|
128
|
+
const client = createClient();
|
|
129
|
+
const params = { q: query };
|
|
130
|
+
if (opts.project)
|
|
131
|
+
params.project = opts.project;
|
|
132
|
+
if (opts.limit)
|
|
133
|
+
params.limit = opts.limit;
|
|
134
|
+
const url = buildUrl("/api/v1/docs/search", params, cfg.format);
|
|
135
|
+
const res = await client.get(url);
|
|
136
|
+
await printResponse(res);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
const e = err;
|
|
140
|
+
console.error(`Error: ${e.detail || "Failed to search docs"}`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opvs session — board context and agent session info
|
|
3
|
+
*/
|
|
4
|
+
import { loadConfig } from "../lib/config.js";
|
|
5
|
+
import { createClient } from "../lib/api.js";
|
|
6
|
+
import { buildUrl, printResponse } from "../lib/format.js";
|
|
7
|
+
export function registerSessionCommands(program) {
|
|
8
|
+
const session = program.command("session").description("Board session context");
|
|
9
|
+
session
|
|
10
|
+
.command("get")
|
|
11
|
+
.description("Get board context (agent session info + assigned tasks)")
|
|
12
|
+
.option("--self", "Show only your own context")
|
|
13
|
+
.option("--board <id>", "Board ID")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
const cfg = loadConfig();
|
|
16
|
+
try {
|
|
17
|
+
const client = createClient();
|
|
18
|
+
if (opts.self) {
|
|
19
|
+
// Use the agent convenience endpoint
|
|
20
|
+
const url = buildUrl("/api/v1/board/agent-api/my-tasks", undefined, cfg.format);
|
|
21
|
+
const res = await client.get(url);
|
|
22
|
+
await printResponse(res);
|
|
23
|
+
}
|
|
24
|
+
else if (opts.board) {
|
|
25
|
+
const url = buildUrl(`/api/v1/board/boards/${opts.board}`, undefined, cfg.format);
|
|
26
|
+
const res = await client.get(url);
|
|
27
|
+
await printResponse(res);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// Default: list boards to show available context
|
|
31
|
+
const url = buildUrl("/api/v1/board/boards", undefined, cfg.format);
|
|
32
|
+
const res = await client.get(url);
|
|
33
|
+
await printResponse(res);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const e = err;
|
|
38
|
+
console.error(`Error: ${e.detail || "Failed to get session"}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE3D,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAEhF,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,yDAAyD,CAAC;SACtE,MAAM,CAAC,QAAQ,EAAE,4BAA4B,CAAC;SAC9C,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,qCAAqC;gBACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,kCAAkC,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBAChF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAClC,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;iBAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,GAAG,GAAG,QAAQ,CAAC,wBAAwB,IAAI,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBAClF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAClC,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,iDAAiD;gBACjD,MAAM,GAAG,GAAG,QAAQ,CAAC,sBAAsB,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBACpE,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAClC,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;QACH,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;AAEP,CAAC"}
|