autosnippet 3.0.10 → 3.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.
- package/bin/cli.js +64 -1
- package/config/default.json +9 -0
- package/dashboard/dist/assets/{index-I2ySoCmF.js → index-Bnm26ulL.js} +47 -47
- package/dashboard/dist/index.html +1 -1
- package/lib/cli/SetupService.js +92 -5
- package/lib/cli/UpgradeService.js +14 -5
- package/lib/core/discovery/GenericDiscoverer.js +4 -28
- package/lib/external/mcp/handlers/bootstrap/base-dimensions.js +246 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/checkpoint.js +80 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +275 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +600 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +125 -342
- package/lib/external/mcp/handlers/bootstrap/refine.js +362 -0
- package/lib/external/mcp/handlers/bootstrap.js +6 -590
- package/lib/external/mcp/handlers/browse.js +119 -9
- package/lib/external/mcp/handlers/guard.js +25 -6
- package/lib/external/mcp/handlers/search.js +56 -24
- package/lib/http/routes/guardRules.js +9 -17
- package/lib/injection/ServiceContainer.js +12 -3
- package/lib/platform/ios/xcode/XcodeImportResolver.js +434 -0
- package/lib/platform/ios/xcode/XcodeIntegration.js +40 -659
- package/lib/platform/ios/xcode/XcodeWriteUtils.js +220 -0
- package/lib/service/chat/ChatAgent.js +39 -418
- package/lib/service/chat/ChatAgentPrompts.js +149 -0
- package/lib/service/chat/ChatAgentTasks.js +297 -0
- package/lib/service/chat/tools/_shared.js +61 -0
- package/lib/service/chat/tools/ai-analysis.js +284 -0
- package/lib/service/chat/tools/ast-graph.js +681 -0
- package/lib/service/chat/tools/composite.js +496 -0
- package/lib/service/chat/tools/guard.js +265 -0
- package/lib/service/chat/tools/index.js +250 -0
- package/lib/service/chat/tools/infrastructure.js +222 -0
- package/lib/service/chat/tools/knowledge-graph.js +234 -0
- package/lib/service/chat/tools/lifecycle.js +469 -0
- package/lib/service/chat/tools/project-access.js +923 -0
- package/lib/service/chat/tools/query.js +264 -0
- package/lib/service/chat/tools.js +14 -3994
- package/lib/service/cursor/AgentInstructionsGenerator.js +395 -0
- package/lib/service/cursor/CursorDeliveryPipeline.js +70 -11
- package/lib/service/cursor/FileProtection.js +116 -0
- package/lib/service/cursor/KnowledgeCompressor.js +61 -11
- package/lib/service/cursor/SkillsSyncer.js +5 -3
- package/lib/service/cursor/TopicClassifier.js +19 -3
- package/lib/service/guard/ExclusionManager.js +26 -2
- package/lib/service/guard/GuardCheckEngine.js +38 -370
- package/lib/service/guard/GuardCodeChecks.js +362 -0
- package/lib/service/guard/GuardCrossFileChecks.js +307 -0
- package/lib/service/guard/GuardPatternUtils.js +180 -0
- package/lib/service/guard/GuardService.js +80 -38
- package/lib/service/module/ModuleService.js +1 -0
- package/lib/service/search/SearchEngine.js +10 -2
- package/lib/service/wiki/WikiGenerator.js +226 -1532
- package/lib/service/wiki/WikiRenderers.js +1878 -0
- package/lib/service/wiki/WikiUtils.js +907 -0
- package/lib/shared/LanguageService.js +299 -0
- package/package.json +1 -1
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XcodeWriteUtils — Xcode 写入与插入工具函数
|
|
3
|
+
*
|
|
4
|
+
* 从 XcodeIntegration.js 拆分,负责:
|
|
5
|
+
* - 通用工具函数(sleep, withAutoSnippetNote)
|
|
6
|
+
* - SPM 依赖决策逻辑
|
|
7
|
+
* - Xcode osascript 写入
|
|
8
|
+
* - 文件写入回退
|
|
9
|
+
* - 粘贴行号偏移计算
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { saveEventFilter } from './SaveEventFilter.js';
|
|
14
|
+
|
|
15
|
+
export function sleep(ms) {
|
|
16
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 在 import 行末尾附加来源标记注释
|
|
21
|
+
*/
|
|
22
|
+
export function withAutoSnippetNote(importLine) {
|
|
23
|
+
if (!importLine) {
|
|
24
|
+
return importLine;
|
|
25
|
+
}
|
|
26
|
+
const note = '// AutoSnippet: 自动插入';
|
|
27
|
+
if (importLine.includes(note)) {
|
|
28
|
+
return importLine;
|
|
29
|
+
}
|
|
30
|
+
return `${importLine} ${note}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 将 SpmService.ensureDependency 返回值映射为三种动作:
|
|
35
|
+
* continue — 依赖已存在
|
|
36
|
+
* block — 循环/反向依赖,禁止插入
|
|
37
|
+
* review — 依赖缺失但可添加,需用户确认
|
|
38
|
+
*/
|
|
39
|
+
export function evaluateDepResult(ensureResult, from, to) {
|
|
40
|
+
if (ensureResult.exists) {
|
|
41
|
+
return { action: 'continue' };
|
|
42
|
+
}
|
|
43
|
+
if (!ensureResult.canAdd) {
|
|
44
|
+
return { action: 'block', reason: ensureResult.reason || 'cycleBlocked', from, to };
|
|
45
|
+
}
|
|
46
|
+
return { action: 'review', reason: ensureResult.reason || 'missingDependency', from, to };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 公共依赖审查弹窗逻辑(insertHeaders 和 _preflightDeps 共享)
|
|
51
|
+
*
|
|
52
|
+
* @param {object} ctx - { spmService, currentTarget, mod, ensureResult, NU, depWarnings, label }
|
|
53
|
+
* @returns {{ blocked: boolean }}
|
|
54
|
+
*/
|
|
55
|
+
export function handleDepReview(ctx) {
|
|
56
|
+
const { spmService, currentTarget, mod, ensureResult, NU, depWarnings, label = '' } = ctx;
|
|
57
|
+
|
|
58
|
+
const fixMode = spmService.getFixMode();
|
|
59
|
+
const buttons =
|
|
60
|
+
fixMode === 'fix'
|
|
61
|
+
? ['直接插入(信任架构)', '提示操作插入', '自动修复依赖', '取消操作']
|
|
62
|
+
: ['直接插入(信任架构)', '提示操作插入', '取消操作'];
|
|
63
|
+
|
|
64
|
+
const crossTag = ensureResult.crossPackage ? ' (跨包)' : '';
|
|
65
|
+
const prefix = label ? `[${label}] ` : '';
|
|
66
|
+
|
|
67
|
+
const userChoice = NU.promptWithButtons(
|
|
68
|
+
`检测到依赖缺失:${currentTarget} -> ${mod}${crossTag}\n\n请选择处理方式:`,
|
|
69
|
+
buttons,
|
|
70
|
+
'AutoSnippet SPM 依赖决策'
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
if (
|
|
74
|
+
userChoice === '取消操作' ||
|
|
75
|
+
(!userChoice && !['直接插入(信任架构)', '提示操作插入', '自动修复依赖'].includes(userChoice))
|
|
76
|
+
) {
|
|
77
|
+
return { blocked: true };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (userChoice === '提示操作插入') {
|
|
81
|
+
depWarnings.set(mod, `${currentTarget} -> ${mod}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (userChoice === '自动修复依赖') {
|
|
85
|
+
const fixResult = spmService.addDependency(currentTarget, mod);
|
|
86
|
+
if (fixResult.ok) {
|
|
87
|
+
NU.notify(`已补齐依赖:${currentTarget} -> ${mod}`, 'AutoSnippet SPM');
|
|
88
|
+
} else {
|
|
89
|
+
console.warn(` ⚠️ ${prefix}自动修复失败: ${fixResult.error},继续插入`);
|
|
90
|
+
depWarnings.set(mod, `${currentTarget} -> ${mod}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return { blocked: false };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ═══════════════════════════════════════════════════════════════
|
|
98
|
+
// Xcode osascript 单条 import 写入
|
|
99
|
+
// ═══════════════════════════════════════════════════════════════
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 通过 Xcode 自动化插入一条 import,保持 Xcode Undo 可用。
|
|
103
|
+
*
|
|
104
|
+
* 流程:保存剪贴板 → 写入 import 内容 → osascript 跳转+粘贴 → 恢复剪贴板
|
|
105
|
+
*
|
|
106
|
+
* @param {string} importLine 完整的 import 文本
|
|
107
|
+
* @param {number} insertLine 1-based 行号
|
|
108
|
+
* @param {object} XA XcodeAutomation 模块
|
|
109
|
+
* @param {object} CM ClipboardManager 模块
|
|
110
|
+
* @returns {boolean}
|
|
111
|
+
*/
|
|
112
|
+
export function writeImportLineXcode(importLine, insertLine, XA, CM) {
|
|
113
|
+
if (!XA.isXcodeRunning()) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const contentToWrite = `${String(importLine).trim()}\n`;
|
|
118
|
+
const previousClipboard = CM.read();
|
|
119
|
+
|
|
120
|
+
CM.write(contentToWrite);
|
|
121
|
+
const ok = XA.insertAtLineStartInXcode(insertLine);
|
|
122
|
+
|
|
123
|
+
// 始终恢复剪贴板
|
|
124
|
+
if (typeof previousClipboard === 'string') {
|
|
125
|
+
CM.write(previousClipboard);
|
|
126
|
+
}
|
|
127
|
+
return ok;
|
|
128
|
+
} catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ═══════════════════════════════════════════════════════════════
|
|
134
|
+
// 文件写入回退
|
|
135
|
+
// ═══════════════════════════════════════════════════════════════
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 纯文件写入插入单条 import。
|
|
139
|
+
* Xcode 会因文件变更而自动 reload。
|
|
140
|
+
*/
|
|
141
|
+
export function writeImportLineFile(filePath, importLine, isSwift) {
|
|
142
|
+
try {
|
|
143
|
+
const content = readFileSync(filePath, 'utf8');
|
|
144
|
+
const lines = content.split('\n');
|
|
145
|
+
let lastImportIdx = -1;
|
|
146
|
+
for (let i = 0; i < lines.length; i++) {
|
|
147
|
+
const t = lines[i].trim();
|
|
148
|
+
if (isSwift) {
|
|
149
|
+
if (t.startsWith('import ') && !t.startsWith('import (')) {
|
|
150
|
+
lastImportIdx = i;
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
if (t.startsWith('#import ') || t.startsWith('#include ') || t.startsWith('@import ')) {
|
|
154
|
+
lastImportIdx = i;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const insertAt = lastImportIdx >= 0 ? lastImportIdx + 1 : 0;
|
|
159
|
+
lines.splice(insertAt, 0, importLine);
|
|
160
|
+
const newContent = lines.join('\n');
|
|
161
|
+
saveEventFilter.markWrite(filePath, newContent);
|
|
162
|
+
writeFileSync(filePath, newContent, 'utf8');
|
|
163
|
+
return true;
|
|
164
|
+
} catch {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ═══════════════════════════════════════════════════════════════
|
|
170
|
+
// 粘贴行号偏移计算
|
|
171
|
+
// ═══════════════════════════════════════════════════════════════
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 查找文件中最后一个 import 行的行号(1-based,0 表示无 import)
|
|
175
|
+
*/
|
|
176
|
+
export function getLastImportLine(filePath) {
|
|
177
|
+
try {
|
|
178
|
+
if (!existsSync(filePath)) {
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
181
|
+
const content = readFileSync(filePath, 'utf8');
|
|
182
|
+
const lines = content.split(/\r?\n/);
|
|
183
|
+
let lastIdx = -1;
|
|
184
|
+
for (let i = 0; i < lines.length; i++) {
|
|
185
|
+
const t = lines[i].trim();
|
|
186
|
+
if (
|
|
187
|
+
t.startsWith('#import ') ||
|
|
188
|
+
t.startsWith('@import ') ||
|
|
189
|
+
t.startsWith('#include ') ||
|
|
190
|
+
t.startsWith('import ')
|
|
191
|
+
) {
|
|
192
|
+
lastIdx = i;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return lastIdx >= 0 ? lastIdx + 1 : 0;
|
|
196
|
+
} catch {
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 计算代码粘贴行号
|
|
203
|
+
*
|
|
204
|
+
* 如果 headers 插入在 trigger 行之前(import 区),trigger 行号需要向下偏移。
|
|
205
|
+
*/
|
|
206
|
+
export function computePasteLineNumber(triggerLineNumber, headerInsertCount, filePath, options = {}) {
|
|
207
|
+
const expectedCount = Number.isFinite(options.expectedHeaderCount)
|
|
208
|
+
? options.expectedHeaderCount
|
|
209
|
+
: headerInsertCount;
|
|
210
|
+
if (expectedCount > 0) {
|
|
211
|
+
if (options.forceOffset) {
|
|
212
|
+
return triggerLineNumber + expectedCount;
|
|
213
|
+
}
|
|
214
|
+
const headerInsertPosition = getLastImportLine(filePath);
|
|
215
|
+
if (headerInsertPosition > 0 && headerInsertPosition < triggerLineNumber) {
|
|
216
|
+
return triggerLineNumber + expectedCount;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return triggerLineNumber;
|
|
220
|
+
}
|