@xfe-repo/cli 2.0.11 → 2.0.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.
@@ -1,262 +0,0 @@
1
- /**
2
- * XFE CLI Server/Task 静态命令。
3
- *
4
- * 负责本地 server 启动、远端任务创建和 client request 交互循环。
5
- */
6
- import { createInterface } from 'node:readline/promises';
7
- import { DEFAULT_SERVER_PORT, startServer } from '@xfe-repo/server';
8
- import { HttpBackendGateway } from './http-backend.js';
9
- // ─── Public API ─────────────────────────────────────────────
10
- export function registerServerCommands(program) {
11
- const serverCmd = program.command('server').helpCommand(false).description('XFE Server 管理');
12
- serverCmd
13
- .command('start')
14
- .description('启动本地 xfe server')
15
- .option('-p, --port <port>', `监听端口,默认 ${DEFAULT_SERVER_PORT}`)
16
- .option('-H, --host <host>', '监听地址')
17
- .action((options) => {
18
- const server = startServer({ port: resolvePort(options.port), hostname: options.host });
19
- printServerStarted(server);
20
- bindServerSignals(server);
21
- });
22
- }
23
- export function registerTaskCommands(program) {
24
- const taskCmd = program.command('task').helpCommand(false).description('远端/本地 XFE Server 任务');
25
- registerTaskCreateCommand(taskCmd);
26
- registerTaskStartCommand(taskCmd);
27
- registerRequestCommands(taskCmd);
28
- }
29
- // ─── Task Commands ─────────────────────────────────────────
30
- function registerTaskCreateCommand(taskCmd) {
31
- taskCmd
32
- .command('create')
33
- .description('通过 xfe server 创建远端 agent 任务')
34
- .requiredOption('--repo <repoUrl>', 'Git 仓库地址')
35
- .requiredOption('--task <taskId>', '任务号,例如 3600')
36
- .requiredOption('--description <description>', '任务需求描述')
37
- .option('--server <url>', `server 地址,默认 http://localhost:${DEFAULT_SERVER_PORT}`)
38
- .option('--tenant <tenantId>', '租户 ID,本地默认 local')
39
- .option('--document-url <url>', '需求文档链接')
40
- .option('--base-branch <branch>', '基准分支,默认 main')
41
- .option('--branch <branchName>', '任务分支,默认 feat-${taskId}')
42
- .option('--workflow <workflowId>', '任务流程 ID,默认 plan-code-review')
43
- .option('--prepare-workspace', '创建任务后立即 clone 仓库并创建任务分支')
44
- .option('--start', '创建任务后启动 agent workflow')
45
- .option('--executor <executor>', 'agent executor,mock | codex | claude | copilot')
46
- .option('--auto-approve', '启动 agent workflow 后自动通过计划审批')
47
- .action(async (options) => {
48
- const gateway = createBackendGateway(options);
49
- const result = await gateway.createTask(createRemoteTaskPayload(options));
50
- printJson(result);
51
- if (!options.start)
52
- return;
53
- printJson(await gateway.startTask({ taskId: options.task, executor: options.executor, autoApprove: options.autoApprove }));
54
- });
55
- }
56
- function registerTaskStartCommand(taskCmd) {
57
- taskCmd
58
- .command('start <taskId>')
59
- .description('启动已创建的 agent workflow')
60
- .option('--executor <executor>', 'agent executor,mock | codex | claude | copilot')
61
- .option('--auto-approve', '自动通过计划审批')
62
- .option('--server <url>', `server 地址,默认 http://localhost:${DEFAULT_SERVER_PORT}`)
63
- .option('--tenant <tenantId>', '租户 ID,本地默认 local')
64
- .action(async (taskId, options) => {
65
- const gateway = createBackendGateway(options);
66
- printJson(await gateway.startTask({ taskId, executor: options.executor, autoApprove: options.autoApprove }));
67
- });
68
- }
69
- function registerRequestCommands(taskCmd) {
70
- taskCmd
71
- .command('requests')
72
- .description('列出等待用户处理的 ask/approval 请求')
73
- .option('--status <status>', '请求状态,默认不过滤')
74
- .option('--server <url>', `server 地址,默认 http://localhost:${DEFAULT_SERVER_PORT}`)
75
- .option('--tenant <tenantId>', '租户 ID,本地默认 local')
76
- .action(async (options) => {
77
- printJson(await createBackendGateway(options).listClientRequests({ status: options.status }));
78
- });
79
- taskCmd
80
- .command('watch')
81
- .description('监听并处理等待用户处理的 ask/approval 请求')
82
- .option('--server <url>', `server 地址,默认 http://localhost:${DEFAULT_SERVER_PORT}`)
83
- .option('--tenant <tenantId>', '租户 ID,本地默认 local')
84
- .option('--interval <ms>', '轮询间隔,默认 1000')
85
- .option('--once', '只处理当前 pending 请求后退出')
86
- .action(async (options) => {
87
- await watchClientRequests({ gateway: createBackendGateway(options), intervalMs: resolvePollInterval(options.interval), once: Boolean(options.once) });
88
- });
89
- taskCmd
90
- .command('respond <requestId>')
91
- .description('响应 ask/approval 请求')
92
- .requiredOption('--action <action>', 'accept | decline | cancel')
93
- .option('--content <json>', '响应内容 JSON')
94
- .option('--server <url>', `server 地址,默认 http://localhost:${DEFAULT_SERVER_PORT}`)
95
- .option('--tenant <tenantId>', '租户 ID,本地默认 local')
96
- .action(async (requestId, options) => {
97
- const result = await createBackendGateway(options).respondClientRequest({
98
- requestId,
99
- action: parseResponseAction(options.action),
100
- content: parseJsonRecord(options.content),
101
- });
102
- printJson(result);
103
- });
104
- }
105
- // ─── Watch Flow ────────────────────────────────────────────
106
- async function watchClientRequests(options) {
107
- const terminal = createInterface({ input: process.stdin, output: process.stdout });
108
- const handledRequestIds = new Set();
109
- try {
110
- while (true) {
111
- await handlePendingRequests(terminal, options.gateway, handledRequestIds);
112
- if (options.once)
113
- return;
114
- await wait(options.intervalMs);
115
- }
116
- }
117
- finally {
118
- terminal.close();
119
- }
120
- }
121
- async function handlePendingRequests(terminal, gateway, handledRequestIds) {
122
- const requests = await listPendingClientRequests(gateway, handledRequestIds);
123
- for (const request of requests) {
124
- handledRequestIds.add(request.id);
125
- const response = await promptClientRequest(terminal, request);
126
- await gateway.respondClientRequest({ requestId: request.id, action: response.action, content: response.content });
127
- }
128
- }
129
- async function listPendingClientRequests(gateway, handledRequestIds) {
130
- const response = await gateway.listClientRequests({ status: 'pending' });
131
- return extractClientRequests(response).filter((request) => !handledRequestIds.has(request.id));
132
- }
133
- async function promptClientRequest(terminal, request) {
134
- console.log(`\n[${request.kind}] ${request.id}`);
135
- console.log(request.message);
136
- if (isActionOnlyRequest(request.kind))
137
- return { action: await promptAction(terminal), content: undefined };
138
- return { action: 'accept', content: await promptSchemaContent(terminal, request.schema) };
139
- }
140
- async function promptAction(terminal) {
141
- const answer = await terminal.question('处理方式 accept/decline/cancel,默认 accept: ');
142
- const normalizedAnswer = answer.trim().toLowerCase();
143
- if (!normalizedAnswer)
144
- return 'accept';
145
- if (normalizedAnswer === 'a' || normalizedAnswer === 'accept')
146
- return 'accept';
147
- if (normalizedAnswer === 'd' || normalizedAnswer === 'decline')
148
- return 'decline';
149
- if (normalizedAnswer === 'c' || normalizedAnswer === 'cancel')
150
- return 'cancel';
151
- throw new Error('处理方式必须是 accept、decline 或 cancel');
152
- }
153
- async function promptSchemaContent(terminal, schema) {
154
- const fields = extractSchemaFields(schema);
155
- if (fields.length === 0)
156
- return undefined;
157
- const content = {};
158
- for (const field of fields) {
159
- content[field.name] = await promptSchemaField(terminal, field);
160
- }
161
- return content;
162
- }
163
- async function promptSchemaField(terminal, field) {
164
- const enumText = field.enumValues?.length ? ` (${field.enumValues.join(' | ')})` : '';
165
- const defaultText = field.defaultValue === undefined ? '' : `,默认 ${String(field.defaultValue)}`;
166
- const answer = await terminal.question(`${field.title}${enumText}${defaultText}: `);
167
- const value = answer.trim() || field.defaultValue;
168
- if (field.type === 'boolean')
169
- return parseBooleanField(value);
170
- if (field.type === 'number' || field.type === 'integer')
171
- return Number(value);
172
- return String(value ?? '');
173
- }
174
- function createRemoteTaskPayload(options) {
175
- return {
176
- repoUrl: options.repo,
177
- taskId: options.task,
178
- description: options.description,
179
- documentUrl: options.documentUrl,
180
- baseBranch: options.baseBranch,
181
- branchName: options.branch,
182
- workflowId: options.workflow,
183
- prepareWorkspace: options.prepareWorkspace,
184
- };
185
- }
186
- function createBackendGateway(options) {
187
- return new HttpBackendGateway({ baseUrl: options.server ?? `http://localhost:${DEFAULT_SERVER_PORT}`, tenantId: options.tenant });
188
- }
189
- function printServerStarted(server) {
190
- console.log(`XFE Server listening on ${server.hostname}:${server.port}`);
191
- console.log(`HTTP health: http://${server.hostname}:${server.port}/health`);
192
- }
193
- function bindServerSignals(server) {
194
- process.once('SIGINT', () => void stopLocalServer(server));
195
- process.once('SIGTERM', () => void stopLocalServer(server));
196
- }
197
- async function stopLocalServer(server) {
198
- await server.close();
199
- process.exit(0);
200
- }
201
- function resolvePort(rawPort) {
202
- const port = Number(rawPort);
203
- return Number.isInteger(port) && port > 0 ? port : DEFAULT_SERVER_PORT;
204
- }
205
- function resolvePollInterval(rawInterval) {
206
- const intervalMs = Number(rawInterval);
207
- return Number.isInteger(intervalMs) && intervalMs > 0 ? intervalMs : 1000;
208
- }
209
- function parseResponseAction(action) {
210
- if (action === 'accept' || action === 'decline' || action === 'cancel')
211
- return action;
212
- throw new Error('action 必须是 accept、decline 或 cancel');
213
- }
214
- function parseJsonRecord(content) {
215
- if (!content)
216
- return undefined;
217
- const parsed = JSON.parse(content);
218
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
219
- throw new Error('content 必须是 JSON object');
220
- return parsed;
221
- }
222
- function extractClientRequests(response) {
223
- if (!isRecord(response) || !Array.isArray(response.requests))
224
- return [];
225
- return response.requests.filter(isClientRequestView);
226
- }
227
- function isClientRequestView(value) {
228
- if (!isRecord(value))
229
- return false;
230
- return typeof value.id === 'string' && typeof value.kind === 'string' && typeof value.status === 'string' && typeof value.message === 'string';
231
- }
232
- function extractSchemaFields(schema) {
233
- if (!schema || !isRecord(schema.properties))
234
- return [];
235
- return Object.entries(schema.properties).map(([name, value]) => createSchemaField(name, value));
236
- }
237
- function createSchemaField(name, value) {
238
- const property = isRecord(value) ? value : {};
239
- const enumValues = Array.isArray(property.enum) ? property.enum.filter((item) => typeof item === 'string') : undefined;
240
- const title = typeof property.title === 'string' ? property.title : name;
241
- const type = typeof property.type === 'string' ? property.type : undefined;
242
- return { name, title, type, enumValues, defaultValue: property.default };
243
- }
244
- function isActionOnlyRequest(kind) {
245
- return kind === 'approval' || kind === 'permission' || kind === 'confirm';
246
- }
247
- function parseBooleanField(value) {
248
- if (typeof value === 'boolean')
249
- return value;
250
- const normalizedValue = String(value).trim().toLowerCase();
251
- return normalizedValue === 'true' || normalizedValue === 'yes' || normalizedValue === 'y' || normalizedValue === '1';
252
- }
253
- function isRecord(value) {
254
- return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
255
- }
256
- function wait(intervalMs) {
257
- return new Promise((resolve) => setTimeout(resolve, intervalMs));
258
- }
259
- function printJson(value) {
260
- console.log(JSON.stringify(value, null, 2));
261
- }
262
- //# sourceMappingURL=server-task-commands.js.map
@@ -1,19 +0,0 @@
1
- /**
2
- * @xfe-repo/cli - 命令目录构造(TUI / shell 共用的命令视图聚合)
3
- *
4
- * 把 core 的 CommandWithSource 列表转换为 completion-core 的 CommandCatalogItem 树
5
- * - 同一 source 且共享 namespace 前缀的命令折叠为 group 项
6
- * - 命令支持的 options 由 Zod parameters 派生(getCommandOptionsMeta)
7
- * - 运行中命令标记为 disabled,描述加 `(运行中)` 前缀
8
- */
9
- import type { CommandWithSource } from '@xfe-repo/cli-core';
10
- import type { CommandCatalogItem } from './completion-core.js';
11
- export interface BuildCatalogOptions {
12
- /** 当前正在运行的命令名集合,用于禁用对应条目 */
13
- readonly runningCommandNames?: ReadonlySet<string>;
14
- /** 是否在末尾追加 exit 项(默认 true,TUI 使用) */
15
- readonly includeExit?: boolean;
16
- }
17
- /** 构造命令目录:按 source 分组,namespace 命令折叠为 group */
18
- export declare function buildCommandCatalog(commandsWithSource: readonly CommandWithSource[], options?: BuildCatalogOptions): CommandCatalogItem[];
19
- //# sourceMappingURL=command-catalog.d.ts.map
@@ -1,67 +0,0 @@
1
- /**
2
- * @xfe-repo/cli - 命令目录构造(TUI / shell 共用的命令视图聚合)
3
- *
4
- * 把 core 的 CommandWithSource 列表转换为 completion-core 的 CommandCatalogItem 树
5
- * - 同一 source 且共享 namespace 前缀的命令折叠为 group 项
6
- * - 命令支持的 options 由 Zod parameters 派生(getCommandOptionsMeta)
7
- * - 运行中命令标记为 disabled,描述加 `(运行中)` 前缀
8
- */
9
- import { getCommandOptionsMeta, splitCommandName } from './command.js';
10
- /** 构造命令目录:按 source 分组,namespace 命令折叠为 group */
11
- export function buildCommandCatalog(commandsWithSource, options) {
12
- const running = options?.runningCommandNames ?? new Set();
13
- const includeExit = options?.includeExit ?? true;
14
- const sourceGroups = groupBySource(commandsWithSource);
15
- const items = [];
16
- for (const entries of sourceGroups.values()) {
17
- const namespacePrefix = detectSharedNamespace(entries);
18
- if (namespacePrefix) {
19
- const children = entries.map((e) => toCatalogItem(e, running));
20
- items.push({
21
- name: namespacePrefix,
22
- description: `${children.length} 个命令`,
23
- type: 'group',
24
- children,
25
- });
26
- continue;
27
- }
28
- for (const entry of entries)
29
- items.push(toCatalogItem(entry, running));
30
- }
31
- if (includeExit)
32
- items.push({ name: 'exit', description: '退出 CLI' });
33
- return items;
34
- }
35
- // ─── Helpers ────────────────────────────────────────────────
36
- function groupBySource(commandsWithSource) {
37
- const groups = new Map();
38
- for (const entry of commandsWithSource) {
39
- const list = groups.get(entry.source) ?? [];
40
- list.push(entry);
41
- groups.set(entry.source, list);
42
- }
43
- return groups;
44
- }
45
- /** 检测一组命令是否共享同一个 namespace 前缀 */
46
- function detectSharedNamespace(entries) {
47
- if (entries.length < 2)
48
- return null;
49
- const prefixes = entries.map((e) => splitCommandName(e.command.name).namespace);
50
- const first = prefixes[0];
51
- if (!first)
52
- return null;
53
- if (prefixes.every((p) => p === first))
54
- return first;
55
- return null;
56
- }
57
- function toCatalogItem(entry, running) {
58
- const { name, simpleDescription } = entry.command;
59
- const isRunning = running.has(name);
60
- return {
61
- name,
62
- description: isRunning ? `(运行中) ${simpleDescription}` : simpleDescription,
63
- disabled: isRunning,
64
- options: getCommandOptionsMeta(entry.command.parameters),
65
- };
66
- }
67
- //# sourceMappingURL=command-catalog.js.map
package/dist/command.d.ts DELETED
@@ -1,45 +0,0 @@
1
- /**
2
- * @xfe-repo/cli - 命令元数据 / 参数解析公用工具
3
- *
4
- * 集中三类职责:
5
- * - 从命令 Zod parameters 提取 option 元数据(供 commander、TUI 补全、shell 补全共用)
6
- * - 解析 `--key value` / `--key=value` / `--flag` 形式的命令 token 为 prefilled 对象
7
- * - 拆分 `namespace:action` 形式的命令名
8
- */
9
- export interface CommandOptionMeta {
10
- readonly name: string;
11
- readonly description: string;
12
- readonly enumValues?: readonly string[];
13
- /** 是否为开关型 option(boolean,无值) */
14
- readonly isBoolean?: boolean;
15
- }
16
- export interface SplitCommandName {
17
- readonly namespace: string | null;
18
- readonly action: string;
19
- readonly full: string;
20
- }
21
- /** 从命令的 Zod parameters 提取 option 元数据;非 ZodObject 或无字段时返回 undefined */
22
- export declare function getCommandOptionsMeta(parameters: unknown): CommandOptionMeta[] | undefined;
23
- /**
24
- * 解析 `--key value` / `--key=value` / 裸 `--flag` 形式的命令 token 列表
25
- *
26
- * - 非 `--` 前缀的 token 直接跳过
27
- * - 裸 flag 视为 `'true'`
28
- * - 提供 metas 时,boolean 字段视为开关,下一 token 不会被消费
29
- */
30
- export declare function parseCommandFlagTokens(tokens: readonly string[], metas?: readonly CommandOptionMeta[]): Record<string, string>;
31
- /** 按首个 `:` 拆分命令名;无冒号时 namespace 为 null */
32
- export declare function splitCommandName(name: string): SplitCommandName;
33
- /**
34
- * 把 `<cmd...> [--flag ...]` 形式的查询拆分为命令 tokens 与 flag tokens
35
- *
36
- * - 以首个 `--token` 为分界,前面是命令部分(可能是 1~N 个 token)
37
- * - `endsWithSpace` 用于补全场景区分「正在敲」与「敲完了」
38
- * - 纯字符串拆分,不感知具体命令注册表
39
- */
40
- export declare function splitFlagTokens(rawQuery: string): {
41
- cmdTokens: string[];
42
- flagTokens: string[];
43
- endsWithSpace: boolean;
44
- } | null;
45
- //# sourceMappingURL=command.d.ts.map
package/dist/command.js DELETED
@@ -1,88 +0,0 @@
1
- /**
2
- * @xfe-repo/cli - 命令元数据 / 参数解析公用工具
3
- *
4
- * 集中三类职责:
5
- * - 从命令 Zod parameters 提取 option 元数据(供 commander、TUI 补全、shell 补全共用)
6
- * - 解析 `--key value` / `--key=value` / `--flag` 形式的命令 token 为 prefilled 对象
7
- * - 拆分 `namespace:action` 形式的命令名
8
- */
9
- import { z } from 'zod';
10
- // ─── Public API ─────────────────────────────────────────────
11
- /** 从命令的 Zod parameters 提取 option 元数据;非 ZodObject 或无字段时返回 undefined */
12
- export function getCommandOptionsMeta(parameters) {
13
- if (!(parameters instanceof z.ZodObject))
14
- return undefined;
15
- const shape = parameters.shape;
16
- const result = [];
17
- for (const [name, field] of Object.entries(shape)) {
18
- const inner = unwrapOptional(field);
19
- result.push({
20
- name,
21
- description: field.description ?? '',
22
- enumValues: inner instanceof z.ZodEnum ? inner.options : undefined,
23
- isBoolean: inner instanceof z.ZodBoolean ? true : undefined,
24
- });
25
- }
26
- return result.length > 0 ? result : undefined;
27
- }
28
- /**
29
- * 解析 `--key value` / `--key=value` / 裸 `--flag` 形式的命令 token 列表
30
- *
31
- * - 非 `--` 前缀的 token 直接跳过
32
- * - 裸 flag 视为 `'true'`
33
- * - 提供 metas 时,boolean 字段视为开关,下一 token 不会被消费
34
- */
35
- export function parseCommandFlagTokens(tokens, metas) {
36
- const result = {};
37
- const byName = new Map();
38
- for (const m of metas ?? [])
39
- byName.set(m.name, m);
40
- for (let i = 0; i < tokens.length; i++) {
41
- const curr = tokens[i];
42
- if (!curr.startsWith('--'))
43
- continue;
44
- const eq = curr.indexOf('=');
45
- if (eq >= 0) {
46
- result[curr.slice(2, eq)] = curr.slice(eq + 1);
47
- continue;
48
- }
49
- const key = curr.slice(2);
50
- const isBoolean = byName.get(key)?.isBoolean === true;
51
- const next = tokens[i + 1];
52
- const hasValue = !isBoolean && next && !next.startsWith('--');
53
- result[key] = hasValue ? (i++, next) : 'true';
54
- }
55
- return result;
56
- }
57
- /** 按首个 `:` 拆分命令名;无冒号时 namespace 为 null */
58
- export function splitCommandName(name) {
59
- const idx = name.indexOf(':');
60
- if (idx <= 0)
61
- return { namespace: null, action: name, full: name };
62
- return { namespace: name.slice(0, idx), action: name.slice(idx + 1), full: name };
63
- }
64
- /**
65
- * 把 `<cmd...> [--flag ...]` 形式的查询拆分为命令 tokens 与 flag tokens
66
- *
67
- * - 以首个 `--token` 为分界,前面是命令部分(可能是 1~N 个 token)
68
- * - `endsWithSpace` 用于补全场景区分「正在敲」与「敲完了」
69
- * - 纯字符串拆分,不感知具体命令注册表
70
- */
71
- export function splitFlagTokens(rawQuery) {
72
- const trimmedRight = rawQuery.replace(/\s+$/, '');
73
- if (!trimmedRight)
74
- return null;
75
- const endsWithSpace = trimmedRight.length < rawQuery.length;
76
- const tokens = trimmedRight.split(/\s+/);
77
- const firstFlagIdx = tokens.findIndex((t) => t.startsWith('--'));
78
- return {
79
- cmdTokens: firstFlagIdx === -1 ? tokens : tokens.slice(0, firstFlagIdx),
80
- flagTokens: firstFlagIdx === -1 ? [] : tokens.slice(firstFlagIdx),
81
- endsWithSpace,
82
- };
83
- }
84
- // ─── Helpers ────────────────────────────────────────────────
85
- function unwrapOptional(field) {
86
- return field instanceof z.ZodOptional ? field.unwrap() : field;
87
- }
88
- //# sourceMappingURL=command.js.map
@@ -1,64 +0,0 @@
1
- /**
2
- * @xfe-repo/cli - 补全核心(与 UI / shell 协议解耦)
3
- *
4
- * 集中维护:命令目录条目类型、查询/输入解析、option/value 建议计算、
5
- * 已用 flag 过滤、命令寻址、prefilled 提取、模糊匹配。
6
- *
7
- * 调用方:
8
- * - TUI Commands 组件复用全部能力(含模糊匹配 / 二级菜单 / 已用 flag 过滤)
9
- * - shell / 其他入口可按需复用 catalog 与 option 建议部分,不依赖 UI
10
- */
11
- import type { CommandOptionMeta } from './command.js';
12
- export type CommandCatalogItemType = 'command' | 'group' | 'back' | 'option' | 'value';
13
- export interface CommandCatalogItem {
14
- readonly name: string;
15
- readonly description: string;
16
- readonly disabled?: boolean;
17
- readonly type?: CommandCatalogItemType;
18
- readonly children?: CommandCatalogItem[];
19
- /** 命令支持的 options(仅 type=command 时有意义,用于 --key= 补全) */
20
- readonly options?: readonly CommandOptionMeta[];
21
- }
22
- export interface ParsedQuery {
23
- readonly activeGroup: CommandCatalogItem | null;
24
- readonly subQuery: string;
25
- readonly topQuery: string;
26
- }
27
- export type ExtrasMode = {
28
- readonly kind: 'value';
29
- readonly command: CommandCatalogItem;
30
- readonly key: string;
31
- readonly partial: string;
32
- readonly values: readonly string[];
33
- } | {
34
- readonly kind: 'name';
35
- readonly command: CommandCatalogItem;
36
- readonly partial: string;
37
- readonly usedNames: ReadonlySet<string>;
38
- };
39
- /** 解析 query 是否进入二级菜单模式 */
40
- export declare function parseQuery(query: string, options: readonly CommandCatalogItem[]): ParsedQuery;
41
- /** 顶级查询过滤 + 评分排序 */
42
- export declare function filterTopLevel(options: readonly CommandCatalogItem[], query: string): CommandCatalogItem[];
43
- /** 二级子命令过滤:同时尝试匹配完整名和 action 名 */
44
- export declare function filterSubCommands(options: readonly CommandCatalogItem[], query: string): CommandCatalogItem[];
45
- /**
46
- * 识别 `<cmd> [--k=v ...] [--partial]` 形式的输入,返回 extras 模式
47
- *
48
- * 末尾 `--key=` 进入 value 模式;`--key` / `--` / 空 进入 name 模式
49
- */
50
- export declare function parseExtrasMode(rawQuery: string, options: readonly CommandCatalogItem[]): ExtrasMode | null;
51
- /** extras 模式建议项(option 名或枚举值) */
52
- export declare function buildExtrasSuggestions(mode: ExtrasMode): CommandCatalogItem[];
53
- /** extras 模式 Tab 补全:替换末尾未完成 token,或在末尾空格后追加新 flag */
54
- export declare function applyExtrasCompletion(input: string, mode: ExtrasMode, selected: string): string;
55
- /** 输入包含 flag 时尝试解析对应命令;不依赖命令是否声明 options,仅用于建议回显 */
56
- export declare function resolveMatchedCommandWithFlags(rawQuery: string, options: readonly CommandCatalogItem[]): CommandCatalogItem | null;
57
- /** Enter 提交时把 `/cmd --k1=v1 --k2 v2` 解析为命令 + prefilled */
58
- export declare function extractCommandAndPrefilled(input: string, options: readonly CommandCatalogItem[]): {
59
- command: CommandCatalogItem | null;
60
- prefilled: Record<string, string>;
61
- };
62
- /** 判断输入是否已经包含 `--flag` token */
63
- export declare function hasFlagToken(input: string): boolean;
64
- //# sourceMappingURL=completion-core.d.ts.map