@vectorplane/ctrl-cli 0.1.8 → 0.1.10
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 +18 -0
- package/dist/commands/draft.d.ts +1 -0
- package/dist/commands/draft.js +166 -0
- package/dist/commands/session.js +35 -9
- package/dist/core/api.d.ts +3 -1
- package/dist/core/api.js +19 -0
- package/dist/core/cli.d.ts +1 -0
- package/dist/core/cli.js +10 -0
- package/dist/index.js +4 -0
- package/dist/types/api.d.ts +27 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,9 @@ vp login
|
|
|
17
17
|
vp logout
|
|
18
18
|
vp status
|
|
19
19
|
vp sync
|
|
20
|
+
vp context --workspace <workspace> --delivery
|
|
21
|
+
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
|
+
vp draft create --type progress --title "Entrega concluída" --content "Resumo da mudança"
|
|
20
23
|
```
|
|
21
24
|
|
|
22
25
|
## Comandos
|
|
@@ -45,6 +48,19 @@ vp sync
|
|
|
45
48
|
- mostra o estado da sessão local
|
|
46
49
|
- exibe workspace ativo, diretório atual e última sincronização
|
|
47
50
|
|
|
51
|
+
### `vp draft`
|
|
52
|
+
|
|
53
|
+
- cria drafts editoriais ligados ao workspace atual
|
|
54
|
+
- lista drafts existentes para conferência rápida
|
|
55
|
+
- suporta `ui`, `ux`, `project_skeleton`, `template_engineering`, `patterns`, `progress`, `decisions` e `architecture`
|
|
56
|
+
- aceita `--no-impact` para registrar explicitamente quando uma lane não foi afetada
|
|
57
|
+
|
|
58
|
+
### `vp session`
|
|
59
|
+
|
|
60
|
+
- suporta `check-in`, `heartbeat` e `check-out`
|
|
61
|
+
- permite declarar `feature`, `task`, `component`, `role`, `owning-path`, `need`, `provide` e `status`
|
|
62
|
+
- deve ser usado em conjunto com `vp context --delivery` para reduzir conflito entre agentes ativos
|
|
63
|
+
|
|
48
64
|
### Comandos adicionais já implementados
|
|
49
65
|
|
|
50
66
|
- `vp whoami`
|
|
@@ -64,6 +80,8 @@ vp sync
|
|
|
64
80
|
- obtém instruções de setup do workspace
|
|
65
81
|
- `vp event send`
|
|
66
82
|
- envia eventos operacionais
|
|
83
|
+
- `vp draft`
|
|
84
|
+
- envia e consulta drafts editoriais do workspace
|
|
67
85
|
|
|
68
86
|
## Persistência local
|
|
69
87
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runDraftCommand(cliVersion: string, args: string[]): Promise<number>;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { getBooleanOption, getStringOption, parseArgs, 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 { getBoundWorkspace, resolveWorkspaceRoot } from "../core/workspace-binding.js";
|
|
9
|
+
import { ValidationError } from "../core/errors.js";
|
|
10
|
+
const VALID_DRAFT_TYPES = new Set([
|
|
11
|
+
"architecture",
|
|
12
|
+
"decisions",
|
|
13
|
+
"progress",
|
|
14
|
+
"patterns",
|
|
15
|
+
"ui",
|
|
16
|
+
"ux",
|
|
17
|
+
"template_engineering",
|
|
18
|
+
"project_skeleton",
|
|
19
|
+
]);
|
|
20
|
+
const VALID_STATUSES = new Set([
|
|
21
|
+
"draft",
|
|
22
|
+
"in_review",
|
|
23
|
+
"approved",
|
|
24
|
+
"merged",
|
|
25
|
+
"rejected",
|
|
26
|
+
"archived",
|
|
27
|
+
]);
|
|
28
|
+
function slugify(value) {
|
|
29
|
+
return value
|
|
30
|
+
.trim()
|
|
31
|
+
.toLowerCase()
|
|
32
|
+
.normalize("NFD")
|
|
33
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
34
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
35
|
+
.replace(/^-+|-+$/g, "")
|
|
36
|
+
.slice(0, 120);
|
|
37
|
+
}
|
|
38
|
+
function inferMemoryKey(type, title) {
|
|
39
|
+
const slug = slugify(title);
|
|
40
|
+
if (!slug)
|
|
41
|
+
return undefined;
|
|
42
|
+
const prefix = type === "decisions"
|
|
43
|
+
? "decision"
|
|
44
|
+
: type === "patterns"
|
|
45
|
+
? "pattern"
|
|
46
|
+
: type === "template_engineering"
|
|
47
|
+
? "template"
|
|
48
|
+
: type === "project_skeleton"
|
|
49
|
+
? "skeleton"
|
|
50
|
+
: type;
|
|
51
|
+
return `${prefix}:${slug}`;
|
|
52
|
+
}
|
|
53
|
+
function validateDraftType(value) {
|
|
54
|
+
if (!value || !VALID_DRAFT_TYPES.has(value)) {
|
|
55
|
+
throw new ValidationError("Informe um tipo válido em `--type`.");
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
function validateStatus(value) {
|
|
60
|
+
if (!value)
|
|
61
|
+
return undefined;
|
|
62
|
+
if (!VALID_STATUSES.has(value)) {
|
|
63
|
+
throw new ValidationError("Informe um status válido em `--status`.");
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
function buildNoImpactDraft(type, reason) {
|
|
68
|
+
const laneLabel = type.replaceAll("_", " ");
|
|
69
|
+
const explanation = reason?.trim() || "sem impacto identificado nesta tarefa";
|
|
70
|
+
return {
|
|
71
|
+
title: `Sem impacto em ${laneLabel}`,
|
|
72
|
+
content: `Esta tarefa não alterou diretamente a lane ${laneLabel}. Escopo efetivo: ${explanation}.`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function printDraftList(drafts) {
|
|
76
|
+
if (drafts.length === 0) {
|
|
77
|
+
process.stdout.write("VectorPlane: nenhum draft encontrado.\n");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
for (const draft of drafts) {
|
|
81
|
+
process.stdout.write(`${draft.id} | ${draft.docType} | ${draft.status} | ${draft.title}\n`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async function resolveAuthenticatedWorkspace(cliVersion, rawArgs) {
|
|
85
|
+
const runtime = await loadRuntimeStatus();
|
|
86
|
+
const session = await ensureSessionAvailable(runtime.profile.name);
|
|
87
|
+
const parsed = parseArgs(rawArgs);
|
|
88
|
+
const [git, machine, runtimeContext] = await Promise.all([
|
|
89
|
+
collectGitContext(process.cwd()),
|
|
90
|
+
collectMachineContext(runtime.device, runtime.config),
|
|
91
|
+
collectRuntimeContext(cliVersion, "draft", process.argv.slice(2)),
|
|
92
|
+
]);
|
|
93
|
+
const apiClient = new VectorPlaneApiClient(runtime.profile.apiBaseUrl, runtime.config.requestTimeoutMs, runtime.logger);
|
|
94
|
+
const freshSession = await ensureFreshSession({
|
|
95
|
+
profileName: runtime.profile.name,
|
|
96
|
+
session,
|
|
97
|
+
machine,
|
|
98
|
+
runtime: runtimeContext,
|
|
99
|
+
device: runtime.device,
|
|
100
|
+
apiClient,
|
|
101
|
+
logger: runtime.logger,
|
|
102
|
+
});
|
|
103
|
+
const rootPath = resolveWorkspaceRoot(process.cwd(), git);
|
|
104
|
+
const boundWorkspace = await getBoundWorkspace(rootPath);
|
|
105
|
+
const profileState = getProfileState(runtime.state, runtime.profile.name);
|
|
106
|
+
const workspace = resolveWorkspaceSlug(runtime.profile, freshSession, getStringOption(parsed, "workspace"), boundWorkspace, profileState.lastWorkspace);
|
|
107
|
+
if (!workspace) {
|
|
108
|
+
throw new ValidationError("Nenhum workspace resolvido para operar drafts.");
|
|
109
|
+
}
|
|
110
|
+
return { parsed, runtime, apiClient, freshSession, git, workspace };
|
|
111
|
+
}
|
|
112
|
+
async function runDraftCreate(cliVersion, args) {
|
|
113
|
+
const { parsed, runtime, apiClient, freshSession, git, workspace } = await resolveAuthenticatedWorkspace(cliVersion, args);
|
|
114
|
+
const type = validateDraftType(getStringOption(parsed, "type"));
|
|
115
|
+
const noImpact = getBooleanOption(parsed, "no-impact");
|
|
116
|
+
const explicitTitle = getStringOption(parsed, "title")?.trim();
|
|
117
|
+
const explicitContent = getStringOption(parsed, "content")?.trim();
|
|
118
|
+
const reason = getStringOption(parsed, "reason");
|
|
119
|
+
const derived = noImpact ? buildNoImpactDraft(type, reason) : null;
|
|
120
|
+
const title = explicitTitle || derived?.title;
|
|
121
|
+
const content = explicitContent || derived?.content;
|
|
122
|
+
if (!title) {
|
|
123
|
+
throw new ValidationError("Informe `--title` para criar o draft.");
|
|
124
|
+
}
|
|
125
|
+
if (!content) {
|
|
126
|
+
throw new ValidationError("Informe `--content` para criar o draft.");
|
|
127
|
+
}
|
|
128
|
+
const payload = {
|
|
129
|
+
docType: type,
|
|
130
|
+
title,
|
|
131
|
+
content,
|
|
132
|
+
memoryKey: getStringOption(parsed, "memory-key")?.trim() || inferMemoryKey(type, title),
|
|
133
|
+
featureKey: getStringOption(parsed, "feature")?.trim() || undefined,
|
|
134
|
+
branch: getStringOption(parsed, "branch")?.trim() || git.branch || undefined,
|
|
135
|
+
taskKey: getStringOption(parsed, "task")?.trim() || undefined,
|
|
136
|
+
};
|
|
137
|
+
const draft = await apiClient.createMemoryDraft(freshSession.accessToken, workspace, payload);
|
|
138
|
+
runtime.logger.success(`draft enviado para ${type}.`);
|
|
139
|
+
process.stdout.write(`ID: ${draft.id}\n`);
|
|
140
|
+
process.stdout.write(`Workspace: ${workspace}\n`);
|
|
141
|
+
process.stdout.write(`Status: ${draft.status}\n`);
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
async function runDraftList(cliVersion, args) {
|
|
145
|
+
const { parsed, apiClient, freshSession, workspace } = await resolveAuthenticatedWorkspace(cliVersion, args);
|
|
146
|
+
const status = validateStatus(getStringOption(parsed, "status"));
|
|
147
|
+
const drafts = await apiClient.listMemoryDrafts(freshSession.accessToken, workspace, status);
|
|
148
|
+
if (getBooleanOption(parsed, "json")) {
|
|
149
|
+
process.stdout.write(`${JSON.stringify(drafts, null, 2)}\n`);
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
printDraftList(drafts);
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
export async function runDraftCommand(cliVersion, args) {
|
|
156
|
+
const parsed = parseArgs(args);
|
|
157
|
+
const subcommand = requirePositional(parsed, 0, "Uso: vp draft <create|list> [...]");
|
|
158
|
+
if (subcommand === "create") {
|
|
159
|
+
return runDraftCreate(cliVersion, args.slice(1));
|
|
160
|
+
}
|
|
161
|
+
if (subcommand === "list") {
|
|
162
|
+
return runDraftList(cliVersion, args.slice(1));
|
|
163
|
+
}
|
|
164
|
+
throw new ValidationError("Uso: vp draft <create|list> [...]");
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=draft.js.map
|
package/dist/commands/session.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getStringOption, parseArgs } from "../core/cli.js";
|
|
1
|
+
import { getStringListOption, getStringOption, parseArgs } from "../core/cli.js";
|
|
2
2
|
import { ensureSessionAvailable, getProfileState, updateProfileState } from "../core/config.js";
|
|
3
3
|
import { collectGitContext } from "../core/git.js";
|
|
4
4
|
import { collectMachineContext, collectRuntimeContext } from "../core/machine.js";
|
|
@@ -7,6 +7,25 @@ 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
|
+
function readCollaborationMetadata(parsed, rootPath) {
|
|
11
|
+
const owningPaths = getStringListOption(parsed, "owning-path");
|
|
12
|
+
const needs = getStringListOption(parsed, "need");
|
|
13
|
+
const provides = getStringListOption(parsed, "provide");
|
|
14
|
+
const relatedWorkspaceIds = getStringListOption(parsed, "related-workspace");
|
|
15
|
+
return {
|
|
16
|
+
source: "vp-cli",
|
|
17
|
+
rootPath,
|
|
18
|
+
featureKey: getStringOption(parsed, "feature"),
|
|
19
|
+
taskKey: getStringOption(parsed, "task"),
|
|
20
|
+
component: getStringOption(parsed, "component"),
|
|
21
|
+
role: getStringOption(parsed, "role"),
|
|
22
|
+
statusSummary: getStringOption(parsed, "status"),
|
|
23
|
+
owningPaths: owningPaths.length > 0 ? owningPaths : undefined,
|
|
24
|
+
needs: needs.length > 0 ? needs : undefined,
|
|
25
|
+
provides: provides.length > 0 ? provides : undefined,
|
|
26
|
+
relatedWorkspaceIds: relatedWorkspaceIds.length > 0 ? relatedWorkspaceIds : undefined,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
10
29
|
export async function runSessionCommand(cliVersion, args) {
|
|
11
30
|
const parsed = parseArgs(args);
|
|
12
31
|
const [subcommand] = parsed.positionals;
|
|
@@ -38,6 +57,7 @@ export async function runSessionCommand(cliVersion, args) {
|
|
|
38
57
|
throw new ValidationError("Nenhum workspace resolvido para a sessão.");
|
|
39
58
|
}
|
|
40
59
|
const clientInstanceId = getStringOption(parsed, "client-instance-id") ?? deriveClientInstanceId(runtime.device.machineId, rootPath, git);
|
|
60
|
+
const metadata = readCollaborationMetadata(parsed, rootPath);
|
|
41
61
|
if (subcommand === "check-in") {
|
|
42
62
|
const response = await apiClient.checkInAgent(freshSession.accessToken, {
|
|
43
63
|
workspaceId: workspace,
|
|
@@ -48,10 +68,7 @@ export async function runSessionCommand(cliVersion, args) {
|
|
|
48
68
|
repoUrl: git.remoteOrigin ?? undefined,
|
|
49
69
|
branch: git.branch,
|
|
50
70
|
commitSha: git.commitHash,
|
|
51
|
-
metadata
|
|
52
|
-
source: "vp-cli",
|
|
53
|
-
rootPath,
|
|
54
|
-
},
|
|
71
|
+
metadata,
|
|
55
72
|
});
|
|
56
73
|
const sessionId = String(response.id ?? response.sessionId ?? "");
|
|
57
74
|
await updateProfileState(runtime.profile.name, {
|
|
@@ -62,6 +79,12 @@ export async function runSessionCommand(cliVersion, args) {
|
|
|
62
79
|
});
|
|
63
80
|
process.stdout.write(`Session ID: ${sessionId || "não retornado"}\n`);
|
|
64
81
|
process.stdout.write(`Client Instance ID: ${clientInstanceId}\n`);
|
|
82
|
+
if (metadata.featureKey) {
|
|
83
|
+
process.stdout.write(`Feature: ${metadata.featureKey}\n`);
|
|
84
|
+
}
|
|
85
|
+
if (metadata.taskKey) {
|
|
86
|
+
process.stdout.write(`Task: ${metadata.taskKey}\n`);
|
|
87
|
+
}
|
|
65
88
|
return 0;
|
|
66
89
|
}
|
|
67
90
|
if (subcommand === "heartbeat") {
|
|
@@ -74,16 +97,16 @@ export async function runSessionCommand(cliVersion, args) {
|
|
|
74
97
|
clientInstanceId,
|
|
75
98
|
branch: git.branch,
|
|
76
99
|
commitSha: git.commitHash,
|
|
77
|
-
metadata
|
|
78
|
-
source: "vp-cli",
|
|
79
|
-
rootPath,
|
|
80
|
-
},
|
|
100
|
+
metadata,
|
|
81
101
|
});
|
|
82
102
|
await updateProfileState(runtime.profile.name, {
|
|
83
103
|
lastCommand: "session:heartbeat",
|
|
84
104
|
lastError: null,
|
|
85
105
|
});
|
|
86
106
|
process.stdout.write(`Heartbeat enviado para ${sessionId}\n`);
|
|
107
|
+
if (metadata.statusSummary) {
|
|
108
|
+
process.stdout.write(`Status: ${metadata.statusSummary}\n`);
|
|
109
|
+
}
|
|
87
110
|
return 0;
|
|
88
111
|
}
|
|
89
112
|
if (subcommand === "check-out") {
|
|
@@ -95,6 +118,9 @@ export async function runSessionCommand(cliVersion, args) {
|
|
|
95
118
|
sessionId,
|
|
96
119
|
metadata: {
|
|
97
120
|
source: "vp-cli",
|
|
121
|
+
featureKey: metadata.featureKey,
|
|
122
|
+
taskKey: metadata.taskKey,
|
|
123
|
+
statusSummary: metadata.statusSummary,
|
|
98
124
|
},
|
|
99
125
|
});
|
|
100
126
|
await updateProfileState(runtime.profile.name, {
|
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, ResolveWorkspaceRequest, ResolveWorkspaceResponse, SyncRequest, SyncResponse } from "../types/api.js";
|
|
3
|
+
import type { AgentCheckoutRequest, AgentHeartbeatRequest, AgentSessionRequest, AgentSessionResponse, EventRequest, MemoryDraftCreateRequest, MemoryDraftRecord, MemoryDraftStatus, ResolveWorkspaceRequest, ResolveWorkspaceResponse, SyncRequest, SyncResponse } from "../types/api.js";
|
|
4
4
|
export declare class VectorPlaneApiClient {
|
|
5
5
|
private readonly apiBaseUrl;
|
|
6
6
|
private readonly timeoutMs;
|
|
@@ -22,6 +22,8 @@ export declare class VectorPlaneApiClient {
|
|
|
22
22
|
getWorkspaceSnapshot(accessToken: string, workspaceId: string): Promise<Record<string, unknown>>;
|
|
23
23
|
getWorkspaceDeliveryContext(accessToken: string, workspaceId: string): Promise<Record<string, unknown>>;
|
|
24
24
|
getAgentSetup(accessToken: string, workspaceId: string): Promise<Record<string, unknown>>;
|
|
25
|
+
listMemoryDrafts(accessToken: string, workspaceRef: string, status?: MemoryDraftStatus): Promise<MemoryDraftRecord[]>;
|
|
26
|
+
createMemoryDraft(accessToken: string, workspaceRef: string, payload: MemoryDraftCreateRequest): Promise<MemoryDraftRecord>;
|
|
25
27
|
checkInAgent(accessToken: string, payload: AgentSessionRequest): Promise<AgentSessionResponse>;
|
|
26
28
|
heartbeatAgent(accessToken: string, payload: AgentHeartbeatRequest): Promise<AgentSessionResponse>;
|
|
27
29
|
checkOutAgent(accessToken: string, payload: AgentCheckoutRequest): Promise<AgentSessionResponse>;
|
package/dist/core/api.js
CHANGED
|
@@ -160,6 +160,25 @@ export class VectorPlaneApiClient {
|
|
|
160
160
|
},
|
|
161
161
|
}, this.timeoutMs, this.logger);
|
|
162
162
|
}
|
|
163
|
+
async listMemoryDrafts(accessToken, workspaceRef, status) {
|
|
164
|
+
const url = new URL(`${this.apiBaseUrl}/cli/workspace/${workspaceRef}/memory-drafts`);
|
|
165
|
+
if (status) {
|
|
166
|
+
url.searchParams.set("status", status);
|
|
167
|
+
}
|
|
168
|
+
return requestJson(url.toString(), {
|
|
169
|
+
method: "GET",
|
|
170
|
+
headers: {
|
|
171
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
172
|
+
},
|
|
173
|
+
}, this.timeoutMs, this.logger);
|
|
174
|
+
}
|
|
175
|
+
async createMemoryDraft(accessToken, workspaceRef, payload) {
|
|
176
|
+
return requestJson(`${this.apiBaseUrl}/cli/workspace/${workspaceRef}/memory-drafts`, {
|
|
177
|
+
method: "POST",
|
|
178
|
+
headers: authHeaders(accessToken),
|
|
179
|
+
body: JSON.stringify(payload),
|
|
180
|
+
}, this.timeoutMs, this.logger);
|
|
181
|
+
}
|
|
163
182
|
async checkInAgent(accessToken, payload) {
|
|
164
183
|
return requestJson(`${this.apiBaseUrl}/cli/workspace/${payload.workspaceId}/agents/check-in`, {
|
|
165
184
|
method: "POST",
|
package/dist/core/cli.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export interface ParsedArgs {
|
|
|
5
5
|
export declare function parseArgs(args: string[]): ParsedArgs;
|
|
6
6
|
export declare function getStringOption(parsed: ParsedArgs, key: string): string | undefined;
|
|
7
7
|
export declare function getBooleanOption(parsed: ParsedArgs, key: string): boolean;
|
|
8
|
+
export declare function getStringListOption(parsed: ParsedArgs, key: string): string[];
|
|
8
9
|
export declare function requirePositional(parsed: ParsedArgs, index: number, message: string): string;
|
|
9
10
|
export declare function parseJsonOption(value: string | undefined, fallback?: Record<string, unknown>): Record<string, unknown>;
|
package/dist/core/cli.js
CHANGED
|
@@ -38,6 +38,16 @@ export function getBooleanOption(parsed, key) {
|
|
|
38
38
|
}
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
|
+
export function getStringListOption(parsed, key) {
|
|
42
|
+
const value = getStringOption(parsed, key);
|
|
43
|
+
if (!value) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
return [...new Set(value
|
|
47
|
+
.split(",")
|
|
48
|
+
.map((item) => item.trim())
|
|
49
|
+
.filter(Boolean))];
|
|
50
|
+
}
|
|
41
51
|
export function requirePositional(parsed, index, message) {
|
|
42
52
|
const value = parsed.positionals[index];
|
|
43
53
|
if (!value) {
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { runBootstrapCommand } from "./commands/bootstrap.js";
|
|
|
5
5
|
import { runConfigCommand } from "./commands/config.js";
|
|
6
6
|
import { runContextCommand } from "./commands/context.js";
|
|
7
7
|
import { runDoctorCommand } from "./commands/doctor.js";
|
|
8
|
+
import { runDraftCommand } from "./commands/draft.js";
|
|
8
9
|
import { runEventCommand } from "./commands/event.js";
|
|
9
10
|
import { runLoginCommand } from "./commands/login.js";
|
|
10
11
|
import { runLogoutCommand } from "./commands/logout.js";
|
|
@@ -32,6 +33,7 @@ function printHelp() {
|
|
|
32
33
|
process.stdout.write(" status\n");
|
|
33
34
|
process.stdout.write(" whoami\n");
|
|
34
35
|
process.stdout.write(" doctor\n");
|
|
36
|
+
process.stdout.write(" draft <create|list>\n");
|
|
35
37
|
process.stdout.write(" config <profile|get|set>\n");
|
|
36
38
|
process.stdout.write(" workspace <current|use|resolve|clear>\n");
|
|
37
39
|
process.stdout.write(" session <check-in|heartbeat|check-out>\n");
|
|
@@ -60,6 +62,8 @@ export async function runCli(args) {
|
|
|
60
62
|
return runWhoAmICommand(cliVersion);
|
|
61
63
|
case "doctor":
|
|
62
64
|
return runDoctorCommand(cliVersion);
|
|
65
|
+
case "draft":
|
|
66
|
+
return runDraftCommand(cliVersion, rest);
|
|
63
67
|
case "config":
|
|
64
68
|
return runConfigCommand(rest);
|
|
65
69
|
case "workspace":
|
package/dist/types/api.d.ts
CHANGED
|
@@ -59,3 +59,30 @@ export interface AgentSessionResponse {
|
|
|
59
59
|
workspaceId?: string;
|
|
60
60
|
[key: string]: unknown;
|
|
61
61
|
}
|
|
62
|
+
export type MemoryDraftType = "architecture" | "decisions" | "progress" | "patterns" | "ui" | "ux" | "template_engineering" | "project_skeleton";
|
|
63
|
+
export type MemoryDraftStatus = "draft" | "in_review" | "approved" | "merged" | "rejected" | "archived";
|
|
64
|
+
export interface MemoryDraftCreateRequest {
|
|
65
|
+
docType: MemoryDraftType;
|
|
66
|
+
title: string;
|
|
67
|
+
content: string;
|
|
68
|
+
memoryKey?: string;
|
|
69
|
+
featureKey?: string;
|
|
70
|
+
branch?: string;
|
|
71
|
+
taskKey?: string;
|
|
72
|
+
}
|
|
73
|
+
export interface MemoryDraftRecord {
|
|
74
|
+
id: string;
|
|
75
|
+
workspaceId: string;
|
|
76
|
+
docType: MemoryDraftType;
|
|
77
|
+
title: string;
|
|
78
|
+
content: string;
|
|
79
|
+
memoryKey: string | null;
|
|
80
|
+
featureKey: string | null;
|
|
81
|
+
branch: string | null;
|
|
82
|
+
taskKey: string | null;
|
|
83
|
+
status: MemoryDraftStatus;
|
|
84
|
+
suggestedMergeStrategy?: string | null;
|
|
85
|
+
createdAt: string;
|
|
86
|
+
updatedAt?: string;
|
|
87
|
+
[key: string]: unknown;
|
|
88
|
+
}
|