draftgo-cli 3.0.51 → 3.0.53

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,27 +0,0 @@
1
- 'use strict';
2
-
3
- const log = require('../logger');
4
- const { collectContext, compactContext, TASK_PROFILES } = require('../context');
5
- const { parseTimeout } = require('../timeout');
6
-
7
- function printUsage() {
8
- log.err('Usage: draftgo context --task <task> --output json');
9
- log.dim(` tasks: ${Object.keys(TASK_PROFILES).join(', ')}`);
10
- }
11
-
12
- async function contextCommand(projectDir, positional = [], flags = {}) {
13
- if (positional.length || !flags.task || (flags.output && flags.output !== 'json')) {
14
- printUsage();
15
- return 1;
16
- }
17
- const result = await collectContext(projectDir, flags.task, {
18
- timeoutMs: parseTimeout(flags.timeout),
19
- });
20
- console.log(JSON.stringify(flags.compact ? compactContext(result) : result, null, 2));
21
- return 0;
22
- }
23
-
24
- contextCommand.printUsage = printUsage;
25
- contextCommand.parseTimeout = parseTimeout;
26
-
27
- module.exports = contextCommand;
@@ -1,662 +0,0 @@
1
- 'use strict';
2
-
3
- const crypto = require('crypto');
4
- const fs = require('fs');
5
- const path = require('path');
6
- const pkg = require('../../package.json');
7
- const { RESOURCES_DIR } = require('../paths');
8
- const { loadProjectConfig } = require('../projectConfig');
9
- const { TOOL_NAMES, openToolSession } = require('../mcp/tools');
10
- const { readInstalledVersion } = require('../skill');
11
-
12
- const SKILL_ROOT = path.join(RESOURCES_DIR, 'skill');
13
- const MAX_STRUCTURED_TEXT_BYTES = 1024 * 1024;
14
- const LONG_CONTENT_RESOURCE_TYPES = Object.freeze([
15
- 'pages',
16
- 'navigations',
17
- 'docs/articles',
18
- 'custom_services',
19
- ]);
20
- const DB_META_LIST_PATH = '/api/db-meta';
21
- const DB_META_PAGE_SIZE = 100;
22
-
23
- const TASK_PROFILES = Object.freeze({
24
- frontend: {
25
- apiQueries: [
26
- { resource_type: 'pages' },
27
- { resource_type: 'navigations' },
28
- { resource_type: 'db' },
29
- ],
30
- references: [
31
- {
32
- file: 'references/architecture.md',
33
- headings: ['核心概念(30 秒)', 'App 对象是什么(1 分钟)', '技术栈(30 秒)'],
34
- },
35
- {
36
- file: 'references/modules.md',
37
- headings: ['可开发模块(开发者负责实现)', '平台内置模块(开箱即用,不需实现)'],
38
- },
39
- {
40
- file: 'references/frontend.md',
41
- headings: [
42
- '页面开发强制规则',
43
- '页面实践经验',
44
- '必须 / 禁止',
45
- '前端底座与组件库清单',
46
- '本地静态资源清单',
47
- 'GSAP 动效规范',
48
- '颜色 Token(强制)',
49
- '导航栏开发',
50
- '退出登录',
51
- '加载体验',
52
- '选择器与表单体验',
53
- ],
54
- },
55
- {
56
- file: 'references/runtime.md',
57
- headings: [
58
- 'iframe 注入机制',
59
- 'App 对象来源',
60
- 'URL 参数读取(标准三阶回落)',
61
- '全局事件',
62
- '前端全局层',
63
- ],
64
- },
65
- {
66
- file: 'references/app-api.md',
67
- headings: ['请求', '反馈', '路由', '状态', '主题', '其他'],
68
- },
69
- { file: 'references/mcp.md', headings: ['API 发现与调用'] },
70
- {
71
- file: 'references/checkout.md',
72
- headings: ['适用范围', '命令', 'Commit 流程', '409 / 412 冲突'],
73
- },
74
- ],
75
- },
76
- data: {
77
- apiQueries: [{ resource_type: 'db' }],
78
- references: [
79
- {
80
- file: 'references/modules.md',
81
- headings: ['可开发模块(开发者负责实现)', '模块选型决策'],
82
- },
83
- {
84
- file: 'references/data.md',
85
- headings: [
86
- 'DB Meta 结构',
87
- '关联关系(ref)',
88
- 'CRUD 操作范式',
89
- 'filters 操作符',
90
- 'db_meta 实时契约',
91
- '通用筛选参数(非动态 DB)',
92
- ],
93
- },
94
- { file: 'references/mcp.md', headings: ['API 发现与调用', '协议与安全'] },
95
- ],
96
- },
97
- 'custom-service': {
98
- apiQueries: [{ resource_type: 'custom_scripts' }],
99
- references: [
100
- {
101
- file: 'references/modules.md',
102
- headings: ['可开发模块(开发者负责实现)', '模块选型决策', '自定义服务边界'],
103
- },
104
- {
105
- file: 'references/custom-services.md',
106
- headings: [
107
- '最小服务',
108
- '资源读写',
109
- '触发器',
110
- '平台 SDK',
111
- '权限与运行限制',
112
- '实时 API',
113
- '验收清单',
114
- ],
115
- },
116
- {
117
- file: 'references/data.md',
118
- headings: ['自定义服务内的 draftgo.DB.Query', 'filters 操作符'],
119
- },
120
- { file: 'references/mcp.md', headings: ['API 发现与调用', '协议与安全'] },
121
- ],
122
- },
123
- aihub: {
124
- apiQueries: [
125
- { resource_type: 'aihub' },
126
- { resource_type: 'agents' },
127
- ],
128
- references: [
129
- {
130
- file: 'references/aihub.md',
131
- headings: ['条目骨架', '`data.spec` 字段地图', '观测'],
132
- },
133
- {
134
- file: 'references/chat-sdk.md',
135
- headings: [
136
- '最小接入',
137
- '协议',
138
- '配置与布局',
139
- 'JavaScript API 与事件',
140
- '历史与会话',
141
- '鉴权与安全',
142
- ],
143
- },
144
- { file: 'references/mcp.md', headings: ['API 发现与调用', '协议与安全'] },
145
- ],
146
- },
147
- content: {
148
- apiQueries: [
149
- { resource_type: 'pages' },
150
- { resource_type: 'navigations' },
151
- { resource_type: 'docs/articles' },
152
- ],
153
- references: [
154
- { file: 'references/architecture.md', headings: ['核心概念(30 秒)'] },
155
- { file: 'references/modules.md', headings: ['可开发模块(开发者负责实现)'] },
156
- {
157
- file: 'references/checkout.md',
158
- headings: ['适用范围', '命令', 'Checkout 流程', 'Commit 流程', '409 / 412 冲突'],
159
- },
160
- ],
161
- },
162
- project: {
163
- apiQueries: [
164
- { resource_type: 'pages' },
165
- { resource_type: 'navigations' },
166
- { resource_type: 'docs/articles' },
167
- { resource_type: 'db' },
168
- ],
169
- references: [
170
- {
171
- file: 'references/architecture.md',
172
- headings: ['核心概念(30 秒)', '为什么这样设计(1 分钟)', '技术栈(30 秒)'],
173
- },
174
- {
175
- file: 'references/modules.md',
176
- headings: [
177
- '可开发模块(开发者负责实现)',
178
- '平台内置模块(开箱即用,不需实现)',
179
- '模块选型决策',
180
- '自定义服务边界',
181
- ],
182
- },
183
- { file: 'references/mcp.md', headings: ['边界', 'API 发现与调用', '协议与安全'] },
184
- { file: 'references/checkout.md', headings: ['适用范围'] },
185
- ],
186
- },
187
- });
188
-
189
- const TASK_ALIASES = Object.freeze({
190
- backend: 'custom-service',
191
- service: 'custom-service',
192
- ui: 'frontend',
193
- });
194
-
195
- function normalizeTask(value) {
196
- const requested = String(value || '').trim().toLowerCase();
197
- const task = Object.prototype.hasOwnProperty.call(TASK_ALIASES, requested)
198
- ? TASK_ALIASES[requested]
199
- : requested;
200
- if (!Object.prototype.hasOwnProperty.call(TASK_PROFILES, task)) {
201
- const supported = Object.keys(TASK_PROFILES).join(', ');
202
- throw new Error(`Unsupported context task: ${requested || '(empty)'}. Supported tasks: ${supported}.`);
203
- }
204
- return task;
205
- }
206
-
207
- function lineNumberAt(source, offset) {
208
- let line = 1;
209
- for (let index = 0; index < offset; index += 1) {
210
- if (source.charCodeAt(index) === 10) line += 1;
211
- }
212
- return line;
213
- }
214
-
215
- function sectionEndLine(content, startLine) {
216
- let newlines = 0;
217
- for (let index = 0; index < content.length; index += 1) {
218
- if (content.charCodeAt(index) === 10) newlines += 1;
219
- }
220
- return startLine + newlines - (content.endsWith('\n') ? 1 : 0);
221
- }
222
-
223
- function extractSections(source, requestedHeadings, sourcePath) {
224
- const matches = [...source.matchAll(/^## ([^\r\n]+)\r?$/gm)];
225
- const wanted = requestedHeadings ? new Set(requestedHeadings) : null;
226
- const sections = [];
227
-
228
- if (matches.length && matches[0].index > 0) {
229
- const content = source.slice(0, matches[0].index);
230
- const title = content.match(/^# ([^\r\n]+)\r?$/m);
231
- sections.push({
232
- source: {
233
- kind: 'bundled_reference',
234
- path: sourcePath,
235
- heading: title ? title[1] : '(preamble)',
236
- line_start: 1,
237
- line_end: sectionEndLine(content, 1),
238
- sha256: crypto.createHash('sha256').update(content, 'utf8').digest('hex'),
239
- },
240
- content,
241
- });
242
- }
243
-
244
- for (let index = 0; index < matches.length; index += 1) {
245
- const match = matches[index];
246
- const heading = match[1];
247
- if (wanted && !wanted.has(heading)) continue;
248
- const start = match.index;
249
- const end = index + 1 < matches.length ? matches[index + 1].index : source.length;
250
- const content = source.slice(start, end);
251
- const startLine = lineNumberAt(source, start);
252
- sections.push({
253
- source: {
254
- kind: 'bundled_reference',
255
- path: sourcePath,
256
- heading,
257
- line_start: startLine,
258
- line_end: sectionEndLine(content, startLine),
259
- sha256: crypto.createHash('sha256').update(content, 'utf8').digest('hex'),
260
- },
261
- content,
262
- });
263
- }
264
-
265
- if (wanted) {
266
- const found = new Set(matches.map((match) => match[1]));
267
- const missing = requestedHeadings.filter((heading) => !found.has(heading));
268
- if (missing.length) {
269
- throw new Error(`${sourcePath} is missing required sections: ${missing.join(', ')}.`);
270
- }
271
- }
272
- if (!sections.length) throw new Error(`${sourcePath} contains no selectable reference sections.`);
273
- return sections;
274
- }
275
-
276
- function readTaskReferences(taskValue, options = {}) {
277
- const task = normalizeTask(taskValue);
278
- const skillRoot = options.skillRoot || SKILL_ROOT;
279
- return TASK_PROFILES[task].references.flatMap((entry) => {
280
- const absolute = path.join(skillRoot, entry.file);
281
- const source = fs.readFileSync(absolute, 'utf8');
282
- const sourcePath = path.posix.join('resources/skill', entry.file.replace(/\\/g, '/'));
283
- return extractSections(source, entry.headings, sourcePath);
284
- });
285
- }
286
-
287
- function rawQuery(session, expectedName, args, server, options = {}) {
288
- const tool = session.names[expectedName] || expectedName;
289
- return session.client.toolsCall(tool, args, options).then((result) => ({
290
- source: {
291
- kind: 'mcp_tool',
292
- server,
293
- tool,
294
- canonical_tool: expectedName,
295
- arguments: args,
296
- fetched_at: new Date().toISOString(),
297
- },
298
- result,
299
- }));
300
- }
301
-
302
- function structuredValueFromRaw(result) {
303
- let value = result;
304
- if (value && value.result) value = value.result;
305
- if (value && value.structuredContent) value = value.structuredContent;
306
- else if (value && value.structured_content) value = value.structured_content;
307
- else if (value && Array.isArray(value.content)) {
308
- const text = value.content.find((part) =>
309
- part && part.type === 'text' && typeof part.text === 'string');
310
- if (text) {
311
- if (Buffer.byteLength(text.text, 'utf8') > MAX_STRUCTURED_TEXT_BYTES) {
312
- throw new Error('DraftGo MCP pagination result exceeded the structured JSON limit.');
313
- }
314
- try {
315
- value = JSON.parse(text.text);
316
- } catch {
317
- throw new Error('DraftGo MCP pagination result did not contain structured JSON.');
318
- }
319
- }
320
- }
321
- if (value && value.data) value = value.data;
322
- if (value && Object.prototype.hasOwnProperty.call(value, 'value')) value = value.value;
323
- return value;
324
- }
325
-
326
- function nextCursorFromRaw(result) {
327
- const value = structuredValueFromRaw(result);
328
- if (!value || typeof value !== 'object') return null;
329
- const hasMore = value.has_more === true || value.hasMore === true;
330
- let cursor = null;
331
- let hasCursor = false;
332
- if (Object.prototype.hasOwnProperty.call(value, 'next_cursor')) {
333
- cursor = value.next_cursor;
334
- hasCursor = true;
335
- } else if (Object.prototype.hasOwnProperty.call(value, 'nextCursor')) {
336
- cursor = value.nextCursor;
337
- hasCursor = true;
338
- } else if (hasMore && Object.prototype.hasOwnProperty.call(value, 'cursor')) {
339
- cursor = value.cursor;
340
- hasCursor = true;
341
- }
342
- if (hasMore && (!hasCursor || cursor == null || cursor === '')) {
343
- throw new Error('DraftGo MCP pagination reported more results without a cursor.');
344
- }
345
- return hasCursor ? cursor : null;
346
- }
347
-
348
- async function collectLongContentResources(session, server, options = {}) {
349
- const sequences = await Promise.all(LONG_CONTENT_RESOURCE_TYPES.map((resourceType) =>
350
- rawPagedQuery(
351
- session,
352
- TOOL_NAMES.resourceList,
353
- { resource_type: resourceType, limit: 100 },
354
- server,
355
- options,
356
- )));
357
- return {
358
- source: {
359
- kind: 'mcp_tool_batch',
360
- server,
361
- canonical_tool: TOOL_NAMES.resourceList,
362
- arguments: LONG_CONTENT_RESOURCE_TYPES.map((resourceType) => ({
363
- resource_type: resourceType,
364
- limit: 100,
365
- })),
366
- },
367
- pages: sequences.flatMap((sequence) => sequence.pages),
368
- };
369
- }
370
-
371
- async function collectTaskAPIs(session, queries, server, options = {}) {
372
- const argumentsList = queries.map((query) => ({ ...query, limit: 100 }));
373
- const sequences = await Promise.all(argumentsList.map((args) =>
374
- rawPagedQuery(session, TOOL_NAMES.apiSearch, args, server, options)));
375
- return {
376
- source: {
377
- kind: 'mcp_tool_batch',
378
- server,
379
- canonical_tool: TOOL_NAMES.apiSearch,
380
- arguments: argumentsList,
381
- },
382
- pages: sequences.flatMap((sequence) => sequence.pages),
383
- };
384
- }
385
-
386
- function itemsFromRawSequence(sequence) {
387
- if (!sequence || !Array.isArray(sequence.pages)) return [];
388
- return sequence.pages.flatMap((page) => {
389
- const value = structuredValueFromRaw(page);
390
- if (Array.isArray(value)) return value;
391
- if (value && Array.isArray(value.items)) return value.items;
392
- if (value && Array.isArray(value.operations)) return value.operations;
393
- return [];
394
- });
395
- }
396
-
397
- function selectDBMetaListOperation(sequence) {
398
- return itemsFromRawSequence(sequence).find((operation) => {
399
- if (!operation || typeof operation !== 'object') return false;
400
- const method = String(operation.method || '').trim().toUpperCase();
401
- const resourceType = String(operation.resource_type || '').trim().toLowerCase();
402
- const operationPath = String(operation.path || operation.path_template || '').trim();
403
- return method === 'GET'
404
- && resourceType === 'db_meta'
405
- && operationPath === DB_META_LIST_PATH
406
- && operation.destructive !== true;
407
- }) || null;
408
- }
409
-
410
- function optionalPageInteger(value, field, minimum) {
411
- if (value == null) return null;
412
- if (!Number.isSafeInteger(value) || value < minimum) {
413
- throw new Error(`DraftGo db_meta API returned invalid ${field}.`);
414
- }
415
- return value;
416
- }
417
-
418
- function dbMetaPageInfo(response) {
419
- let value = structuredValueFromRaw(response);
420
- if (value && value.response) value = value.response;
421
- if (value && value.data) value = value.data;
422
- if (!value || typeof value !== 'object' || !Array.isArray(value.items)) return null;
423
- return {
424
- items: value.items,
425
- total: optionalPageInteger(value.total, 'total', 0),
426
- page: optionalPageInteger(value.page, 'page', 1),
427
- pageSize: optionalPageInteger(value.page_size, 'page_size', 1),
428
- };
429
- }
430
-
431
- async function rawPagedQuery(session, expectedName, baseArgs, server, options = {}) {
432
- const pages = [];
433
- const seen = new Set();
434
- const maxPages = options.maxPages == null ? 100 : Number(options.maxPages);
435
- if (!Number.isSafeInteger(maxPages) || maxPages < 1) {
436
- throw new TypeError('maxPages must be a positive integer.');
437
- }
438
- let cursor = null;
439
-
440
- for (let page = 0; page < maxPages; page += 1) {
441
- const args = cursor == null ? { ...baseArgs } : { ...baseArgs, cursor };
442
- const response = await rawQuery(session, expectedName, args, server, options);
443
- pages.push(response);
444
- const next = nextCursorFromRaw(response.result);
445
- if (next == null || next === '') {
446
- return {
447
- source: {
448
- kind: 'mcp_tool_sequence',
449
- server,
450
- canonical_tool: expectedName,
451
- arguments: baseArgs,
452
- },
453
- pages,
454
- };
455
- }
456
- const key = String(next);
457
- if (seen.has(key)) throw new Error(expectedName + ' repeated a cursor.');
458
- seen.add(key);
459
- cursor = next;
460
- }
461
- throw new Error(expectedName + ' exceeded ' + maxPages + ' pages.');
462
- }
463
-
464
- async function collectDBMetaResources(session, operationID, server, options = {}) {
465
- const pages = [];
466
- let fetchedItems = 0;
467
- let reportedTotal = null;
468
- const maxPages = options.maxPages == null ? 100 : Number(options.maxPages);
469
- if (!Number.isSafeInteger(maxPages) || maxPages < 1) {
470
- throw new TypeError('maxPages must be a positive integer.');
471
- }
472
- for (let page = 1; page <= maxPages; page += 1) {
473
- const args = {
474
- operation_id: operationID,
475
- query: { page, page_size: DB_META_PAGE_SIZE },
476
- };
477
- const response = await rawQuery(session, TOOL_NAMES.apiCall, args, server, options);
478
- pages.push(response);
479
- const info = dbMetaPageInfo(response);
480
- if (!info) {
481
- return {
482
- source: {
483
- kind: 'mcp_tool_sequence',
484
- server,
485
- canonical_tool: TOOL_NAMES.apiCall,
486
- operation_id: operationID,
487
- },
488
- pages,
489
- pagination: { complete: false, reason: 'response_shape_unavailable' },
490
- };
491
- }
492
- const responsePage = info.page || page;
493
- const responsePageSize = info.pageSize || DB_META_PAGE_SIZE;
494
- if (responsePage !== page) {
495
- throw new Error(`DraftGo db_meta API returned page ${responsePage} while page ${page} was requested.`);
496
- }
497
- fetchedItems += info.items.length;
498
- if (info.total != null) {
499
- if (reportedTotal != null && info.total !== reportedTotal) {
500
- throw new Error(`DraftGo db_meta API changed total from ${reportedTotal} to ${info.total} during pagination.`);
501
- }
502
- reportedTotal = info.total;
503
- }
504
- if (reportedTotal != null) {
505
- if (fetchedItems >= reportedTotal) {
506
- return {
507
- source: {
508
- kind: 'mcp_tool_sequence',
509
- server,
510
- canonical_tool: TOOL_NAMES.apiCall,
511
- operation_id: operationID,
512
- },
513
- pages,
514
- pagination: { complete: true, total: reportedTotal },
515
- };
516
- }
517
- if (!info.items.length) {
518
- throw new Error('DraftGo db_meta API ended before the reported total was reached.');
519
- }
520
- } else if (info.items.length < responsePageSize) {
521
- return {
522
- source: {
523
- kind: 'mcp_tool_sequence',
524
- server,
525
- canonical_tool: TOOL_NAMES.apiCall,
526
- operation_id: operationID,
527
- },
528
- pages,
529
- pagination: { complete: true, total: null },
530
- };
531
- }
532
- }
533
- throw new Error(`DraftGo db_meta API exceeded ${maxPages} pages.`);
534
- }
535
-
536
- async function collectDataStructures(session, server, options = {}) {
537
- const api = await rawPagedQuery(
538
- session,
539
- TOOL_NAMES.apiSearch,
540
- { resource_type: 'db_meta', limit: 100 },
541
- server,
542
- options,
543
- );
544
- const operation = selectDBMetaListOperation(api);
545
- if (!operation || !operation.operation_id) {
546
- throw new Error('DraftGo MCP does not expose a read-only GET /api/db-meta operation.');
547
- }
548
- const operationID = String(operation.operation_id);
549
- const [contract, resources] = await Promise.all([
550
- rawQuery(
551
- session,
552
- TOOL_NAMES.apiDescribe,
553
- { operation_id: operationID },
554
- server,
555
- options,
556
- ),
557
- collectDBMetaResources(session, operationID, server, options),
558
- ]);
559
- return { api, contract, resources };
560
- }
561
-
562
- async function collectContext(projectDir, taskValue, options = {}) {
563
- const task = normalizeTask(taskValue);
564
- const profile = TASK_PROFILES[task];
565
- const references = readTaskReferences(task, options);
566
- const installedSkillVersion = readInstalledSkillVersion(projectDir);
567
- const config = options.config || loadProjectConfig(projectDir);
568
- const expected = [
569
- TOOL_NAMES.projectOverview,
570
- TOOL_NAMES.resourceList,
571
- TOOL_NAMES.apiSearch,
572
- TOOL_NAMES.apiDescribe,
573
- TOOL_NAMES.apiCall,
574
- ];
575
- const openSession = options.openToolSession || openToolSession;
576
- const session = options.session || await openSession(config, expected, options);
577
- const controller = new AbortController();
578
- const externalSignal = options.signal;
579
- const forwardAbort = () => controller.abort(externalSignal.reason);
580
- if (externalSignal) {
581
- if (externalSignal.aborted) forwardAbort();
582
- else externalSignal.addEventListener('abort', forwardAbort, { once: true });
583
- }
584
-
585
- let project;
586
- let resources;
587
- let api;
588
- let dataStructures;
589
- try {
590
- const queryOptions = { ...options, signal: controller.signal };
591
- [project, resources, api, dataStructures] = await Promise.all([
592
- rawQuery(session, TOOL_NAMES.projectOverview, {}, config.server, queryOptions),
593
- collectLongContentResources(session, config.server, queryOptions),
594
- collectTaskAPIs(session, profile.apiQueries, config.server, queryOptions),
595
- collectDataStructures(session, config.server, queryOptions),
596
- ]);
597
- } catch (error) {
598
- if (!controller.signal.aborted) controller.abort(error);
599
- throw error;
600
- } finally {
601
- if (externalSignal) externalSignal.removeEventListener('abort', forwardAbort);
602
- }
603
-
604
- return {
605
- schema_version: '2.0',
606
- task,
607
- bundled_references: {
608
- source: 'draftgo-cli',
609
- version: pkg.version,
610
- installed_skill_version: installedSkillVersion,
611
- synchronized: installedSkillVersion == null ? null : installedSkillVersion === pkg.version,
612
- sections: references.map((entry) => ({
613
- ...entry,
614
- source: { ...entry.source, source: 'cli_bundle', version: pkg.version },
615
- })),
616
- },
617
- live_project: project,
618
- live_resources: resources,
619
- live_apis: api,
620
- live_db_meta: dataStructures,
621
- live_session: {
622
- server: config.server,
623
- protocol_version: session.client.protocolVersion,
624
- fetched_at: new Date().toISOString(),
625
- },
626
- };
627
- }
628
-
629
- function compactContext(value) {
630
- if (Array.isArray(value)) return value.map(compactContext);
631
- if (!value || typeof value !== 'object') return value;
632
- if (value.source && Object.prototype.hasOwnProperty.call(value, 'result')) {
633
- return { source: compactContext(value.source), value: structuredValueFromRaw(value.result) };
634
- }
635
- const result = {};
636
- for (const [key, child] of Object.entries(value)) result[key] = compactContext(child);
637
- return result;
638
- }
639
-
640
- function readInstalledSkillVersion(projectDir) {
641
- return readInstalledVersion(projectDir);
642
- }
643
-
644
- module.exports = {
645
- TASK_PROFILES,
646
- normalizeTask,
647
- extractSections,
648
- readTaskReferences,
649
- structuredValueFromRaw,
650
- nextCursorFromRaw,
651
- rawPagedQuery,
652
- collectLongContentResources,
653
- collectTaskAPIs,
654
- itemsFromRawSequence,
655
- selectDBMetaListOperation,
656
- dbMetaPageInfo,
657
- collectDBMetaResources,
658
- collectDataStructures,
659
- readInstalledSkillVersion,
660
- collectContext,
661
- compactContext,
662
- };