@vectorplane/ctrl-cli 0.1.12 → 0.1.13
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 +7 -0
- package/dist/commands/context.js +14 -5
- package/dist/commands/task.js +44 -2
- package/dist/commands/workspace.js +65 -0
- package/dist/core/api.d.ts +23 -1
- package/dist/core/api.js +112 -0
- package/dist/index.js +2 -2
- package/dist/types/api.d.ts +46 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,11 +21,15 @@ vp sync
|
|
|
21
21
|
vp task templates
|
|
22
22
|
vp task run --title "Entrega X" --intention "Implementar fluxo Y"
|
|
23
23
|
vp task run --template code-review --title "Review auth" --intention "Revisar risco e cobertura do fluxo de auth"
|
|
24
|
+
vp task watch <task-id>
|
|
24
25
|
vp task claim --capability qa.test
|
|
25
26
|
vp task execute <task-id> --step <step-id>
|
|
26
27
|
vp task daemon --capability qa.test
|
|
27
28
|
vp context --search "decisões sobre autenticação"
|
|
28
29
|
vp context --delivery --search "fluxo de login" --type decisions
|
|
30
|
+
vp context --diff --from latest-1 --to latest
|
|
31
|
+
vp workspace webhook list
|
|
32
|
+
vp workspace webhook create --name approvals --url https://example.com/hooks/vectorplane --secret supersecret123 --events task.approval_required,task.blocked
|
|
29
33
|
vp context --workspace <workspace> --delivery
|
|
30
34
|
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"
|
|
31
35
|
vp draft create --type progress --title "Entrega concluída" --content "Resumo da mudança"
|
|
@@ -74,6 +78,7 @@ vp draft create --type progress --title "Entrega concluída" --content "Resumo d
|
|
|
74
78
|
- lista templates disponíveis com `vp task templates`
|
|
75
79
|
- aceita `--template <slug>` para herdar capabilities e paths padrão do backend
|
|
76
80
|
- lista e inspeciona tasks existentes
|
|
81
|
+
- acompanha uma task em tempo real com `vp task watch <taskId>`
|
|
77
82
|
- faz claim explícito de steps `pending_claim` atribuídos a agentes CLI
|
|
78
83
|
- executa steps locais via `metadata.execution.command`
|
|
79
84
|
- suporta loop controlado com `vp task daemon --capability ...`
|
|
@@ -111,12 +116,14 @@ vp draft create --type progress --title "Entrega concluída" --content "Resumo d
|
|
|
111
116
|
- inclui `vp config privacy` e `vp config policy`
|
|
112
117
|
- `vp workspace`
|
|
113
118
|
- gerencia o workspace atual
|
|
119
|
+
- suporta `vp workspace webhook list|create|delete` para integrações externas por workspace
|
|
114
120
|
- `vp session`
|
|
115
121
|
- gerencia sessões de agente
|
|
116
122
|
- `vp context`
|
|
117
123
|
- carrega contexto remoto do workspace
|
|
118
124
|
- suporta `--search "QUERY"` para busca semântica na memória
|
|
119
125
|
- com `--delivery --search`, retorna delivery context com fragmentos semânticos relevantes
|
|
126
|
+
- suporta `--diff --from latest-1 --to latest` para comparar snapshots do workspace
|
|
120
127
|
- `vp bootstrap`
|
|
121
128
|
- obtém instruções de setup do workspace
|
|
122
129
|
- `vp event send`
|
package/dist/commands/context.js
CHANGED
|
@@ -12,6 +12,7 @@ export async function runContextCommand(cliVersion, args) {
|
|
|
12
12
|
const parsed = parseArgs(args);
|
|
13
13
|
const delivery = getBooleanOption(parsed, "delivery");
|
|
14
14
|
const snapshot = getBooleanOption(parsed, "snapshot");
|
|
15
|
+
const diff = getBooleanOption(parsed, "diff");
|
|
15
16
|
const search = getStringOption(parsed, "search")?.trim();
|
|
16
17
|
const runtime = await loadRuntimeStatus();
|
|
17
18
|
const session = await ensureSessionAvailable(runtime.profile.name);
|
|
@@ -38,6 +39,9 @@ export async function runContextCommand(cliVersion, args) {
|
|
|
38
39
|
throw new ValidationError("Nenhum workspace resolvido para carregar contexto.");
|
|
39
40
|
}
|
|
40
41
|
await ensureRuntimeAgentSetup({ rootPath, workspace, git, session: freshSession, apiClient, logger: runtime.logger });
|
|
42
|
+
if (diff && (delivery || snapshot || search)) {
|
|
43
|
+
throw new ValidationError("`--diff` não pode ser combinado com `--delivery`, `--snapshot` ou `--search`.");
|
|
44
|
+
}
|
|
41
45
|
const payload = search
|
|
42
46
|
? (delivery
|
|
43
47
|
? await apiClient.getWorkspaceDeliveryContextSemantic(freshSession.accessToken, workspace, {
|
|
@@ -52,11 +56,16 @@ export async function runContextCommand(cliVersion, args) {
|
|
|
52
56
|
authority: getStringOption(parsed, "authority")?.trim(),
|
|
53
57
|
limit: Number(getStringOption(parsed, "limit") ?? "0") || undefined,
|
|
54
58
|
}))
|
|
55
|
-
:
|
|
56
|
-
? await apiClient.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
: diff
|
|
60
|
+
? await apiClient.getWorkspaceSnapshotDiff(freshSession.accessToken, workspace, {
|
|
61
|
+
from: getStringOption(parsed, "from")?.trim() || "latest-1",
|
|
62
|
+
to: getStringOption(parsed, "to")?.trim() || "latest",
|
|
63
|
+
})
|
|
64
|
+
: delivery
|
|
65
|
+
? await apiClient.getWorkspaceDeliveryContext(freshSession.accessToken, workspace)
|
|
66
|
+
: snapshot
|
|
67
|
+
? await apiClient.getWorkspaceSnapshot(freshSession.accessToken, workspace)
|
|
68
|
+
: await apiClient.getWorkspaceContext(freshSession.accessToken, workspace);
|
|
60
69
|
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
61
70
|
return 0;
|
|
62
71
|
}
|
package/dist/commands/task.js
CHANGED
|
@@ -157,6 +157,12 @@ function printObservability(payload) {
|
|
|
157
157
|
process.stdout.write(`Delegadas: ${String(payload.delegatedTasks ?? 0)}\n`);
|
|
158
158
|
process.stdout.write(`Success rate: ${String(payload.successRate ?? 0)}\n`);
|
|
159
159
|
}
|
|
160
|
+
function printWatchEvent(event) {
|
|
161
|
+
const scope = event.taskId ? `task=${event.taskId}` : `workspace=${event.workspaceId}`;
|
|
162
|
+
const step = event.stepId ? ` step=${event.stepId}` : "";
|
|
163
|
+
const summary = event.summary ? ` ${JSON.stringify(event.summary)}` : "";
|
|
164
|
+
process.stdout.write(`[${event.timestamp}] ${event.type} ${scope}${step}${summary}\n`);
|
|
165
|
+
}
|
|
160
166
|
async function runTaskList(cliVersion, args) {
|
|
161
167
|
const { parsed, apiClient, freshSession, workspace } = await resolveAuthenticatedWorkspace(cliVersion, args);
|
|
162
168
|
const tasks = await apiClient.listTasks(freshSession.accessToken, workspace);
|
|
@@ -433,6 +439,40 @@ async function runTaskObservability(cliVersion, args) {
|
|
|
433
439
|
}
|
|
434
440
|
return 0;
|
|
435
441
|
}
|
|
442
|
+
async function runTaskWatch(cliVersion, args) {
|
|
443
|
+
const { apiClient, freshSession, workspace } = await resolveAuthenticatedWorkspace(cliVersion, args);
|
|
444
|
+
const parsed = parseArgs(args);
|
|
445
|
+
const taskId = requirePositional(parsed, 0, "Uso: vp task watch <taskId> [--json]");
|
|
446
|
+
const task = await apiClient.getTask(freshSession.accessToken, workspace, taskId);
|
|
447
|
+
if (printJsonIfRequested(parsed, task)) {
|
|
448
|
+
return 0;
|
|
449
|
+
}
|
|
450
|
+
printTask(task);
|
|
451
|
+
const controller = new AbortController();
|
|
452
|
+
let exitCode = 0;
|
|
453
|
+
await apiClient.streamWorkspaceEvents(freshSession.accessToken, workspace, {
|
|
454
|
+
taskId,
|
|
455
|
+
signal: controller.signal,
|
|
456
|
+
onEvent: (event) => {
|
|
457
|
+
if (event.type === "ready" || event.type === "heartbeat") {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
printWatchEvent(event);
|
|
461
|
+
if (event.type === "task.failed" || event.type === "task.blocked") {
|
|
462
|
+
exitCode = 1;
|
|
463
|
+
}
|
|
464
|
+
if (event.type === "task.completed" || event.type === "task.failed" || event.type === "task.blocked") {
|
|
465
|
+
controller.abort();
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
}).catch((error) => {
|
|
469
|
+
if (controller.signal.aborted) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
throw error;
|
|
473
|
+
});
|
|
474
|
+
return exitCode;
|
|
475
|
+
}
|
|
436
476
|
async function runTaskHealth(cliVersion, args) {
|
|
437
477
|
const { apiClient, freshSession, workspace } = await resolveAuthenticatedWorkspace(cliVersion, args);
|
|
438
478
|
const parsed = parseArgs(args);
|
|
@@ -465,7 +505,7 @@ async function runTaskApproval(cliVersion, args, approved) {
|
|
|
465
505
|
}
|
|
466
506
|
export async function runTaskCommand(cliVersion, args) {
|
|
467
507
|
const parsed = parseArgs(args);
|
|
468
|
-
const subcommand = requirePositional(parsed, 0, "Uso: vp task <run|templates|list|inspect|claim|execute|daemon|approve|reject|delegate|step-update|handoff|observability|health> [...]");
|
|
508
|
+
const subcommand = requirePositional(parsed, 0, "Uso: vp task <run|templates|list|inspect|watch|claim|execute|daemon|approve|reject|delegate|step-update|handoff|observability|health> [...]");
|
|
469
509
|
switch (subcommand) {
|
|
470
510
|
case "run":
|
|
471
511
|
return runTaskRun(cliVersion, args.slice(1));
|
|
@@ -475,6 +515,8 @@ export async function runTaskCommand(cliVersion, args) {
|
|
|
475
515
|
return runTaskList(cliVersion, args.slice(1));
|
|
476
516
|
case "inspect":
|
|
477
517
|
return runTaskInspect(cliVersion, args.slice(1));
|
|
518
|
+
case "watch":
|
|
519
|
+
return runTaskWatch(cliVersion, args.slice(1));
|
|
478
520
|
case "claim":
|
|
479
521
|
return runTaskClaim(cliVersion, args.slice(1));
|
|
480
522
|
case "execute":
|
|
@@ -496,7 +538,7 @@ export async function runTaskCommand(cliVersion, args) {
|
|
|
496
538
|
case "health":
|
|
497
539
|
return runTaskHealth(cliVersion, args.slice(1));
|
|
498
540
|
default:
|
|
499
|
-
throw new ValidationError("Uso: vp task <run|templates|list|inspect|claim|execute|daemon|approve|reject|delegate|step-update|handoff|observability|health> [...]");
|
|
541
|
+
throw new ValidationError("Uso: vp task <run|templates|list|inspect|watch|claim|execute|daemon|approve|reject|delegate|step-update|handoff|observability|health> [...]");
|
|
500
542
|
}
|
|
501
543
|
}
|
|
502
544
|
//# sourceMappingURL=task.js.map
|
|
@@ -39,6 +39,20 @@ function printPolicyRule(rule) {
|
|
|
39
39
|
process.stdout.write(`Required capabilities: ${rule.conditions.requiredCapabilities.join(", ")}\n`);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
function printWebhook(hook) {
|
|
43
|
+
process.stdout.write(`Webhook: ${hook.id}\n`);
|
|
44
|
+
process.stdout.write(`Nome: ${hook.name}\n`);
|
|
45
|
+
process.stdout.write(`URL: ${hook.targetUrl}\n`);
|
|
46
|
+
process.stdout.write(`Enabled: ${hook.enabled ? "true" : "false"}\n`);
|
|
47
|
+
process.stdout.write(`Secret: ${hook.secretPreview}\n`);
|
|
48
|
+
process.stdout.write(`Eventos: ${hook.events.join(", ")}\n`);
|
|
49
|
+
if (hook.lastDeliveryStatus) {
|
|
50
|
+
process.stdout.write(`Última entrega: ${hook.lastDeliveryStatus}${hook.lastDeliveryAt ? ` em ${hook.lastDeliveryAt}` : ""}\n`);
|
|
51
|
+
}
|
|
52
|
+
if (hook.lastError) {
|
|
53
|
+
process.stdout.write(`Erro: ${hook.lastError}\n`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
42
56
|
function resolvePolicyConditions(parsed) {
|
|
43
57
|
const archetypes = getStringListOption(parsed, "archetypes");
|
|
44
58
|
const requiredCapabilities = getStringListOption(parsed, "required-capabilities");
|
|
@@ -155,6 +169,54 @@ async function runWorkspacePolicyCommand(args) {
|
|
|
155
169
|
}
|
|
156
170
|
throw new ValidationError("Subcomando de workspace policy não suportado.");
|
|
157
171
|
}
|
|
172
|
+
async function runWorkspaceWebhookCommand(args) {
|
|
173
|
+
const parsed = parseArgs(args);
|
|
174
|
+
const [subcommand] = parsed.positionals.slice(1);
|
|
175
|
+
const { session, apiClient, workspace } = await resolveWorkspaceApiContext();
|
|
176
|
+
if (!subcommand || subcommand === "list") {
|
|
177
|
+
const hooks = await apiClient.listWorkspaceWebhooks(session.accessToken, workspace);
|
|
178
|
+
if (printJsonIfRequested(parsed, hooks)) {
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
181
|
+
if (hooks.length === 0) {
|
|
182
|
+
process.stdout.write("VectorPlane: nenhum webhook encontrado.\n");
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
for (const hook of hooks) {
|
|
186
|
+
process.stdout.write(`${hook.id} | ${hook.enabled ? "enabled" : "disabled"} | ${hook.name} | ${hook.targetUrl}\n`);
|
|
187
|
+
}
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
if (subcommand === "create") {
|
|
191
|
+
const name = getStringOption(parsed, "name")?.trim();
|
|
192
|
+
const targetUrl = getStringOption(parsed, "url")?.trim();
|
|
193
|
+
const secret = getStringOption(parsed, "secret")?.trim();
|
|
194
|
+
const events = getStringListOption(parsed, "events");
|
|
195
|
+
if (!name || !targetUrl || !secret || events.length === 0) {
|
|
196
|
+
throw new ValidationError("Informe `--name`, `--url`, `--secret` e `--events`.");
|
|
197
|
+
}
|
|
198
|
+
const hook = await apiClient.createWorkspaceWebhook(session.accessToken, workspace, {
|
|
199
|
+
name,
|
|
200
|
+
targetUrl,
|
|
201
|
+
secret,
|
|
202
|
+
events,
|
|
203
|
+
enabled: parsed.options.enabled === undefined ? true : getBooleanOption(parsed, "enabled"),
|
|
204
|
+
});
|
|
205
|
+
if (!printJsonIfRequested(parsed, hook)) {
|
|
206
|
+
printWebhook(hook);
|
|
207
|
+
}
|
|
208
|
+
return 0;
|
|
209
|
+
}
|
|
210
|
+
if (subcommand === "delete") {
|
|
211
|
+
const webhookId = requirePositional(parsed, 2, "Informe o identificador do webhook.");
|
|
212
|
+
const result = await apiClient.deleteWorkspaceWebhook(session.accessToken, workspace, webhookId);
|
|
213
|
+
if (!printJsonIfRequested(parsed, result)) {
|
|
214
|
+
process.stdout.write(`Webhook removido: ${result.webhookId}\n`);
|
|
215
|
+
}
|
|
216
|
+
return 0;
|
|
217
|
+
}
|
|
218
|
+
throw new ValidationError("Subcomando de workspace webhook não suportado.");
|
|
219
|
+
}
|
|
158
220
|
export async function runWorkspaceCommand(args) {
|
|
159
221
|
const parsed = parseArgs(args);
|
|
160
222
|
const [subcommand] = parsed.positionals;
|
|
@@ -214,6 +276,9 @@ export async function runWorkspaceCommand(args) {
|
|
|
214
276
|
if (subcommand === "policy") {
|
|
215
277
|
return runWorkspacePolicyCommand(args);
|
|
216
278
|
}
|
|
279
|
+
if (subcommand === "webhook") {
|
|
280
|
+
return runWorkspaceWebhookCommand(args);
|
|
281
|
+
}
|
|
217
282
|
throw new ValidationError("Subcomando de workspace não suportado.");
|
|
218
283
|
}
|
|
219
284
|
//# sourceMappingURL=workspace.js.map
|
package/dist/core/api.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger } from "./logger.js";
|
|
2
2
|
import type { CurrentUserResponse, AuthCodeExchangeRequest, AuthTokenExchangeResponse, CreateLoginAttemptRequest, CreateLoginAttemptResponse, LoginAttemptStatusResponse, RefreshTokenRequest } from "../types/auth.js";
|
|
3
|
-
import type { AgentCheckoutRequest, AgentHeartbeatRequest, AgentSessionRequest, AgentSessionResponse, EventRequest, MemoryDraftCreateRequest, MemoryDraftRecord, MemoryDraftStatus, MemorySearchRecord, ClaimableTaskStepRecord, ClaimedTaskStepResponse, TaskCreateRequest, TaskHandoffRecord, TaskObservabilityRecord, TaskRecord, ResolveWorkspaceRequest, ResolveWorkspaceResponse, SyncRequest, SyncResponse, WorkspaceAgentSetup, WorkspacePolicyRuleRecord, AgentRegistryRecord, TaskTemplateRecord } from "../types/api.js";
|
|
3
|
+
import type { AgentCheckoutRequest, AgentHeartbeatRequest, AgentSessionRequest, AgentSessionResponse, EventRequest, MemoryDraftCreateRequest, MemoryDraftRecord, MemoryDraftStatus, MemorySearchRecord, ClaimableTaskStepRecord, ClaimedTaskStepResponse, TaskCreateRequest, TaskHandoffRecord, TaskObservabilityRecord, TaskRecord, ResolveWorkspaceRequest, ResolveWorkspaceResponse, SyncRequest, SyncResponse, WorkspaceAgentSetup, WorkspaceSnapshotDiffRecord, WorkspacePolicyRuleRecord, WorkspaceWebhookRecord, AgentRegistryRecord, TaskTemplateRecord, WorkspaceStreamEventRecord } from "../types/api.js";
|
|
4
4
|
export declare class VectorPlaneApiClient {
|
|
5
5
|
private readonly apiBaseUrl;
|
|
6
6
|
private readonly timeoutMs;
|
|
@@ -20,6 +20,10 @@ export declare class VectorPlaneApiClient {
|
|
|
20
20
|
resolveWorkspaceByRepo(accessToken: string, payload: ResolveWorkspaceRequest): Promise<ResolveWorkspaceResponse>;
|
|
21
21
|
getWorkspaceContext(accessToken: string, workspaceId: string): Promise<Record<string, unknown>>;
|
|
22
22
|
getWorkspaceSnapshot(accessToken: string, workspaceId: string): Promise<Record<string, unknown>>;
|
|
23
|
+
getWorkspaceSnapshotDiff(accessToken: string, workspaceId: string, params: {
|
|
24
|
+
from?: string;
|
|
25
|
+
to?: string;
|
|
26
|
+
}): Promise<WorkspaceSnapshotDiffRecord>;
|
|
23
27
|
getWorkspaceDeliveryContext(accessToken: string, workspaceId: string): Promise<Record<string, unknown>>;
|
|
24
28
|
getWorkspaceDeliveryContextSemantic(accessToken: string, workspaceId: string, params: {
|
|
25
29
|
query: string;
|
|
@@ -49,6 +53,18 @@ export declare class VectorPlaneApiClient {
|
|
|
49
53
|
approvalRole?: string | null;
|
|
50
54
|
enabled?: boolean;
|
|
51
55
|
}): Promise<WorkspacePolicyRuleRecord>;
|
|
56
|
+
listWorkspaceWebhooks(accessToken: string, workspaceRef: string): Promise<WorkspaceWebhookRecord[]>;
|
|
57
|
+
createWorkspaceWebhook(accessToken: string, workspaceRef: string, payload: {
|
|
58
|
+
name: string;
|
|
59
|
+
targetUrl: string;
|
|
60
|
+
secret: string;
|
|
61
|
+
events: WorkspaceWebhookRecord["events"];
|
|
62
|
+
enabled?: boolean;
|
|
63
|
+
}): Promise<WorkspaceWebhookRecord>;
|
|
64
|
+
deleteWorkspaceWebhook(accessToken: string, workspaceRef: string, webhookId: string): Promise<{
|
|
65
|
+
deleted: boolean;
|
|
66
|
+
webhookId: string;
|
|
67
|
+
}>;
|
|
52
68
|
listMemoryDrafts(accessToken: string, workspaceRef: string, status?: MemoryDraftStatus): Promise<MemoryDraftRecord[]>;
|
|
53
69
|
createMemoryDraft(accessToken: string, workspaceRef: string, payload: MemoryDraftCreateRequest): Promise<MemoryDraftRecord>;
|
|
54
70
|
searchWorkspaceMemory(accessToken: string, workspaceRef: string, params: {
|
|
@@ -119,4 +135,10 @@ export declare class VectorPlaneApiClient {
|
|
|
119
135
|
checkOutAgent(accessToken: string, payload: AgentCheckoutRequest): Promise<AgentSessionResponse>;
|
|
120
136
|
getHealth(): Promise<Record<string, unknown>>;
|
|
121
137
|
getReady(): Promise<Record<string, unknown>>;
|
|
138
|
+
streamWorkspaceEvents(accessToken: string, workspaceRef: string, params: {
|
|
139
|
+
taskId?: string;
|
|
140
|
+
types?: string[];
|
|
141
|
+
signal?: AbortSignal;
|
|
142
|
+
onEvent: (event: WorkspaceStreamEventRecord) => void;
|
|
143
|
+
}): Promise<void>;
|
|
122
144
|
}
|
package/dist/core/api.js
CHANGED
|
@@ -144,6 +144,21 @@ export class VectorPlaneApiClient {
|
|
|
144
144
|
},
|
|
145
145
|
}, this.timeoutMs, this.logger);
|
|
146
146
|
}
|
|
147
|
+
async getWorkspaceSnapshotDiff(accessToken, workspaceId, params) {
|
|
148
|
+
const url = new URL(`${this.apiBaseUrl}/workspace/${workspaceId}/snapshot/diff`);
|
|
149
|
+
if (params.from) {
|
|
150
|
+
url.searchParams.set("from", params.from);
|
|
151
|
+
}
|
|
152
|
+
if (params.to) {
|
|
153
|
+
url.searchParams.set("to", params.to);
|
|
154
|
+
}
|
|
155
|
+
return requestJson(url.toString(), {
|
|
156
|
+
method: "GET",
|
|
157
|
+
headers: {
|
|
158
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
159
|
+
},
|
|
160
|
+
}, this.timeoutMs, this.logger);
|
|
161
|
+
}
|
|
147
162
|
async getWorkspaceDeliveryContext(accessToken, workspaceId) {
|
|
148
163
|
return requestJson(`${this.apiBaseUrl}/cli/workspace/${workspaceId}/delivery-context`, {
|
|
149
164
|
method: "GET",
|
|
@@ -202,6 +217,29 @@ export class VectorPlaneApiClient {
|
|
|
202
217
|
body: JSON.stringify(payload),
|
|
203
218
|
}, this.timeoutMs, this.logger);
|
|
204
219
|
}
|
|
220
|
+
async listWorkspaceWebhooks(accessToken, workspaceRef) {
|
|
221
|
+
return requestJson(`${this.apiBaseUrl}/workspace/${workspaceRef}/webhooks`, {
|
|
222
|
+
method: "GET",
|
|
223
|
+
headers: {
|
|
224
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
225
|
+
},
|
|
226
|
+
}, this.timeoutMs, this.logger);
|
|
227
|
+
}
|
|
228
|
+
async createWorkspaceWebhook(accessToken, workspaceRef, payload) {
|
|
229
|
+
return requestJson(`${this.apiBaseUrl}/workspace/${workspaceRef}/webhooks`, {
|
|
230
|
+
method: "POST",
|
|
231
|
+
headers: authHeaders(accessToken),
|
|
232
|
+
body: JSON.stringify(payload),
|
|
233
|
+
}, this.timeoutMs, this.logger);
|
|
234
|
+
}
|
|
235
|
+
async deleteWorkspaceWebhook(accessToken, workspaceRef, webhookId) {
|
|
236
|
+
return requestJson(`${this.apiBaseUrl}/workspace/${workspaceRef}/webhooks/${webhookId}`, {
|
|
237
|
+
method: "DELETE",
|
|
238
|
+
headers: {
|
|
239
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
240
|
+
},
|
|
241
|
+
}, this.timeoutMs, this.logger);
|
|
242
|
+
}
|
|
205
243
|
async listMemoryDrafts(accessToken, workspaceRef, status) {
|
|
206
244
|
const url = new URL(`${this.apiBaseUrl}/cli/workspace/${workspaceRef}/memory-drafts`);
|
|
207
245
|
if (status) {
|
|
@@ -421,5 +459,79 @@ export class VectorPlaneApiClient {
|
|
|
421
459
|
method: "GET",
|
|
422
460
|
}, this.timeoutMs, this.logger);
|
|
423
461
|
}
|
|
462
|
+
async streamWorkspaceEvents(accessToken, workspaceRef, params) {
|
|
463
|
+
const url = new URL(`${this.apiBaseUrl}/workspace/${workspaceRef}/events/stream`);
|
|
464
|
+
if (params.taskId) {
|
|
465
|
+
url.searchParams.set("task_id", params.taskId);
|
|
466
|
+
}
|
|
467
|
+
if (params.types && params.types.length > 0) {
|
|
468
|
+
url.searchParams.set("types", params.types.join(","));
|
|
469
|
+
}
|
|
470
|
+
this.logger.debug("http_stream_open", { url: url.toString() });
|
|
471
|
+
const response = await fetch(url.toString(), {
|
|
472
|
+
method: "GET",
|
|
473
|
+
headers: {
|
|
474
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
475
|
+
"Accept": "text/event-stream",
|
|
476
|
+
},
|
|
477
|
+
signal: params.signal,
|
|
478
|
+
});
|
|
479
|
+
if (!response.ok || !response.body) {
|
|
480
|
+
const body = await parseBody(response);
|
|
481
|
+
const message = typeof body === "string" ? body : `HTTP ${response.status}`;
|
|
482
|
+
throw new ApiError(message, response.status, body);
|
|
483
|
+
}
|
|
484
|
+
const reader = response.body.getReader();
|
|
485
|
+
const decoder = new TextDecoder();
|
|
486
|
+
let buffer = "";
|
|
487
|
+
const emitFrame = (frame) => {
|
|
488
|
+
const lines = frame.split("\n");
|
|
489
|
+
let eventName = "message";
|
|
490
|
+
const dataLines = [];
|
|
491
|
+
for (const line of lines) {
|
|
492
|
+
if (line.startsWith("event:")) {
|
|
493
|
+
eventName = line.slice(6).trim();
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
if (line.startsWith("data:")) {
|
|
497
|
+
dataLines.push(line.slice(5).trim());
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
if (dataLines.length === 0) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
const payload = JSON.parse(dataLines.join("\n"));
|
|
505
|
+
params.onEvent({
|
|
506
|
+
type: eventName,
|
|
507
|
+
workspaceId: payload.workspaceId,
|
|
508
|
+
taskId: payload.taskId ?? null,
|
|
509
|
+
stepId: payload.stepId ?? null,
|
|
510
|
+
timestamp: payload.timestamp,
|
|
511
|
+
summary: payload.summary ?? null,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
catch (error) {
|
|
515
|
+
this.logger.debug("http_stream_frame_ignored", {
|
|
516
|
+
reason: error instanceof Error ? error.message : "invalid_json",
|
|
517
|
+
eventName,
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
while (true) {
|
|
522
|
+
const { done, value } = await reader.read();
|
|
523
|
+
if (done) {
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
buffer += decoder.decode(value, { stream: true });
|
|
527
|
+
let separatorIndex = buffer.indexOf("\n\n");
|
|
528
|
+
while (separatorIndex >= 0) {
|
|
529
|
+
const frame = buffer.slice(0, separatorIndex);
|
|
530
|
+
buffer = buffer.slice(separatorIndex + 2);
|
|
531
|
+
emitFrame(frame);
|
|
532
|
+
separatorIndex = buffer.indexOf("\n\n");
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
424
536
|
}
|
|
425
537
|
//# sourceMappingURL=api.js.map
|
package/dist/index.js
CHANGED
|
@@ -35,13 +35,13 @@ function printHelp() {
|
|
|
35
35
|
process.stdout.write(" logout\n");
|
|
36
36
|
process.stdout.write(" sync [--force]\n");
|
|
37
37
|
process.stdout.write(" status\n");
|
|
38
|
-
process.stdout.write(" task <run|templates|list|inspect|claim|execute|daemon|approve|reject|delegate|step-update|handoff|observability|health>\n");
|
|
38
|
+
process.stdout.write(" task <run|templates|list|inspect|watch|claim|execute|daemon|approve|reject|delegate|step-update|handoff|observability|health>\n");
|
|
39
39
|
process.stdout.write(" registry <list|register|update|deactivate>\n");
|
|
40
40
|
process.stdout.write(" whoami\n");
|
|
41
41
|
process.stdout.write(" doctor\n");
|
|
42
42
|
process.stdout.write(" draft <create|list>\n");
|
|
43
43
|
process.stdout.write(" config <profile|get|set>\n");
|
|
44
|
-
process.stdout.write(" workspace <current|use|resolve|clear>\n");
|
|
44
|
+
process.stdout.write(" workspace <current|use|resolve|clear|policy|webhook>\n");
|
|
45
45
|
process.stdout.write(" session <check-in|heartbeat|check-out>\n");
|
|
46
46
|
process.stdout.write(" context [--snapshot|--delivery]\n");
|
|
47
47
|
process.stdout.write(" bootstrap\n");
|
package/dist/types/api.d.ts
CHANGED
|
@@ -88,6 +88,23 @@ export interface WorkspacePolicyRuleRecord {
|
|
|
88
88
|
updatedAt: string;
|
|
89
89
|
[key: string]: unknown;
|
|
90
90
|
}
|
|
91
|
+
export type WorkspaceWebhookEventType = "task.created" | "task.blocked" | "task.completed" | "task.approval_required" | "health.degraded";
|
|
92
|
+
export interface WorkspaceWebhookRecord {
|
|
93
|
+
id: string;
|
|
94
|
+
orgId: string;
|
|
95
|
+
workspaceId: string;
|
|
96
|
+
name: string;
|
|
97
|
+
targetUrl: string;
|
|
98
|
+
secretPreview: string;
|
|
99
|
+
events: WorkspaceWebhookEventType[];
|
|
100
|
+
enabled: boolean;
|
|
101
|
+
lastDeliveryAt: string | null;
|
|
102
|
+
lastDeliveryStatus: "delivered" | "failed" | null;
|
|
103
|
+
lastError: string | null;
|
|
104
|
+
createdAt: string;
|
|
105
|
+
updatedAt: string;
|
|
106
|
+
[key: string]: unknown;
|
|
107
|
+
}
|
|
91
108
|
export interface AgentRegistryRecord {
|
|
92
109
|
id: string;
|
|
93
110
|
orgId: string | null;
|
|
@@ -291,3 +308,32 @@ export interface TaskObservabilityRecord {
|
|
|
291
308
|
timeline?: Array<Record<string, unknown>>;
|
|
292
309
|
[key: string]: unknown;
|
|
293
310
|
}
|
|
311
|
+
export interface WorkspaceStreamEventRecord {
|
|
312
|
+
type: string;
|
|
313
|
+
workspaceId: string;
|
|
314
|
+
taskId?: string | null;
|
|
315
|
+
stepId?: string | null;
|
|
316
|
+
timestamp: string;
|
|
317
|
+
summary?: Record<string, unknown> | null;
|
|
318
|
+
}
|
|
319
|
+
export interface WorkspaceSnapshotDiffRecord {
|
|
320
|
+
workspaceId: string;
|
|
321
|
+
from: {
|
|
322
|
+
reference: string;
|
|
323
|
+
version: number;
|
|
324
|
+
generatedAt: string;
|
|
325
|
+
};
|
|
326
|
+
to: {
|
|
327
|
+
reference: string;
|
|
328
|
+
version: number;
|
|
329
|
+
generatedAt: string;
|
|
330
|
+
};
|
|
331
|
+
summary: Record<string, {
|
|
332
|
+
added: number;
|
|
333
|
+
removed: number;
|
|
334
|
+
modified: number;
|
|
335
|
+
}>;
|
|
336
|
+
added: Record<string, Array<Record<string, unknown>>>;
|
|
337
|
+
removed: Record<string, Array<Record<string, unknown>>>;
|
|
338
|
+
modified: Record<string, Array<Record<string, unknown>>>;
|
|
339
|
+
}
|