@overlordai/developer-cli 1.0.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.
Files changed (65) hide show
  1. package/dist/auth/api-client.d.ts +15 -0
  2. package/dist/auth/api-client.d.ts.map +1 -0
  3. package/dist/auth/api-client.js +79 -0
  4. package/dist/auth/api-client.js.map +1 -0
  5. package/dist/auth/token-store.d.ts +13 -0
  6. package/dist/auth/token-store.d.ts.map +1 -0
  7. package/dist/auth/token-store.js +52 -0
  8. package/dist/auth/token-store.js.map +1 -0
  9. package/dist/commands/attach.d.ts +3 -0
  10. package/dist/commands/attach.d.ts.map +1 -0
  11. package/dist/commands/attach.js +48 -0
  12. package/dist/commands/attach.js.map +1 -0
  13. package/dist/commands/config.d.ts +11 -0
  14. package/dist/commands/config.d.ts.map +1 -0
  15. package/dist/commands/config.js +100 -0
  16. package/dist/commands/config.js.map +1 -0
  17. package/dist/commands/helpers.d.ts +15 -0
  18. package/dist/commands/helpers.d.ts.map +1 -0
  19. package/dist/commands/helpers.js +41 -0
  20. package/dist/commands/helpers.js.map +1 -0
  21. package/dist/commands/login.d.ts +3 -0
  22. package/dist/commands/login.d.ts.map +1 -0
  23. package/dist/commands/login.js +83 -0
  24. package/dist/commands/login.js.map +1 -0
  25. package/dist/commands/logout.d.ts +3 -0
  26. package/dist/commands/logout.d.ts.map +1 -0
  27. package/dist/commands/logout.js +16 -0
  28. package/dist/commands/logout.js.map +1 -0
  29. package/dist/commands/machine.d.ts +3 -0
  30. package/dist/commands/machine.d.ts.map +1 -0
  31. package/dist/commands/machine.js +81 -0
  32. package/dist/commands/machine.js.map +1 -0
  33. package/dist/commands/notifications.d.ts +3 -0
  34. package/dist/commands/notifications.d.ts.map +1 -0
  35. package/dist/commands/notifications.js +55 -0
  36. package/dist/commands/notifications.js.map +1 -0
  37. package/dist/commands/project.d.ts +3 -0
  38. package/dist/commands/project.d.ts.map +1 -0
  39. package/dist/commands/project.js +61 -0
  40. package/dist/commands/project.js.map +1 -0
  41. package/dist/commands/search.d.ts +3 -0
  42. package/dist/commands/search.d.ts.map +1 -0
  43. package/dist/commands/search.js +58 -0
  44. package/dist/commands/search.js.map +1 -0
  45. package/dist/commands/task.d.ts +3 -0
  46. package/dist/commands/task.d.ts.map +1 -0
  47. package/dist/commands/task.js +347 -0
  48. package/dist/commands/task.js.map +1 -0
  49. package/dist/commands/whoami.d.ts +3 -0
  50. package/dist/commands/whoami.d.ts.map +1 -0
  51. package/dist/commands/whoami.js +32 -0
  52. package/dist/commands/whoami.js.map +1 -0
  53. package/dist/main.d.ts +3 -0
  54. package/dist/main.d.ts.map +1 -0
  55. package/dist/main.js +32 -0
  56. package/dist/main.js.map +1 -0
  57. package/dist/output/formatter.d.ts +18 -0
  58. package/dist/output/formatter.d.ts.map +1 -0
  59. package/dist/output/formatter.js +63 -0
  60. package/dist/output/formatter.js.map +1 -0
  61. package/dist/terminal/pty-client.d.ts +20 -0
  62. package/dist/terminal/pty-client.d.ts.map +1 -0
  63. package/dist/terminal/pty-client.js +133 -0
  64. package/dist/terminal/pty-client.js.map +1 -0
  65. package/package.json +29 -0
