@vectorplane/ctrl-cli 0.1.10 → 0.1.12

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 CHANGED
@@ -13,10 +13,19 @@ npm install -g @vectorplane/ctrl-cli
13
13
  ## Uso
14
14
 
15
15
  ```bash
16
+ vp init
16
17
  vp login
17
18
  vp logout
18
19
  vp status
19
20
  vp sync
21
+ vp task templates
22
+ vp task run --title "Entrega X" --intention "Implementar fluxo Y"
23
+ vp task run --template code-review --title "Review auth" --intention "Revisar risco e cobertura do fluxo de auth"
24
+ vp task claim --capability qa.test
25
+ vp task execute <task-id> --step <step-id>
26
+ vp task daemon --capability qa.test
27
+ vp context --search "decisões sobre autenticação"
28
+ vp context --delivery --search "fluxo de login" --type decisions
20
29
  vp context --workspace <workspace> --delivery
21
30
  vp session check-in --workspace <workspace> --agent codex --type codex --client openai-codex --feature feature-key --task task-key --owning-path "src/core,src/ui" --need "api-contract" --provide "implementation" --status "starting implementation"
22
31
  vp draft create --type progress --title "Entrega concluída" --content "Resumo da mudança"
@@ -24,6 +33,16 @@ vp draft create --type progress --title "Entrega concluída" --content "Resumo d
24
33
 
25
34
  ## Comandos
26
35
 
36
+ ### `vp init`
37
+
38
+ - autentica localmente se ainda não houver sessão
39
+ - resolve e associa o workspace atual a partir do `git remote`, somente quando houver correspondência com um workspace que o usuário pode acessar
40
+ - detecta o agente local automaticamente, pede confirmação se houver ambiguidade e aceita `--agent`
41
+ - baixa o template oficial do backend
42
+ - grava o arquivo local e adiciona a entrada no `.gitignore`
43
+ - aceita `--force` para sobrescrever template existente
44
+ - durante execução, se outro agente passar a operar no workspace e a detecção for confiável, o setup local é reconciliado automaticamente
45
+
27
46
  ### `vp login`
28
47
 
29
48
  - abre o navegador para autenticação
@@ -31,6 +50,7 @@ vp draft create --type progress --title "Entrega concluída" --content "Resumo d
31
50
  - salva a sessão localmente
32
51
  - suporta `--no-browser` e `--manual`
33
52
  - em ambientes remotos ou isolados, o loopback local pode exigir um fluxo alternativo
53
+ - a URL web do login é emitida pelo control plane; o domínio do app não deve ser hardcoded em automações externas
34
54
 
35
55
  ### `vp logout`
36
56
 
@@ -48,6 +68,25 @@ vp draft create --type progress --title "Entrega concluída" --content "Resumo d
48
68
  - mostra o estado da sessão local
49
69
  - exibe workspace ativo, diretório atual e última sincronização
50
70
 
71
+ ### `vp task`
72
+
73
+ - cria tasks no orchestrator do workspace
74
+ - lista templates disponíveis com `vp task templates`
75
+ - aceita `--template <slug>` para herdar capabilities e paths padrão do backend
76
+ - lista e inspeciona tasks existentes
77
+ - faz claim explícito de steps `pending_claim` atribuídos a agentes CLI
78
+ - executa steps locais via `metadata.execution.command`
79
+ - suporta loop controlado com `vp task daemon --capability ...`
80
+ - registra delegação de step
81
+ - envia callback de execução por step para concluir a pipeline
82
+ - lê handoff operacional por task
83
+ - consulta observabilidade por task ou workspace
84
+ - consulta health do workspace ligado às tasks
85
+ - para automação local real, o agente de registry deve ter `metadata.execution` com:
86
+ - `type: "command"`
87
+ - `command: "npm"` ou equivalente
88
+ - `args`, `cwd` e `env` opcionais
89
+
51
90
  ### `vp draft`
52
91
 
53
92
  - cria drafts editoriais ligados ao workspace atual
@@ -76,12 +115,16 @@ vp draft create --type progress --title "Entrega concluída" --content "Resumo d
76
115
  - gerencia sessões de agente
77
116
  - `vp context`
78
117
  - carrega contexto remoto do workspace
118
+ - suporta `--search "QUERY"` para busca semântica na memória
119
+ - com `--delivery --search`, retorna delivery context com fragmentos semânticos relevantes
79
120
  - `vp bootstrap`
80
121
  - obtém instruções de setup do workspace
81
122
  - `vp event send`
82
123
  - envia eventos operacionais
83
124
  - `vp draft`
84
125
  - envia e consulta drafts editoriais do workspace
126
+ - `vp task`
127
+ - opera tasks do autonomous control plane
85
128
 
86
129
  ## Persistência local
87
130
 
@@ -7,10 +7,12 @@ import { ensureFreshSession, resolveWorkspaceSlug } from "../core/session.js";
7
7
  import { VectorPlaneApiClient } from "../core/api.js";
8
8
  import { getBoundWorkspace, resolveWorkspaceRoot } from "../core/workspace-binding.js";
9
9
  import { ValidationError } from "../core/errors.js";
10
+ import { ensureRuntimeAgentSetup } from "../core/runtime-agent-setup.js";
10
11
  export async function runContextCommand(cliVersion, args) {
11
12
  const parsed = parseArgs(args);
12
13
  const delivery = getBooleanOption(parsed, "delivery");
13
14
  const snapshot = getBooleanOption(parsed, "snapshot");
15
+ const search = getStringOption(parsed, "search")?.trim();
14
16
  const runtime = await loadRuntimeStatus();
15
17
  const session = await ensureSessionAvailable(runtime.profile.name);
16
18
  const [git, machine, runtimeContext] = await Promise.all([
@@ -35,11 +37,26 @@ export async function runContextCommand(cliVersion, args) {
35
37
  if (!workspace) {
36
38
  throw new ValidationError("Nenhum workspace resolvido para carregar contexto.");
37
39
  }
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);
40
+ await ensureRuntimeAgentSetup({ rootPath, workspace, git, session: freshSession, apiClient, logger: runtime.logger });
41
+ const payload = search
42
+ ? (delivery
43
+ ? await apiClient.getWorkspaceDeliveryContextSemantic(freshSession.accessToken, workspace, {
44
+ query: search,
45
+ type: getStringOption(parsed, "type")?.trim(),
46
+ authority: getStringOption(parsed, "authority")?.trim(),
47
+ limit: Number(getStringOption(parsed, "limit") ?? "0") || undefined,
48
+ })
49
+ : await apiClient.searchWorkspaceMemory(freshSession.accessToken, workspace, {
50
+ query: search,
51
+ type: getStringOption(parsed, "type")?.trim(),
52
+ authority: getStringOption(parsed, "authority")?.trim(),
53
+ limit: Number(getStringOption(parsed, "limit") ?? "0") || undefined,
54
+ }))
55
+ : delivery
56
+ ? await apiClient.getWorkspaceDeliveryContext(freshSession.accessToken, workspace)
57
+ : snapshot
58
+ ? await apiClient.getWorkspaceSnapshot(freshSession.accessToken, workspace)
59
+ : await apiClient.getWorkspaceContext(freshSession.accessToken, workspace);
43
60
  process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
44
61
  return 0;
45
62
  }
@@ -0,0 +1 @@
1
+ export declare function runInitCommand(cliVersion: string, args: string[]): Promise<number>;
@@ -0,0 +1,35 @@
1
+ import { getBooleanOption, getStringOption, parseArgs } from "../core/cli.js";
2
+ import { runLoginCommand } from "./login.js";
3
+ import { loadRuntimeStatus } from "../core/runtime.js";
4
+ import { buildInitLoginArgs, runInitWorkspaceUseCase } from "../core/init-workspace.js";
5
+ export async function runInitCommand(cliVersion, args) {
6
+ const parsed = parseArgs(args);
7
+ const force = getBooleanOption(parsed, "force");
8
+ const requestedAgent = getStringOption(parsed, "agent");
9
+ const explicitWorkspace = getStringOption(parsed, "workspace");
10
+ const requestedProfile = getStringOption(parsed, "profile");
11
+ const loginArgs = await buildInitLoginArgs({
12
+ manual: getBooleanOption(parsed, "manual"),
13
+ noBrowser: getBooleanOption(parsed, "no-browser"),
14
+ profile: requestedProfile ?? undefined,
15
+ });
16
+ const runtime = await loadRuntimeStatus();
17
+ const result = await runInitWorkspaceUseCase({
18
+ cliVersion,
19
+ commandArgs: process.argv.slice(2),
20
+ runtime,
21
+ force,
22
+ explicitWorkspace: explicitWorkspace ?? undefined,
23
+ requestedAgent,
24
+ ensureLoggedIn: async () => {
25
+ await runLoginCommand(cliVersion, loginArgs);
26
+ },
27
+ });
28
+ runtime.logger.success("workspace inicializado.");
29
+ process.stdout.write(`Workspace: ${result.workspace}\n`);
30
+ process.stdout.write(`Agente configurado: ${result.agent}\n`);
31
+ process.stdout.write(`Confiança da detecção: ${result.confidence}\n`);
32
+ process.stdout.write(`Template: ${result.templatePath} (${result.fileStatus})\n`);
33
+ return 0;
34
+ }
35
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ export declare function runRegistryCommand(args: string[]): Promise<number>;
@@ -0,0 +1,116 @@
1
+ import { getBooleanOption, getStringListOption, getStringOption, parseArgs, parseJsonOption, requirePositional } from "../core/cli.js";
2
+ import { ensureSessionAvailable } from "../core/config.js";
3
+ import { loadRuntimeStatus } from "../core/runtime.js";
4
+ import { VectorPlaneApiClient } from "../core/api.js";
5
+ import { ValidationError } from "../core/errors.js";
6
+ function printJsonIfRequested(parsed, payload) {
7
+ if (!getBooleanOption(parsed, "json")) {
8
+ return false;
9
+ }
10
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
11
+ return true;
12
+ }
13
+ function printAgent(agent) {
14
+ process.stdout.write(`Agent: ${agent.id}\n`);
15
+ process.stdout.write(`Nome: ${agent.name}\n`);
16
+ process.stdout.write(`Runtime: ${agent.runtimeType}\n`);
17
+ process.stdout.write(`Provider: ${agent.provider}\n`);
18
+ process.stdout.write(`Model: ${agent.model}\n`);
19
+ process.stdout.write(`Status: ${agent.status}\n`);
20
+ process.stdout.write(`Reliability: ${String(agent.reliabilityScore)}\n`);
21
+ process.stdout.write(`Capabilities: ${agent.capabilities.join(", ")}\n`);
22
+ if (agent.metadata && Object.keys(agent.metadata).length > 0) {
23
+ process.stdout.write(`Metadata: ${JSON.stringify(agent.metadata)}\n`);
24
+ }
25
+ }
26
+ async function resolveRegistryContext() {
27
+ const runtime = await loadRuntimeStatus();
28
+ const session = await ensureSessionAvailable(runtime.profile.name);
29
+ const apiClient = new VectorPlaneApiClient(runtime.profile.apiBaseUrl, runtime.config.requestTimeoutMs, runtime.logger);
30
+ return { runtime, session, apiClient };
31
+ }
32
+ export async function runRegistryCommand(args) {
33
+ const parsed = parseArgs(args);
34
+ const subcommand = requirePositional(parsed, 0, "Uso: vp registry <list|register|update|deactivate> [...]");
35
+ const { runtime, session, apiClient } = await resolveRegistryContext();
36
+ if (subcommand === "list") {
37
+ const agents = await apiClient.listAgentRegistry(session.accessToken);
38
+ if (printJsonIfRequested(parsed, agents))
39
+ return 0;
40
+ if (agents.length === 0) {
41
+ process.stdout.write("VectorPlane: nenhum agente registrado.\n");
42
+ return 0;
43
+ }
44
+ for (const agent of agents) {
45
+ process.stdout.write(`${agent.id} | ${agent.status} | ${agent.runtimeType} | ${agent.provider}/${agent.model} | ${agent.name}\n`);
46
+ }
47
+ return 0;
48
+ }
49
+ if (subcommand === "register") {
50
+ const name = getStringOption(parsed, "name")?.trim();
51
+ const runtimeType = getStringOption(parsed, "runtime")?.trim();
52
+ const provider = getStringOption(parsed, "provider")?.trim();
53
+ const model = getStringOption(parsed, "model")?.trim();
54
+ if (!name || !runtimeType || !provider || !model) {
55
+ throw new ValidationError("Informe `--name`, `--runtime`, `--provider` e `--model`.");
56
+ }
57
+ const agent = await apiClient.createRegistryAgent(session.accessToken, {
58
+ orgId: getStringOption(parsed, "org-id")?.trim() || undefined,
59
+ name,
60
+ runtimeType,
61
+ provider,
62
+ model,
63
+ capabilities: getStringListOption(parsed, "capabilities"),
64
+ costProfile: getStringOption(parsed, "cost")?.trim() || "standard",
65
+ latencyProfile: getStringOption(parsed, "latency")?.trim() || "standard",
66
+ reliabilityScore: Number(getStringOption(parsed, "reliability") ?? "0.9"),
67
+ status: getStringOption(parsed, "status")?.trim() || "active",
68
+ metadata: parseJsonOption(getStringOption(parsed, "metadata")),
69
+ });
70
+ runtime.logger.success("agente registrado.");
71
+ if (!printJsonIfRequested(parsed, agent)) {
72
+ printAgent(agent);
73
+ }
74
+ return 0;
75
+ }
76
+ if (subcommand === "update") {
77
+ const agentId = requirePositional(parsed, 1, "Informe o identificador do agente.");
78
+ const payload = {};
79
+ if (parsed.options.name !== undefined)
80
+ payload.name = getStringOption(parsed, "name")?.trim();
81
+ if (parsed.options.provider !== undefined)
82
+ payload.provider = getStringOption(parsed, "provider")?.trim();
83
+ if (parsed.options.model !== undefined)
84
+ payload.model = getStringOption(parsed, "model")?.trim();
85
+ if (parsed.options.capabilities !== undefined)
86
+ payload.capabilities = getStringListOption(parsed, "capabilities");
87
+ if (parsed.options.cost !== undefined)
88
+ payload.costProfile = getStringOption(parsed, "cost")?.trim();
89
+ if (parsed.options.latency !== undefined)
90
+ payload.latencyProfile = getStringOption(parsed, "latency")?.trim();
91
+ if (parsed.options.reliability !== undefined)
92
+ payload.reliabilityScore = Number(getStringOption(parsed, "reliability"));
93
+ if (parsed.options.status !== undefined)
94
+ payload.status = getStringOption(parsed, "status")?.trim();
95
+ if (parsed.options.metadata !== undefined)
96
+ payload.metadata = parseJsonOption(getStringOption(parsed, "metadata"));
97
+ if (Object.keys(payload).length === 0) {
98
+ throw new ValidationError("Informe ao menos um campo para atualização.");
99
+ }
100
+ const agent = await apiClient.updateRegistryAgent(session.accessToken, agentId, payload);
101
+ runtime.logger.success("agente atualizado.");
102
+ if (!printJsonIfRequested(parsed, agent)) {
103
+ printAgent(agent);
104
+ }
105
+ return 0;
106
+ }
107
+ if (subcommand === "deactivate") {
108
+ const agentId = requirePositional(parsed, 1, "Informe o identificador do agente.");
109
+ await apiClient.deactivateRegistryAgent(session.accessToken, agentId);
110
+ runtime.logger.success("agente desativado.");
111
+ process.stdout.write(`Agent deactivated: ${agentId}\n`);
112
+ return 0;
113
+ }
114
+ throw new ValidationError("Subcomando de registry não suportado.");
115
+ }
116
+ //# sourceMappingURL=registry.js.map
@@ -7,6 +7,7 @@ import { ensureFreshSession, resolveWorkspaceSlug } from "../core/session.js";
7
7
  import { VectorPlaneApiClient } from "../core/api.js";
8
8
  import { deriveClientInstanceId, getBoundWorkspace, resolveWorkspaceRoot } from "../core/workspace-binding.js";
9
9
  import { ValidationError } from "../core/errors.js";
10
+ import { ensureRuntimeAgentSetup } from "../core/runtime-agent-setup.js";
10
11
  function readCollaborationMetadata(parsed, rootPath) {
11
12
  const owningPaths = getStringListOption(parsed, "owning-path");
12
13
  const needs = getStringListOption(parsed, "need");
@@ -56,6 +57,7 @@ export async function runSessionCommand(cliVersion, args) {
56
57
  if (!workspace) {
57
58
  throw new ValidationError("Nenhum workspace resolvido para a sessão.");
58
59
  }
60
+ await ensureRuntimeAgentSetup({ rootPath, workspace, git, session: freshSession, apiClient, logger: runtime.logger });
59
61
  const clientInstanceId = getStringOption(parsed, "client-instance-id") ?? deriveClientInstanceId(runtime.device.machineId, rootPath, git);
60
62
  const metadata = readCollaborationMetadata(parsed, rootPath);
61
63
  if (subcommand === "check-in") {
@@ -10,6 +10,7 @@ import { VectorPlaneApiClient } from "../core/api.js";
10
10
  import { collectWorkspaceContext } from "../core/workspace.js";
11
11
  import { getBoundWorkspace } from "../core/workspace-binding.js";
12
12
  import { ValidationError } from "../core/errors.js";
13
+ import { ensureRuntimeAgentSetup } from "../core/runtime-agent-setup.js";
13
14
  export async function runSyncCommand(cliVersion, args) {
14
15
  const parsed = parseArgs(args);
15
16
  const force = getBooleanOption(parsed, "force");
@@ -39,6 +40,14 @@ export async function runSyncCommand(cliVersion, args) {
39
40
  if (!workspaceSlug) {
40
41
  throw new ValidationError("Nenhum workspace ativo foi resolvido. Use `vp workspace use <workspace>` ou `vp login`.");
41
42
  }
43
+ await ensureRuntimeAgentSetup({
44
+ rootPath: workspaceRoot,
45
+ workspace: workspaceSlug,
46
+ git,
47
+ session: freshSession,
48
+ apiClient,
49
+ logger: runtime.logger,
50
+ });
42
51
  const workspace = await collectWorkspaceContext(process.cwd(), git);
43
52
  runtime.logger.info("consolidando contexto...");
44
53
  const timestamp = new Date().toISOString();
@@ -0,0 +1 @@
1
+ export declare function runTaskCommand(cliVersion: string, args: string[]): Promise<number>;