@vectorplane/ctrl-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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +167 -0
  3. package/bin/vp.js +12 -0
  4. package/dist/commands/bootstrap.d.ts +1 -0
  5. package/dist/commands/bootstrap.js +40 -0
  6. package/dist/commands/config.d.ts +1 -0
  7. package/dist/commands/config.js +96 -0
  8. package/dist/commands/context.d.ts +1 -0
  9. package/dist/commands/context.js +46 -0
  10. package/dist/commands/doctor.d.ts +1 -0
  11. package/dist/commands/doctor.js +69 -0
  12. package/dist/commands/event.d.ts +1 -0
  13. package/dist/commands/event.js +65 -0
  14. package/dist/commands/login.d.ts +1 -0
  15. package/dist/commands/login.js +39 -0
  16. package/dist/commands/session.d.ts +1 -0
  17. package/dist/commands/session.js +110 -0
  18. package/dist/commands/status.d.ts +1 -0
  19. package/dist/commands/status.js +46 -0
  20. package/dist/commands/sync.d.ts +1 -0
  21. package/dist/commands/sync.js +108 -0
  22. package/dist/commands/whoami.d.ts +1 -0
  23. package/dist/commands/whoami.js +32 -0
  24. package/dist/commands/workspace.d.ts +1 -0
  25. package/dist/commands/workspace.js +66 -0
  26. package/dist/core/api.d.ts +24 -0
  27. package/dist/core/api.js +190 -0
  28. package/dist/core/auth.d.ts +16 -0
  29. package/dist/core/auth.js +71 -0
  30. package/dist/core/cli.d.ts +9 -0
  31. package/dist/core/cli.js +66 -0
  32. package/dist/core/config.d.ts +31 -0
  33. package/dist/core/config.js +263 -0
  34. package/dist/core/constants.d.ts +22 -0
  35. package/dist/core/constants.js +78 -0
  36. package/dist/core/env.d.ts +2 -0
  37. package/dist/core/env.js +10 -0
  38. package/dist/core/errors.d.ts +18 -0
  39. package/dist/core/errors.js +37 -0
  40. package/dist/core/git.d.ts +2 -0
  41. package/dist/core/git.js +66 -0
  42. package/dist/core/logger.d.ts +8 -0
  43. package/dist/core/logger.js +52 -0
  44. package/dist/core/machine.d.ts +4 -0
  45. package/dist/core/machine.js +87 -0
  46. package/dist/core/queue.d.ts +14 -0
  47. package/dist/core/queue.js +62 -0
  48. package/dist/core/runtime.d.ts +13 -0
  49. package/dist/core/runtime.js +16 -0
  50. package/dist/core/serializer.d.ts +7 -0
  51. package/dist/core/serializer.js +31 -0
  52. package/dist/core/server.d.ts +10 -0
  53. package/dist/core/server.js +84 -0
  54. package/dist/core/session.d.ts +16 -0
  55. package/dist/core/session.js +35 -0
  56. package/dist/core/workspace-binding.d.ts +15 -0
  57. package/dist/core/workspace-binding.js +41 -0
  58. package/dist/core/workspace.d.ts +2 -0
  59. package/dist/core/workspace.js +121 -0
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.js +97 -0
  62. package/dist/types/api.d.ts +61 -0
  63. package/dist/types/api.js +2 -0
  64. package/dist/types/auth.d.ts +36 -0
  65. package/dist/types/auth.js +2 -0
  66. package/dist/types/config.d.ts +58 -0
  67. package/dist/types/config.js +2 -0
  68. package/dist/types/machine.d.ts +49 -0
  69. package/dist/types/machine.js +2 -0
  70. package/dist/types/snapshot.d.ts +15 -0
  71. package/dist/types/snapshot.js +2 -0
  72. package/dist/types/workspace.d.ts +44 -0
  73. package/dist/types/workspace.js +2 -0
  74. package/package.json +61 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 VectorPlane
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # VectorPlane Ctrl CLI
2
+
3
+ `vectorplane-ctrl-cli` é o CLI oficial do ecossistema **VectorPlane**, nome comercial do backend `conductor-edge-ia`.
4
+
5
+ O repositório analisado posiciona o produto como uma control plane de contexto para engenharia com IA: memória remota por workspace, snapshots consolidados, governança, sessões de agentes, jobs e operação edge. Este CLI segue exatamente essa lógica. Ele não é um utilitário genérico de sync; ele é a porta local para autenticação, coleta de contexto da máquina, análise de workspace e envio seguro de snapshots para o plano de controle.
6
+
7
+ ## Relação com `conductor-edge-ia`
8
+
9
+ O backend atual define alguns conceitos centrais que este CLI preserva:
10
+
11
+ - `workspace` como unidade primária de contexto
12
+ - `snapshot` consolidado como envelope principal de estado
13
+ - `agent session` e `clientInstanceId` como base de observabilidade e coordenação
14
+ - `control plane` como camada acima de clientes locais, MCP e REST
15
+ - preocupação explícita com governança, rastreabilidade, serialização consistente e isolamento
16
+
17
+ O `vp` foi desenhado para se encaixar nesse vocabulário e servir como cliente local premium do VectorPlane.
18
+
19
+ ## Evolução planejada
20
+
21
+ O roadmap do CLI foi documentado em [`docs/evolution-phases.md`](./docs/evolution-phases.md), alinhado às fases já visíveis no `conductor-edge-ia`:
22
+
23
+ - `Foundation`
24
+ - `Coordination`
25
+ - `Governed Sync`
26
+ - `Enterprise Control Surface`
27
+
28
+ ## Instalação
29
+
30
+ ```bash
31
+ npm install
32
+ npm run build
33
+ npm install -g .
34
+ ```
35
+
36
+ Instalação via npm público:
37
+
38
+ ```bash
39
+ npm install -g @vectorplane/ctrl-cli
40
+ ```
41
+
42
+ ## Uso local
43
+
44
+ ```bash
45
+ vp login
46
+ vp status
47
+ vp sync
48
+ vp whoami
49
+ vp doctor
50
+ vp workspace current
51
+ ```
52
+
53
+ ## Comandos
54
+
55
+ ### `vp login`
56
+
57
+ - inicia callback local em `http://127.0.0.1:4217/callback`
58
+ - gera `state` seguro
59
+ - abre o navegador para autenticação
60
+ - troca `code` por tokens via API
61
+ - persiste a sessão em `~/.vectorplane/session.json`
62
+
63
+ ### `vp sync`
64
+
65
+ - exige sessão ativa
66
+ - coleta contexto de máquina, runtime, workspace e git
67
+ - gera snapshot estruturado e hash estável
68
+ - faz deduplicação por hash
69
+ - persiste snapshot localmente
70
+ - envia para `POST https://api.vectorplane.io/sync`
71
+ - enfileira localmente quando a API falha
72
+
73
+ ### `vp status`
74
+
75
+ - informa estado da sessão local
76
+ - mostra perfil ativo
77
+ - mostra workspace ativo e binding local
78
+ - mostra diretório atual
79
+ - mostra machine ID persistido
80
+ - mostra branch git, fila local, sessão de agente e última sincronização quando disponíveis
81
+
82
+ ### Comandos adicionais já implementados
83
+
84
+ - `vp whoami`
85
+ - consulta a identidade atual via API
86
+ - `vp doctor`
87
+ - verifica diretório local, git, health, ready e autenticação
88
+ - `vp config`
89
+ - lista, cria e troca perfis
90
+ - lê e altera configurações principais
91
+ - `vp workspace`
92
+ - consulta o workspace atual
93
+ - faz binding manual
94
+ - tenta resolver por repositório remoto
95
+ - `vp session`
96
+ - faz check-in, heartbeat e check-out de sessão de agente
97
+ - `vp context`
98
+ - carrega `context`, `snapshot` ou `delivery-context`
99
+ - `vp bootstrap`
100
+ - lê `agent-setup` e guidance de bootstrap do workspace
101
+ - `vp event send`
102
+ - envia ou enfileira eventos operacionais
103
+
104
+ ## Persistência local
105
+
106
+ Arquivos usados:
107
+
108
+ - `~/.vectorplane/config.json`
109
+ - `~/.vectorplane/session.json`
110
+ - `~/.vectorplane/device.json`
111
+ - `~/.vectorplane/state.json`
112
+ - `~/.vectorplane/queue.json`
113
+ - `~/.vectorplane/workspaces.json`
114
+ - `~/.vectorplane/snapshots/`
115
+
116
+ ## Segurança
117
+
118
+ - tokens nunca são impressos no terminal
119
+ - tokens nunca são enviados por query string
120
+ - o callback aceita apenas `code` e `state`
121
+ - `state` é validado obrigatoriamente
122
+ - logs evitam payloads sensíveis e mascaram chaves delicadas
123
+ - remotes git são sanitizados antes de entrarem no snapshot
124
+
125
+ ## Desenvolvimento
126
+
127
+ ```bash
128
+ npm run check
129
+ npm run build
130
+ npm start -- status
131
+ ```
132
+
133
+ ## Publicação npm
134
+
135
+ O pacote foi preparado para publicação pública como `@vectorplane/ctrl-cli`.
136
+
137
+ Checklist local:
138
+
139
+ ```bash
140
+ npm run release:check
141
+ ```
142
+
143
+ Publicação:
144
+
145
+ ```bash
146
+ npm login
147
+ npm publish --access public
148
+ ```
149
+
150
+ Notas de empacotamento:
151
+
152
+ - o tarball publica apenas `bin/`, `dist/`, `README.md` e `LICENSE`
153
+ - `src/`, `docs/`, `.git/`, `node_modules/`, `package-lock.json` e arquivos locais não entram no pacote
154
+ - tokens, sessão local e dados de `~/.vectorplane/` não fazem parte do publish
155
+
156
+ ## Integração aplicada
157
+
158
+ O fluxo web e backend do CLI foi alinhado ao ecossistema real:
159
+
160
+ - dashboard com rota `/cli/login`
161
+ - emissão autenticada de código por `POST /auth/cli/code`
162
+ - troca de token por `POST /cli/token/exchange`
163
+ - refresh por `POST /cli/token/refresh`
164
+ - resolução e leitura de workspace via rotas `cli/workspace/*`
165
+ - `POST /sync` e `POST /events` no mesmo envelope oficial do worker
166
+
167
+ O cliente agora faz unwrapping do envelope `{ success, data, requestId }` usado pelo `conductor-edge-ia`, em vez de assumir respostas cruas.
package/bin/vp.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ import("../dist/index.js")
4
+ .then(({ runCli }) => runCli(process.argv.slice(2)))
5
+ .then((exitCode) => {
6
+ process.exitCode = typeof exitCode === "number" ? exitCode : 0;
7
+ })
8
+ .catch((error) => {
9
+ const message = error instanceof Error ? error.message : String(error);
10
+ console.error(`VectorPlane: ${message}`);
11
+ process.exitCode = 1;
12
+ });
@@ -0,0 +1 @@
1
+ export declare function runBootstrapCommand(cliVersion: string, args: string[]): Promise<number>;
@@ -0,0 +1,40 @@
1
+ import { getStringOption, parseArgs } from "../core/cli.js";
2
+ import { ensureSessionAvailable, getProfileState } from "../core/config.js";
3
+ import { collectGitContext } from "../core/git.js";
4
+ import { collectMachineContext, collectRuntimeContext } from "../core/machine.js";
5
+ import { loadRuntimeStatus } from "../core/runtime.js";
6
+ import { ensureFreshSession, resolveWorkspaceSlug } from "../core/session.js";
7
+ import { VectorPlaneApiClient } from "../core/api.js";
8
+ import { getBoundWorkspace, resolveWorkspaceRoot } from "../core/workspace-binding.js";
9
+ import { ValidationError } from "../core/errors.js";
10
+ export async function runBootstrapCommand(cliVersion, args) {
11
+ const parsed = parseArgs(args);
12
+ const runtime = await loadRuntimeStatus();
13
+ const session = await ensureSessionAvailable(runtime.profile.name);
14
+ const [git, machine, runtimeContext] = await Promise.all([
15
+ collectGitContext(process.cwd()),
16
+ collectMachineContext(runtime.device, runtime.config),
17
+ collectRuntimeContext(cliVersion, "bootstrap", process.argv.slice(2)),
18
+ ]);
19
+ const apiClient = new VectorPlaneApiClient(runtime.profile.apiBaseUrl, runtime.config.requestTimeoutMs, runtime.logger);
20
+ const freshSession = await ensureFreshSession({
21
+ profileName: runtime.profile.name,
22
+ session,
23
+ machine,
24
+ runtime: runtimeContext,
25
+ device: runtime.device,
26
+ apiClient,
27
+ logger: runtime.logger,
28
+ });
29
+ const rootPath = resolveWorkspaceRoot(process.cwd(), git);
30
+ const boundWorkspace = await getBoundWorkspace(rootPath);
31
+ const profileState = getProfileState(runtime.state, runtime.profile.name);
32
+ const workspace = resolveWorkspaceSlug(runtime.profile, freshSession, getStringOption(parsed, "workspace"), boundWorkspace, profileState.lastWorkspace);
33
+ if (!workspace) {
34
+ throw new ValidationError("Nenhum workspace resolvido para bootstrap.");
35
+ }
36
+ const payload = await apiClient.getAgentSetup(freshSession.accessToken, workspace);
37
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
38
+ return 0;
39
+ }
40
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ export declare function runConfigCommand(args: string[]): Promise<number>;
@@ -0,0 +1,96 @@
1
+ import { getStringOption, parseArgs, requirePositional } from "../core/cli.js";
2
+ import { getActiveProfile, loadConfig, saveConfig, setActiveProfile, upsertProfile } from "../core/config.js";
3
+ import { ValidationError } from "../core/errors.js";
4
+ function setProfileField(profile, key, value) {
5
+ switch (key) {
6
+ case "apiBaseUrl":
7
+ return { ...profile, apiBaseUrl: value };
8
+ case "appBaseUrl":
9
+ return { ...profile, appBaseUrl: value };
10
+ case "workspace":
11
+ return { ...profile, workspace: value };
12
+ case "orgId":
13
+ return { ...profile, orgId: value };
14
+ case "environment":
15
+ return { ...profile, environment: value };
16
+ default:
17
+ throw new ValidationError(`Campo de perfil não suportado: ${key}`);
18
+ }
19
+ }
20
+ export async function runConfigCommand(args) {
21
+ const parsed = parseArgs(args);
22
+ const [subcommand, ...rest] = parsed.positionals;
23
+ const config = await loadConfig();
24
+ if (!subcommand) {
25
+ process.stdout.write(JSON.stringify(config, null, 2));
26
+ process.stdout.write("\n");
27
+ return 0;
28
+ }
29
+ if (subcommand === "profile") {
30
+ const action = rest[0];
31
+ if (!action || action === "list") {
32
+ for (const profile of Object.values(config.profiles)) {
33
+ process.stdout.write(`${profile.name}${config.activeProfile === profile.name ? " *" : ""}\n`);
34
+ }
35
+ return 0;
36
+ }
37
+ if (action === "create") {
38
+ const name = rest[1];
39
+ if (!name) {
40
+ throw new ValidationError("Informe o nome do perfil.");
41
+ }
42
+ await upsertProfile(name, { name });
43
+ process.stdout.write(`Perfil criado: ${name}\n`);
44
+ return 0;
45
+ }
46
+ if (action === "use") {
47
+ const name = rest[1];
48
+ if (!name) {
49
+ throw new ValidationError("Informe o nome do perfil.");
50
+ }
51
+ await setActiveProfile(name);
52
+ process.stdout.write(`Perfil ativo: ${name}\n`);
53
+ return 0;
54
+ }
55
+ }
56
+ if (subcommand === "get") {
57
+ const key = requirePositional({ ...parsed, positionals: rest }, 0, "Informe a chave a ser lida.");
58
+ const active = getActiveProfile(config);
59
+ switch (key) {
60
+ case "debug":
61
+ process.stdout.write(String(config.debug));
62
+ break;
63
+ case "telemetryEnabled":
64
+ process.stdout.write(String(config.telemetryEnabled));
65
+ break;
66
+ default:
67
+ process.stdout.write(String(active[key] ?? ""));
68
+ break;
69
+ }
70
+ process.stdout.write("\n");
71
+ return 0;
72
+ }
73
+ if (subcommand === "set") {
74
+ const key = rest[0];
75
+ const value = rest[1];
76
+ if (!key || value === undefined) {
77
+ throw new ValidationError("Uso: vp config set <chave> <valor>");
78
+ }
79
+ if (key === "debug" || key === "telemetryEnabled") {
80
+ const next = { ...config, [key]: ["1", "true", "yes", "on"].includes(value.toLowerCase()) };
81
+ await saveConfig(next);
82
+ process.stdout.write(`Configuração atualizada: ${key}\n`);
83
+ return 0;
84
+ }
85
+ const profileName = getStringOption(parsed, "profile") ?? config.activeProfile;
86
+ const current = config.profiles[profileName];
87
+ if (!current) {
88
+ throw new ValidationError(`Perfil ${profileName} não existe.`);
89
+ }
90
+ await upsertProfile(profileName, setProfileField(current, key, value));
91
+ process.stdout.write(`Perfil ${profileName} atualizado: ${key}\n`);
92
+ return 0;
93
+ }
94
+ throw new ValidationError("Subcomando de config não suportado.");
95
+ }
96
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ export declare function runContextCommand(cliVersion: string, args: string[]): Promise<number>;
@@ -0,0 +1,46 @@
1
+ import { getBooleanOption, getStringOption, parseArgs } from "../core/cli.js";
2
+ import { ensureSessionAvailable, getProfileState } from "../core/config.js";
3
+ import { collectGitContext } from "../core/git.js";
4
+ import { collectMachineContext, collectRuntimeContext } from "../core/machine.js";
5
+ import { loadRuntimeStatus } from "../core/runtime.js";
6
+ import { ensureFreshSession, resolveWorkspaceSlug } from "../core/session.js";
7
+ import { VectorPlaneApiClient } from "../core/api.js";
8
+ import { getBoundWorkspace, resolveWorkspaceRoot } from "../core/workspace-binding.js";
9
+ import { ValidationError } from "../core/errors.js";
10
+ export async function runContextCommand(cliVersion, args) {
11
+ const parsed = parseArgs(args);
12
+ const delivery = getBooleanOption(parsed, "delivery");
13
+ const snapshot = getBooleanOption(parsed, "snapshot");
14
+ const runtime = await loadRuntimeStatus();
15
+ const session = await ensureSessionAvailable(runtime.profile.name);
16
+ const [git, machine, runtimeContext] = await Promise.all([
17
+ collectGitContext(process.cwd()),
18
+ collectMachineContext(runtime.device, runtime.config),
19
+ collectRuntimeContext(cliVersion, "context", process.argv.slice(2)),
20
+ ]);
21
+ const apiClient = new VectorPlaneApiClient(runtime.profile.apiBaseUrl, runtime.config.requestTimeoutMs, runtime.logger);
22
+ const freshSession = await ensureFreshSession({
23
+ profileName: runtime.profile.name,
24
+ session,
25
+ machine,
26
+ runtime: runtimeContext,
27
+ device: runtime.device,
28
+ apiClient,
29
+ logger: runtime.logger,
30
+ });
31
+ const rootPath = resolveWorkspaceRoot(process.cwd(), git);
32
+ const boundWorkspace = await getBoundWorkspace(rootPath);
33
+ const profileState = getProfileState(runtime.state, runtime.profile.name);
34
+ const workspace = resolveWorkspaceSlug(runtime.profile, freshSession, getStringOption(parsed, "workspace"), boundWorkspace, profileState.lastWorkspace);
35
+ if (!workspace) {
36
+ throw new ValidationError("Nenhum workspace resolvido para carregar contexto.");
37
+ }
38
+ const payload = delivery
39
+ ? await apiClient.getWorkspaceDeliveryContext(freshSession.accessToken, workspace)
40
+ : snapshot
41
+ ? await apiClient.getWorkspaceSnapshot(freshSession.accessToken, workspace)
42
+ : await apiClient.getWorkspaceContext(freshSession.accessToken, workspace);
43
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
44
+ return 0;
45
+ }
46
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ export declare function runDoctorCommand(cliVersion: string): Promise<number>;
@@ -0,0 +1,69 @@
1
+ import { access } from "node:fs/promises";
2
+ import { constants as fsConstants } from "node:fs";
3
+ import { configDirectoryExists, ensureSessionAvailable, getConfigDirectoryPath } from "../core/config.js";
4
+ import { collectGitContext } from "../core/git.js";
5
+ import { collectMachineContext, collectRuntimeContext } from "../core/machine.js";
6
+ import { loadRuntimeStatus } from "../core/runtime.js";
7
+ import { ensureFreshSession } from "../core/session.js";
8
+ import { VectorPlaneApiClient } from "../core/api.js";
9
+ async function writable(filePath) {
10
+ try {
11
+ await access(filePath, fsConstants.W_OK);
12
+ return true;
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ }
18
+ function printCheck(label, ok, details) {
19
+ process.stdout.write(`${ok ? "OK" : "FAIL"} ${label}: ${details}\n`);
20
+ }
21
+ export async function runDoctorCommand(cliVersion) {
22
+ const runtime = await loadRuntimeStatus();
23
+ const configDirectory = await getConfigDirectoryPath();
24
+ const [hasConfigDir, git, canWriteConfig] = await Promise.all([
25
+ configDirectoryExists(),
26
+ collectGitContext(process.cwd()),
27
+ writable(configDirectory),
28
+ ]);
29
+ printCheck("config_dir", hasConfigDir, configDirectory);
30
+ printCheck("config_dir_writable", canWriteConfig, canWriteConfig ? "gravável" : "sem permissão de escrita");
31
+ printCheck("git", git.isRepository, git.isRepository ? (git.rootPath ?? process.cwd()) : "repositório não detectado");
32
+ printCheck("node", true, process.version);
33
+ const apiClient = new VectorPlaneApiClient(runtime.profile.apiBaseUrl, runtime.config.requestTimeoutMs, runtime.logger);
34
+ try {
35
+ const health = await apiClient.getHealth();
36
+ printCheck("api_health", true, JSON.stringify(health));
37
+ }
38
+ catch (error) {
39
+ printCheck("api_health", false, error instanceof Error ? error.message : String(error));
40
+ }
41
+ try {
42
+ const ready = await apiClient.getReady();
43
+ printCheck("api_ready", true, JSON.stringify(ready));
44
+ }
45
+ catch (error) {
46
+ printCheck("api_ready", false, error instanceof Error ? error.message : String(error));
47
+ }
48
+ try {
49
+ const session = await ensureSessionAvailable(runtime.profile.name);
50
+ const machine = await collectMachineContext(runtime.device, runtime.config);
51
+ const runtimeContext = await collectRuntimeContext(cliVersion, "doctor", process.argv.slice(2));
52
+ const freshSession = await ensureFreshSession({
53
+ profileName: runtime.profile.name,
54
+ session,
55
+ machine,
56
+ runtime: runtimeContext,
57
+ device: runtime.device,
58
+ apiClient,
59
+ logger: runtime.logger,
60
+ });
61
+ const me = await apiClient.getCurrentUser(freshSession.accessToken);
62
+ printCheck("auth_me", true, `${me.type}:${me.id}`);
63
+ }
64
+ catch (error) {
65
+ printCheck("auth_me", false, error instanceof Error ? error.message : String(error));
66
+ }
67
+ return 0;
68
+ }
69
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ export declare function runEventCommand(cliVersion: string, args: string[]): Promise<number>;
@@ -0,0 +1,65 @@
1
+ import { getStringOption, parseArgs, parseJsonOption, requirePositional } from "../core/cli.js";
2
+ import { ensureSessionAvailable, getProfileState } from "../core/config.js";
3
+ import { collectGitContext } from "../core/git.js";
4
+ import { collectMachineContext, collectRuntimeContext } from "../core/machine.js";
5
+ import { loadRuntimeStatus } from "../core/runtime.js";
6
+ import { ensureFreshSession, resolveWorkspaceSlug } from "../core/session.js";
7
+ import { VectorPlaneApiClient } from "../core/api.js";
8
+ import { queueEvent } from "../core/queue.js";
9
+ import { getBoundWorkspace, resolveWorkspaceRoot } from "../core/workspace-binding.js";
10
+ import { ValidationError } from "../core/errors.js";
11
+ export async function runEventCommand(cliVersion, args) {
12
+ const parsed = parseArgs(args);
13
+ const [subcommand] = parsed.positionals;
14
+ if (!subcommand || subcommand !== "send") {
15
+ throw new ValidationError("Uso: vp event send <nome> [--payload '{...}']");
16
+ }
17
+ const eventName = requirePositional(parsed, 1, "Informe o nome do evento.");
18
+ const payloadObject = parseJsonOption(getStringOption(parsed, "payload"));
19
+ const runtime = await loadRuntimeStatus();
20
+ const session = await ensureSessionAvailable(runtime.profile.name);
21
+ const [git, machine, runtimeContext] = await Promise.all([
22
+ collectGitContext(process.cwd()),
23
+ collectMachineContext(runtime.device, runtime.config),
24
+ collectRuntimeContext(cliVersion, "event", process.argv.slice(2)),
25
+ ]);
26
+ const apiClient = new VectorPlaneApiClient(runtime.profile.apiBaseUrl, runtime.config.requestTimeoutMs, runtime.logger);
27
+ const freshSession = await ensureFreshSession({
28
+ profileName: runtime.profile.name,
29
+ session,
30
+ machine,
31
+ runtime: runtimeContext,
32
+ device: runtime.device,
33
+ apiClient,
34
+ logger: runtime.logger,
35
+ });
36
+ const rootPath = resolveWorkspaceRoot(process.cwd(), git);
37
+ const boundWorkspace = await getBoundWorkspace(rootPath);
38
+ const profileState = getProfileState(runtime.state, runtime.profile.name);
39
+ const workspace = resolveWorkspaceSlug(runtime.profile, freshSession, getStringOption(parsed, "workspace"), boundWorkspace, profileState.lastWorkspace);
40
+ if (!workspace) {
41
+ throw new ValidationError("Nenhum workspace resolvido para o evento.");
42
+ }
43
+ const eventPayload = {
44
+ workspace,
45
+ event: eventName,
46
+ payload: {
47
+ ...payloadObject,
48
+ branch: git.branch,
49
+ commitHash: git.commitHash,
50
+ rootPath,
51
+ },
52
+ sent_at: new Date().toISOString(),
53
+ };
54
+ try {
55
+ await apiClient.sendEvent(freshSession.accessToken, eventPayload);
56
+ runtime.logger.success("evento enviado.");
57
+ return 0;
58
+ }
59
+ catch (error) {
60
+ await queueEvent(runtime.profile.name, eventPayload, error);
61
+ runtime.logger.warn("API indisponível no momento. O evento foi enfileirado localmente.");
62
+ return 0;
63
+ }
64
+ }
65
+ //# sourceMappingURL=event.js.map
@@ -0,0 +1 @@
1
+ export declare function runLoginCommand(cliVersion: string, args: string[]): Promise<number>;
@@ -0,0 +1,39 @@
1
+ import { getStringOption, parseArgs } from "../core/cli.js";
2
+ import { runLoginFlow } from "../core/auth.js";
3
+ import { saveSession, setActiveProfile, updateProfileState, upsertProfile } from "../core/config.js";
4
+ import { collectMachineContext, collectRuntimeContext } from "../core/machine.js";
5
+ import { loadRuntimeStatus } from "../core/runtime.js";
6
+ import { VectorPlaneApiClient } from "../core/api.js";
7
+ export async function runLoginCommand(cliVersion, args) {
8
+ const parsed = parseArgs(args);
9
+ const requestedProfile = getStringOption(parsed, "profile");
10
+ if (requestedProfile) {
11
+ await upsertProfile(requestedProfile, { name: requestedProfile });
12
+ await setActiveProfile(requestedProfile);
13
+ }
14
+ const runtime = await loadRuntimeStatus();
15
+ const machine = await collectMachineContext(runtime.device, runtime.config);
16
+ const runtimeContext = await collectRuntimeContext(cliVersion, "login", process.argv.slice(2));
17
+ const apiClient = new VectorPlaneApiClient(runtime.profile.apiBaseUrl, runtime.config.requestTimeoutMs, runtime.logger);
18
+ const session = await runLoginFlow({
19
+ config: runtime.config,
20
+ profile: runtime.profile,
21
+ machine,
22
+ runtime: runtimeContext,
23
+ device: runtime.device,
24
+ apiClient,
25
+ logger: runtime.logger,
26
+ });
27
+ await saveSession(session, runtime.profile.name);
28
+ await upsertProfile(runtime.profile.name, { workspace: session.workspace });
29
+ await updateProfileState(runtime.profile.name, {
30
+ lastCommand: "login",
31
+ lastWorkspace: session.workspace,
32
+ lastError: null,
33
+ });
34
+ runtime.logger.success("login realizado com sucesso.");
35
+ process.stdout.write(`Perfil: ${runtime.profile.name}\n`);
36
+ process.stdout.write(`Workspace ativo: ${session.workspace}\n`);
37
+ return 0;
38
+ }
39
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ export declare function runSessionCommand(cliVersion: string, args: string[]): Promise<number>;