@@ -0,0 +1,15 @@
1
+ export interface ApiResponse<T = unknown> {
2
+ status: number;
3
+ data: T;
4
+ }
5
+ export declare class ApiClient {
6
+ private readonly baseUrl;
7
+ private readonly token;
8
+ constructor(baseUrl: string, token: string);
9
+ get<T = unknown>(path: string): Promise<ApiResponse<T>>;
10
+ post<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
11
+ put<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
12
+ delete<T = unknown>(path: string): Promise<ApiResponse<T>>;
13
+ private request;
14
+ }
15
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/auth/api-client.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,CAAC;CACT;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAKpC,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAIvD,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAIxE,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAIvE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAIhE,OAAO,CAAC,OAAO;CAkEhB"}
@@ -0,0 +1,79 @@
1
+ import * as http from 'node:http';
2
+ import * as https from 'node:https';
3
+ import { URL } from 'node:url';
4
+ export class ApiClient {
5
+ baseUrl;
6
+ token;
7
+ constructor(baseUrl, token) {
8
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
9
+ this.token = token;
10
+ }
11
+ async get(path) {
12
+ return this.request('GET', path);
13
+ }
14
+ async post(path, body) {
15
+ return this.request('POST', path, body);
16
+ }
17
+ async put(path, body) {
18
+ return this.request('PUT', path, body);
19
+ }
20
+ async delete(path) {
21
+ return this.request('DELETE', path);
22
+ }
23
+ request(method, apiPath, body) {
24
+ return new Promise((resolve, reject) => {
25
+ const url = new URL(`${this.baseUrl}${apiPath}`);
26
+ const isHttps = url.protocol === 'https:';
27
+ const transport = isHttps ? https : http;
28
+ const headers = {
29
+ 'Authorization': `Bearer ${this.token}`,
30
+ 'Accept': 'application/json',
31
+ };
32
+ let bodyStr;
33
+ if (body !== undefined) {
34
+ bodyStr = JSON.stringify(body);
35
+ headers['Content-Type'] = 'application/json';
36
+ headers['Content-Length'] = Buffer.byteLength(bodyStr).toString();
37
+ }
38
+ const req = transport.request({
39
+ hostname: url.hostname,
40
+ port: url.port || (isHttps ? 443 : 80),
41
+ path: url.pathname + url.search,
42
+ method,
43
+ headers,
44
+ }, (res) => {
45
+ const chunks = [];
46
+ res.on('data', (chunk) => chunks.push(chunk));
47
+ res.on('end', () => {
48
+ const rawBody = Buffer.concat(chunks).toString('utf-8');
49
+ let data;
50
+ try {
51
+ data = JSON.parse(rawBody);
52
+ }
53
+ catch {
54
+ data = rawBody;
55
+ }
56
+ const status = res.statusCode ?? 0;
57
+ if (status === 401) {
58
+ reject(new Error('Authentication failed. Please run `ov login` to re-authenticate.'));
59
+ return;
60
+ }
61
+ if (status === 429) {
62
+ const retryAfter = res.headers['retry-after'];
63
+ reject(new Error(`Rate limited. Retry after ${retryAfter ?? 'unknown'} seconds.`));
64
+ return;
65
+ }
66
+ resolve({ status, data });
67
+ });
68
+ });
69
+ req.on('error', (err) => {
70
+ reject(new Error(`Request failed: ${err.message}`));
71
+ });
72
+ if (bodyStr) {
73
+ req.write(bodyStr);
74
+ }
75
+ req.end();
76
+ });
77
+ }
78
+ }
79
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/auth/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface Credentials {
2
+ server: string;
3
+ token: string;
4
+ }
5
+ export declare class TokenStore {
6
+ private readonly configDir;
7
+ private readonly credentialsPath;
8
+ constructor(configDir?: string);
9
+ save(server: string, token: string): void;
10
+ load(): Credentials | null;
11
+ clear(): void;
12
+ }
13
+ //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,SAAS,CAAC,EAAE,MAAM;IAO9B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAYzC,IAAI,IAAI,WAAW,GAAG,IAAI;IAgB1B,KAAK,IAAI,IAAI;CASd"}
@@ -0,0 +1,52 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as os from 'node:os';
4
+ const CONFIG_DIR = path.join(os.homedir(), '.config', 'overlord');
5
+ const CREDENTIALS_PATH = path.join(CONFIG_DIR, 'credentials.json');
6
+ export class TokenStore {
7
+ configDir;
8
+ credentialsPath;
9
+ constructor(configDir) {
10
+ this.configDir = configDir ?? CONFIG_DIR;
11
+ this.credentialsPath = configDir
12
+ ? path.join(configDir, 'credentials.json')
13
+ : CREDENTIALS_PATH;
14
+ }
15
+ save(server, token) {
16
+ if (!fs.existsSync(this.configDir)) {
17
+ fs.mkdirSync(this.configDir, { recursive: true });
18
+ }
19
+ const data = { server, token };
20
+ fs.writeFileSync(this.credentialsPath, JSON.stringify(data, null, 2), {
21
+ encoding: 'utf-8',
22
+ mode: 0o600,
23
+ });
24
+ }
25
+ load() {
26
+ try {
27
+ if (!fs.existsSync(this.credentialsPath)) {
28
+ return null;
29
+ }
30
+ const raw = fs.readFileSync(this.credentialsPath, 'utf-8');
31
+ const data = JSON.parse(raw);
32
+ if (!data.server || !data.token) {
33
+ return null;
34
+ }
35
+ return data;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ clear() {
42
+ try {
43
+ if (fs.existsSync(this.credentialsPath)) {
44
+ fs.unlinkSync(this.credentialsPath);
45
+ }
46
+ }
47
+ catch {
48
+ // Ignore errors during cleanup
49
+ }
50
+ }
51
+ }
52
+ //# sourceMappingURL=token-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAO9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAClE,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAEnE,MAAM,OAAO,UAAU;IACJ,SAAS,CAAS;IAClB,eAAe,CAAS;IAEzC,YAAY,SAAkB;QAC5B,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,UAAU,CAAC;QACzC,IAAI,CAAC,eAAe,GAAG,SAAS;YAC9B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC;YAC1C,CAAC,CAAC,gBAAgB,CAAC;IACvB,CAAC;IAED,IAAI,CAAC,MAAc,EAAE,KAAa;QAChC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC5C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;YACpE,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;IAED,IAAI;QACF,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;gBACzC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;YAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;gBACxC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const attachCommand: Command;
3
+ //# sourceMappingURL=attach.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.d.ts","sourceRoot":"","sources":["../../src/commands/attach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,eAAO,MAAM,aAAa,SAkCtB,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { Command } from 'commander';
2
+ import { getServerUrl, getToken } from './helpers.js';
3
+ import { ApiClient } from '../auth/api-client.js';
4
+ import { PtyClient } from '../terminal/pty-client.js';
5
+ import { formatter } from '../output/formatter.js';
6
+ async function getChannelToken(serverUrl, taskId, token) {
7
+ const client = new ApiClient(serverUrl, token);
8
+ const res = await client.post(`/api/web/tasks/${taskId}/pty-token`);
9
+ if (res.status !== 200 && res.status !== 201) {
10
+ throw new Error(`Failed to obtain PTY channel token (status ${res.status})`);
11
+ }
12
+ return res.data.channelToken;
13
+ }
14
+ export const attachCommand = new Command('attach')
15
+ .description('Connect to a task PTY terminal')
16
+ .argument('<taskId>', 'Task ID to attach to')
17
+ .option('--takeover', 'Take over PTY control from current user')
18
+ .option('--watch', 'Read-only observer mode')
19
+ .option('--session <sessionId>', 'Session ID for takeover')
20
+ .action(async (taskId, opts) => {
21
+ let mode = 'interactive';
22
+ if (opts.takeover)
23
+ mode = 'takeover';
24
+ if (opts.watch)
25
+ mode = 'watch';
26
+ const serverUrl = getServerUrl();
27
+ const token = getToken();
28
+ formatter.info(`Attaching to task #${taskId} (${mode} mode)...`);
29
+ if (mode !== 'watch') {
30
+ formatter.info('Press Ctrl+] to detach.');
31
+ }
32
+ const client = new PtyClient({
33
+ serverUrl,
34
+ taskId,
35
+ token,
36
+ mode,
37
+ sessionId: opts.session,
38
+ getChannelToken,
39
+ });
40
+ try {
41
+ await client.connect();
42
+ }
43
+ catch (err) {
44
+ formatter.error(err instanceof Error ? err.message : String(err));
45
+ process.exitCode = 1;
46
+ }
47
+ });
48
+ //# sourceMappingURL=attach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.js","sourceRoot":"","sources":["../../src/commands/attach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,KAAK,UAAU,eAAe,CAAC,SAAiB,EAAE,MAAc,EAAE,KAAa;IAC7E,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAA2B,kBAAkB,MAAM,YAAY,CAAC,CAAC;IAC9F,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,gCAAgC,CAAC;KAC7C,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAC;KAC5C,MAAM,CAAC,YAAY,EAAE,yCAAyC,CAAC;KAC/D,MAAM,CAAC,SAAS,EAAE,yBAAyB,CAAC;KAC5C,MAAM,CAAC,uBAAuB,EAAE,yBAAyB,CAAC;KAC1D,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,IAA+D,EAAE,EAAE;IAChG,IAAI,IAAI,GAAyC,aAAa,CAAC;IAC/D,IAAI,IAAI,CAAC,QAAQ;QAAE,IAAI,GAAG,UAAU,CAAC;IACrC,IAAI,IAAI,CAAC,KAAK;QAAE,IAAI,GAAG,OAAO,CAAC;IAE/B,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,SAAS,CAAC,IAAI,CAAC,sBAAsB,MAAM,KAAK,IAAI,WAAW,CAAC,CAAC;IACjE,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,SAAS,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,SAAS;QACT,MAAM;QACN,KAAK;QACL,IAAI;QACJ,SAAS,EAAE,IAAI,CAAC,OAAO;QACvB,eAAe;KAChB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,SAAS,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ export interface CliConfig {
3
+ server?: string;
4
+ default_project?: string;
5
+ output_format?: string;
6
+ color?: boolean;
7
+ }
8
+ export declare function loadConfig(configPath?: string): CliConfig;
9
+ export declare function saveConfig(config: CliConfig, configPath?: string): void;
10
+ export declare const configCommand: Command;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAKD,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAWzD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAOvE;AAED,eAAO,MAAM,aAAa,SACS,CAAC"}
@@ -0,0 +1,100 @@
1
+ import { Command } from 'commander';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import * as os from 'node:os';
5
+ import { formatter } from '../output/formatter.js';
6
+ const CONFIG_DIR = path.join(os.homedir(), '.config', 'overlord');
7
+ const CONFIG_PATH = path.join(CONFIG_DIR, 'config.json');
8
+ export function loadConfig(configPath) {
9
+ const filePath = configPath ?? CONFIG_PATH;
10
+ try {
11
+ if (!fs.existsSync(filePath)) {
12
+ return {};
13
+ }
14
+ const raw = fs.readFileSync(filePath, 'utf-8');
15
+ return JSON.parse(raw);
16
+ }
17
+ catch {
18
+ return {};
19
+ }
20
+ }
21
+ export function saveConfig(config, configPath) {
22
+ const filePath = configPath ?? CONFIG_PATH;
23
+ const dir = path.dirname(filePath);
24
+ if (!fs.existsSync(dir)) {
25
+ fs.mkdirSync(dir, { recursive: true });
26
+ }
27
+ fs.writeFileSync(filePath, JSON.stringify(config, null, 2), 'utf-8');
28
+ }
29
+ export const configCommand = new Command('config')
30
+ .description('CLI configuration');
31
+ configCommand
32
+ .command('set <key> <value>')
33
+ .description('Set a configuration value (server, default-project)')
34
+ .action((key, value) => {
35
+ const config = loadConfig();
36
+ switch (key) {
37
+ case 'server':
38
+ // Validate URL format
39
+ try {
40
+ new URL(value);
41
+ }
42
+ catch {
43
+ formatter.error(`Invalid server URL: ${value}`);
44
+ process.exitCode = 1;
45
+ return;
46
+ }
47
+ config.server = value;
48
+ break;
49
+ case 'default-project':
50
+ config.default_project = value;
51
+ break;
52
+ case 'output-format':
53
+ config.output_format = value;
54
+ break;
55
+ case 'color':
56
+ config.color = value === 'true';
57
+ break;
58
+ default:
59
+ formatter.error(`Unknown config key: ${key}. Valid keys: server, default-project, output-format, color`);
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+ saveConfig(config);
64
+ formatter.success(`${key} = ${value}`);
65
+ });
66
+ configCommand
67
+ .command('get <key>')
68
+ .description('Get a configuration value')
69
+ .action((key) => {
70
+ const config = loadConfig();
71
+ const configMap = {
72
+ 'server': config.server,
73
+ 'default-project': config.default_project,
74
+ 'output-format': config.output_format,
75
+ 'color': config.color,
76
+ };
77
+ if (!(key in configMap)) {
78
+ formatter.error(`Unknown config key: ${key}`);
79
+ process.exitCode = 1;
80
+ return;
81
+ }
82
+ const value = configMap[key];
83
+ console.log(value !== undefined ? String(value) : '(not set)');
84
+ });
85
+ configCommand
86
+ .command('list')
87
+ .description('List all configuration values')
88
+ .option('--json', 'Output as JSON')
89
+ .action((opts) => {
90
+ if (opts.json)
91
+ formatter.setJsonMode(true);
92
+ const config = loadConfig();
93
+ formatter.detail({
94
+ server: config.server ?? '(not set)',
95
+ 'default-project': config.default_project ?? '(not set)',
96
+ 'output-format': config.output_format ?? 'table',
97
+ color: config.color !== false ? 'true' : 'false',
98
+ });
99
+ });
100
+ //# 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,15 @@
1
+ import { ApiClient } from '../auth/api-client.js';
2
+ /**
3
+ * Get an authenticated API client from saved credentials.
4
+ * Exits with an error if not logged in.
5
+ */
6
+ export declare function getApiClient(): ApiClient;
7
+ /**
8
+ * Get the server URL from saved credentials.
9
+ */
10
+ export declare function getServerUrl(): string;
11
+ /**
12
+ * Get the saved token.
13
+ */
14
+ export declare function getToken(): string;
15
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/commands/helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;;GAGG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAUxC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAUrC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CAUjC"}
@@ -0,0 +1,41 @@
1
+ import { TokenStore } from '../auth/token-store.js';
2
+ import { ApiClient } from '../auth/api-client.js';
3
+ import { formatter } from '../output/formatter.js';
4
+ /**
5
+ * Get an authenticated API client from saved credentials.
6
+ * Exits with an error if not logged in.
7
+ */
8
+ export function getApiClient() {
9
+ const store = new TokenStore();
10
+ const creds = store.load();
11
+ if (!creds) {
12
+ formatter.error('Not logged in. Run `ov login` first.');
13
+ process.exit(1);
14
+ }
15
+ return new ApiClient(creds.server, creds.token);
16
+ }
17
+ /**
18
+ * Get the server URL from saved credentials.
19
+ */
20
+ export function getServerUrl() {
21
+ const store = new TokenStore();
22
+ const creds = store.load();
23
+ if (!creds) {
24
+ formatter.error('Not logged in. Run `ov login` first.');
25
+ process.exit(1);
26
+ }
27
+ return creds.server;
28
+ }
29
+ /**
30
+ * Get the saved token.
31
+ */
32
+ export function getToken() {
33
+ const store = new TokenStore();
34
+ const creds = store.load();
35
+ if (!creds) {
36
+ formatter.error('Not logged in. Run `ov login` first.');
37
+ process.exit(1);
38
+ }
39
+ return creds.token;
40
+ }
41
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/commands/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,SAAS,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,SAAS,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,SAAS,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC;AACrB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const loginCommand: Command;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,YAAY,SAqErB,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { Command } from 'commander';
2
+ import * as readline from 'node:readline';
3
+ import { TokenStore } from '../auth/token-store.js';
4
+ import { ApiClient } from '../auth/api-client.js';
5
+ import { formatter } from '../output/formatter.js';
6
+ import { loadConfig } from './config.js';
7
+ export const loginCommand = new Command('login')
8
+ .description('Authenticate with the Overlord server')
9
+ .option('--token <token>', 'Provide token directly (for CI/CD)')
10
+ .option('--force', 'Force re-login even if already authenticated')
11
+ .action(async (opts) => {
12
+ const store = new TokenStore();
13
+ const existing = store.load();
14
+ if (existing && !opts.force && !opts.token) {
15
+ try {
16
+ const client = new ApiClient(existing.server, existing.token);
17
+ const res = await client.get('/api/web/profile');
18
+ if (res.status === 200) {
19
+ formatter.info(`Already logged in as ${res.data.name}. Use --force to re-login.`);
20
+ return;
21
+ }
22
+ }
23
+ catch {
24
+ // Token invalid, proceed with login
25
+ }
26
+ }
27
+ const config = loadConfig();
28
+ let server = config.server;
29
+ if (!server) {
30
+ server = await promptInput('Enter Overlord server URL: ');
31
+ if (!server) {
32
+ formatter.error('Server URL is required.');
33
+ process.exitCode = 1;
34
+ return;
35
+ }
36
+ }
37
+ server = server.replace(/\/+$/, '');
38
+ let token = opts.token;
39
+ if (!token) {
40
+ console.log('');
41
+ console.log(' ┌─────────────────────────────────────────────────────────┐');
42
+ console.log(` │ Open this URL in your browser to create a token: │`);
43
+ console.log(` │ ${server}/settings/tokens`);
44
+ console.log(' └─────────────────────────────────────────────────────────┘');
45
+ console.log('');
46
+ token = await promptInput('Paste your Personal Access Token: ');
47
+ }
48
+ if (!token) {
49
+ formatter.error('Token is required.');
50
+ process.exitCode = 1;
51
+ return;
52
+ }
53
+ // Validate token
54
+ try {
55
+ const client = new ApiClient(server, token);
56
+ const res = await client.get('/api/web/profile');
57
+ if (res.status === 200) {
58
+ store.save(server, token);
59
+ formatter.success(`Logged in as ${res.data.name} (${res.data.role})`);
60
+ }
61
+ else {
62
+ formatter.error('Invalid token, please try again.');
63
+ process.exitCode = 1;
64
+ }
65
+ }
66
+ catch (err) {
67
+ formatter.error(`Login failed: ${err instanceof Error ? err.message : String(err)}`);
68
+ process.exitCode = 1;
69
+ }
70
+ });
71
+ function promptInput(prompt) {
72
+ return new Promise((resolve) => {
73
+ const rl = readline.createInterface({
74
+ input: process.stdin,
75
+ output: process.stderr,
76
+ });
77
+ rl.question(prompt, (answer) => {
78
+ rl.close();
79
+ resolve(answer.trim());
80
+ });
81
+ });
82
+ }
83
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const logoutCommand: Command;
3
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SAatB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { Command } from 'commander';
2
+ import { TokenStore } from '../auth/token-store.js';
3
+ import { formatter } from '../output/formatter.js';
4
+ export const logoutCommand = new Command('logout')
5
+ .description('Clear saved credentials')
6
+ .action(() => {
7
+ const store = new TokenStore();
8
+ const existing = store.load();
9
+ if (!existing) {
10
+ formatter.info('Not currently logged in.');
11
+ return;
12
+ }
13
+ store.clear();
14
+ formatter.success('Logged out successfully.');
15
+ });
16
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE9B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,SAAS,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,SAAS,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const machineCommand: Command;
3
+ //# sourceMappingURL=machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../src/commands/machine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,eAAO,MAAM,cAAc,SACc,CAAC"}