autosnippet 3.2.6 → 3.2.8
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 +16 -1
- package/bin/cli.js +7 -0
- package/dashboard/dist/assets/index-D5jiDBQG.css +1 -0
- package/dashboard/dist/assets/{index-DfHY_3ln.js → index-e5OKj-Ni.js} +38 -38
- package/dashboard/dist/index.html +2 -2
- package/lib/cli/AiScanService.js +3 -3
- package/lib/core/AstAnalyzer.js +26 -4
- package/lib/core/analysis/CallEdgeResolver.js +402 -0
- package/lib/core/analysis/CallGraphAnalyzer.js +367 -0
- package/lib/core/analysis/CallSiteExtractor.js +629 -0
- package/lib/core/analysis/DataFlowInferrer.js +57 -0
- package/lib/core/analysis/ImportPathResolver.js +189 -0
- package/lib/core/analysis/ImportRecord.js +105 -0
- package/lib/core/analysis/SymbolTableBuilder.js +211 -0
- package/lib/core/ast/ProjectGraph.js +8 -0
- package/lib/core/ast/lang-dart.js +352 -5
- package/lib/core/ast/lang-go.js +212 -10
- package/lib/core/ast/lang-java.js +205 -1
- package/lib/core/ast/lang-kotlin.js +330 -1
- package/lib/core/ast/lang-python.js +31 -2
- package/lib/core/ast/lang-rust.js +284 -3
- package/lib/core/ast/lang-swift.js +180 -1
- package/lib/core/ast/lang-typescript.js +290 -1
- package/lib/external/mcp/McpServer.js +1 -0
- package/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +21 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +5 -4
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +2 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +70 -4
- package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +95 -1
- package/lib/external/mcp/handlers/bootstrap-external.js +9 -2
- package/lib/external/mcp/handlers/bootstrap-internal.js +17 -6
- package/lib/external/mcp/handlers/consolidated.js +9 -0
- package/lib/external/mcp/handlers/guard.js +3 -3
- package/lib/external/mcp/handlers/structure.js +62 -0
- package/lib/external/mcp/handlers/task.js +182 -10
- package/lib/external/mcp/handlers/wiki-external.js +66 -3
- package/lib/external/mcp/tools.js +36 -1
- package/lib/http/HttpServer.js +4 -0
- package/lib/http/routes/remote.js +1138 -0
- package/lib/http/routes/task.js +1 -0
- package/lib/infrastructure/database/migrations/003_add_remote_commands.js +27 -0
- package/lib/injection/ServiceContainer.js +6 -11
- package/lib/platform/ios/index.js +2 -2
- package/lib/platform/ios/spm/PackageSwiftParser.js +14 -3
- package/lib/platform/ios/spm/SpmDiscoverer.js +123 -17
- package/lib/platform/ios/spm/{SpmService.js → SpmHelper.js} +43 -675
- package/lib/platform/ios/xcode/XcodeWriteUtils.js +1 -1
- package/lib/service/chat/ChatAgent.js +1 -1
- package/lib/service/chat/ChatAgentPrompts.js +13 -1
- package/lib/service/chat/ExplorationTracker.js +52 -8
- package/lib/service/chat/HandoffProtocol.js +19 -1
- package/lib/service/chat/WorkingMemory.js +3 -1
- package/lib/service/chat/memory/ActiveContext.js +3 -1
- package/lib/service/chat/memory/SessionStore.js +4 -3
- package/lib/service/chat/tools/ast-graph.js +229 -32
- package/lib/service/chat/tools/index.js +6 -1
- package/lib/service/chat/tools/infrastructure.js +5 -0
- package/lib/service/cursor/CursorDeliveryPipeline.js +167 -1
- package/lib/service/knowledge/CodeEntityGraph.js +327 -2
- package/lib/service/knowledge/KnowledgeService.js +5 -1
- package/lib/service/module/ModuleService.js +9 -0
- package/lib/service/wiki/WikiGenerator.js +1 -1
- package/lib/shared/PathGuard.js +1 -1
- package/package.json +12 -1
- package/dashboard/dist/assets/index-BaGY7kJI.css +0 -1
package/lib/http/routes/task.js
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 003 — Remote Command Queue
|
|
3
|
+
*
|
|
4
|
+
* 飞书/Telegram 等 IM 远程指令队列表
|
|
5
|
+
* VSCode 扩展轮询 pending → 注入 Copilot Chat → 回写结果
|
|
6
|
+
*/
|
|
7
|
+
export default function migrate(db) {
|
|
8
|
+
db.exec(`
|
|
9
|
+
CREATE TABLE IF NOT EXISTS remote_commands (
|
|
10
|
+
id TEXT PRIMARY KEY,
|
|
11
|
+
source TEXT NOT NULL DEFAULT 'lark',
|
|
12
|
+
chat_id TEXT,
|
|
13
|
+
message_id TEXT,
|
|
14
|
+
user_id TEXT,
|
|
15
|
+
user_name TEXT,
|
|
16
|
+
command TEXT NOT NULL,
|
|
17
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
18
|
+
result TEXT,
|
|
19
|
+
created_at INTEGER NOT NULL,
|
|
20
|
+
claimed_at INTEGER,
|
|
21
|
+
completed_at INTEGER
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
CREATE INDEX IF NOT EXISTS idx_remote_commands_status ON remote_commands(status);
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_remote_commands_created ON remote_commands(created_at);
|
|
26
|
+
`);
|
|
27
|
+
}
|
|
@@ -18,7 +18,7 @@ import { IndexingPipeline } from '../infrastructure/vector/IndexingPipeline.js';
|
|
|
18
18
|
// ─── P0: Vector Storage ──────────────────────────────
|
|
19
19
|
import { JsonVectorAdapter } from '../infrastructure/vector/JsonVectorAdapter.js';
|
|
20
20
|
// ─── P2: SPM ──────────────────────────────────────────
|
|
21
|
-
import {
|
|
21
|
+
import { SpmHelper } from '../platform/ios/spm/SpmHelper.js';
|
|
22
22
|
import { KnowledgeRepositoryImpl } from '../repository/knowledge/KnowledgeRepository.impl.js';
|
|
23
23
|
// ─── P1: Token Usage Tracking ─────────────────────────
|
|
24
24
|
import { TokenUsageStore } from '../repository/token/TokenUsageStore.js';
|
|
@@ -121,7 +121,7 @@ export class ServiceContainer {
|
|
|
121
121
|
this.singletons.skillHooks = bootstrapComponents.skillHooks;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
// AiFactory 模块引用(用于
|
|
124
|
+
// AiFactory 模块引用(用于 SpmHelper AI 扫描)
|
|
125
125
|
try {
|
|
126
126
|
this.singletons._aiFactory = await import('../external/ai/AiFactory.js');
|
|
127
127
|
} catch {
|
|
@@ -658,18 +658,11 @@ export class ServiceContainer {
|
|
|
658
658
|
return this.singletons.feedbackCollector;
|
|
659
659
|
});
|
|
660
660
|
|
|
661
|
-
//
|
|
661
|
+
// SpmHelper (SPM 包结构解析与依赖操作辅助)
|
|
662
662
|
this.register('spmService', () => {
|
|
663
663
|
if (!this.singletons.spmService) {
|
|
664
664
|
const projectRoot = this.singletons._projectRoot || process.cwd();
|
|
665
|
-
this.singletons.spmService = new
|
|
666
|
-
aiFactory: this.singletons._aiFactory || null,
|
|
667
|
-
chatAgent: this.singletons.chatAgent || null,
|
|
668
|
-
qualityScorer: this.get('qualityScorer'),
|
|
669
|
-
recipeExtractor: this.singletons._recipeExtractor || null,
|
|
670
|
-
guardCheckEngine: this.get('guardCheckEngine'),
|
|
671
|
-
violationsStore: this.get('violationsStore'),
|
|
672
|
-
});
|
|
665
|
+
this.singletons.spmService = new SpmHelper(projectRoot);
|
|
673
666
|
}
|
|
674
667
|
return this.singletons.spmService;
|
|
675
668
|
});
|
|
@@ -766,9 +759,11 @@ export class ServiceContainer {
|
|
|
766
759
|
if (!this.singletons.cursorDeliveryPipeline) {
|
|
767
760
|
const knowledgeService = this.get('knowledgeService');
|
|
768
761
|
const projectRoot = this.singletons._projectRoot || process.cwd();
|
|
762
|
+
const database = this.get('database');
|
|
769
763
|
this.singletons.cursorDeliveryPipeline = new CursorDeliveryPipeline({
|
|
770
764
|
knowledgeService,
|
|
771
765
|
projectRoot,
|
|
766
|
+
database,
|
|
772
767
|
logger: this.logger,
|
|
773
768
|
});
|
|
774
769
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* PlaceholderConverter.js — Xcode <#…#> ↔ VSCode ${N:…} 占位符转换
|
|
15
15
|
*
|
|
16
16
|
* spm/
|
|
17
|
-
*
|
|
17
|
+
* SpmHelper.js — SPM 包结构解析与依赖操作辅助工具
|
|
18
18
|
* SpmDiscoverer.js — SPM 项目自动发现(ProjectDiscoverer 接口)
|
|
19
19
|
* PackageSwiftParser.js — Package.swift 解析器
|
|
20
20
|
* DependencyGraph.js — SPM Target 依赖图
|
|
@@ -36,7 +36,7 @@ export { PackageSwiftParser } from './spm/PackageSwiftParser.js';
|
|
|
36
36
|
export { PolicyEngine } from './spm/PolicyEngine.js';
|
|
37
37
|
export { SpmDiscoverer } from './spm/SpmDiscoverer.js';
|
|
38
38
|
// ── Swift Package Manager ──
|
|
39
|
-
export {
|
|
39
|
+
export { SpmHelper } from './spm/SpmHelper.js';
|
|
40
40
|
export { saveEventFilter } from './xcode/SaveEventFilter.js';
|
|
41
41
|
// ── Xcode IDE 自动化 ──
|
|
42
42
|
export {
|
|
@@ -218,10 +218,11 @@ export class PackageSwiftParser {
|
|
|
218
218
|
|
|
219
219
|
#extractDependencies(content) {
|
|
220
220
|
const deps = [];
|
|
221
|
-
|
|
221
|
+
|
|
222
|
+
// 1. URL 依赖: .package(url: "...", ...)
|
|
223
|
+
const urlRe = /\.package\s*\(\s*url\s*:\s*"([^"]+)"[^)]*\)/g;
|
|
222
224
|
let m;
|
|
223
|
-
while ((m =
|
|
224
|
-
// 提取版本约束
|
|
225
|
+
while ((m = urlRe.exec(content)) !== null) {
|
|
225
226
|
const block = m[0];
|
|
226
227
|
const fromMatch = block.match(/from\s*:\s*"([^"]+)"/);
|
|
227
228
|
const exactMatch = block.match(/exact\s*:\s*"([^"]+)"/);
|
|
@@ -231,6 +232,16 @@ export class PackageSwiftParser {
|
|
|
231
232
|
type: 'package',
|
|
232
233
|
});
|
|
233
234
|
}
|
|
235
|
+
|
|
236
|
+
// 2. Local path 依赖: .package(path: "...")
|
|
237
|
+
const pathRe = /\.package\s*\(\s*path\s*:\s*"([^"]+)"\s*\)/g;
|
|
238
|
+
while ((m = pathRe.exec(content)) !== null) {
|
|
239
|
+
deps.push({
|
|
240
|
+
path: m[1],
|
|
241
|
+
type: 'local',
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
234
245
|
return deps;
|
|
235
246
|
}
|
|
236
247
|
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module SpmDiscoverer
|
|
3
|
-
* @description 包装现有
|
|
3
|
+
* @description 包装现有 SpmHelper,适配 ProjectDiscoverer 接口
|
|
4
4
|
*
|
|
5
5
|
* 检测: 项目根或子目录存在 Package.swift
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { existsSync, readdirSync } from 'node:fs';
|
|
9
|
-
import { basename, join, relative } from 'node:path';
|
|
9
|
+
import { basename, dirname, join, relative } from 'node:path';
|
|
10
10
|
import { ProjectDiscoverer } from '../../../core/discovery/ProjectDiscoverer.js';
|
|
11
11
|
import { LanguageService } from '../../../shared/LanguageService.js';
|
|
12
|
+
import { PackageSwiftParser } from './PackageSwiftParser.js';
|
|
12
13
|
|
|
13
14
|
export class SpmDiscoverer extends ProjectDiscoverer {
|
|
14
|
-
/** @type {import('./
|
|
15
|
+
/** @type {import('./SpmHelper.js').SpmHelper|null} */
|
|
15
16
|
#spm = null;
|
|
16
17
|
#projectRoot = null;
|
|
17
18
|
|
|
@@ -52,9 +53,9 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
52
53
|
|
|
53
54
|
async load(projectRoot) {
|
|
54
55
|
this.#projectRoot = projectRoot;
|
|
55
|
-
// 动态加载
|
|
56
|
-
const {
|
|
57
|
-
this.#spm = new
|
|
56
|
+
// 动态加载 SpmHelper(避免循环导入)
|
|
57
|
+
const { SpmHelper } = await import('./SpmHelper.js');
|
|
58
|
+
this.#spm = new SpmHelper(projectRoot);
|
|
58
59
|
await this.#spm.load();
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -97,21 +98,126 @@ export class SpmDiscoverer extends ProjectDiscoverer {
|
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
async getDependencyGraph() {
|
|
100
|
-
if (!this.#
|
|
101
|
+
if (!this.#projectRoot) {
|
|
102
|
+
return { nodes: [], edges: [] };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 直接用 PackageSwiftParser 构建依赖图,不依赖 SpmHelper
|
|
106
|
+
const parser = new PackageSwiftParser(this.#projectRoot);
|
|
107
|
+
const allPkgPaths = parser.findAllPackageSwifts(this.#projectRoot);
|
|
108
|
+
|
|
109
|
+
if (allPkgPaths.length === 0) {
|
|
101
110
|
return { nodes: [], edges: [] };
|
|
102
111
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
|
|
113
|
+
const nodes = [];
|
|
114
|
+
const edges = [];
|
|
115
|
+
const pkgNameSet = new Set();
|
|
116
|
+
// targetName → 所属 packageName 映射(用于跨包 target 依赖解析)
|
|
117
|
+
const targetToPkg = new Map();
|
|
118
|
+
|
|
119
|
+
// ── 第一遍:收集所有 package + target 节点 ──
|
|
120
|
+
const allParsed = [];
|
|
121
|
+
// 记录 umbrella 包名(无 targets 且无 products 的纯组织性入口包),不作为图节点
|
|
122
|
+
const umbrellaNames = new Set();
|
|
123
|
+
for (const pkgPath of allPkgPaths) {
|
|
124
|
+
try {
|
|
125
|
+
const parsed = parser.parse(pkgPath);
|
|
126
|
+
if (pkgNameSet.has(parsed.name)) continue;
|
|
127
|
+
pkgNameSet.add(parsed.name);
|
|
128
|
+
allParsed.push({ ...parsed, _dir: dirname(pkgPath) });
|
|
129
|
+
|
|
130
|
+
// 跳过 umbrella 包(无 targets + 无 products)——它只是组织子包的入口
|
|
131
|
+
const hasTargets = parsed.targets && parsed.targets.length > 0;
|
|
132
|
+
const hasProducts = parsed.products && parsed.products.length > 0;
|
|
133
|
+
if (!hasTargets && !hasProducts) {
|
|
134
|
+
umbrellaNames.add(parsed.name);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// package 节点
|
|
139
|
+
nodes.push({
|
|
140
|
+
id: parsed.name,
|
|
141
|
+
label: parsed.name,
|
|
142
|
+
type: 'package',
|
|
143
|
+
fullPath: dirname(pkgPath),
|
|
144
|
+
targetCount: parsed.targets.length,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// target 节点
|
|
148
|
+
for (const t of parsed.targets) {
|
|
149
|
+
nodes.push({
|
|
150
|
+
id: t.name,
|
|
151
|
+
label: t.name,
|
|
152
|
+
type: 'target',
|
|
153
|
+
parent: parsed.name,
|
|
154
|
+
targetType: t.type,
|
|
155
|
+
});
|
|
156
|
+
targetToPkg.set(t.name, parsed.name);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// product name → package(product 名可能和 target 名不同)
|
|
160
|
+
for (const prod of parsed.products || []) {
|
|
161
|
+
if (!targetToPkg.has(prod.name)) {
|
|
162
|
+
targetToPkg.set(prod.name, parsed.name);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} catch {
|
|
166
|
+
// 解析失败,跳过
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ── 第二遍:构建 edges ──
|
|
171
|
+
for (const parsed of allParsed) {
|
|
172
|
+
// 跳过 umbrella 包的边
|
|
173
|
+
if (umbrellaNames.has(parsed.name)) continue;
|
|
174
|
+
|
|
175
|
+
// 包级 local path 依赖
|
|
176
|
+
for (const dep of parsed.dependencies || []) {
|
|
177
|
+
if (dep.type === 'local' && dep.path) {
|
|
178
|
+
const depPkgSwift = join(parsed._dir, dep.path, 'Package.swift');
|
|
179
|
+
if (existsSync(depPkgSwift)) {
|
|
180
|
+
try {
|
|
181
|
+
const depParsed = parser.parse(depPkgSwift);
|
|
182
|
+
// 跳过指向 umbrella 包的边
|
|
183
|
+
if (!umbrellaNames.has(depParsed.name)) {
|
|
184
|
+
edges.push({ from: parsed.name, to: depParsed.name, type: 'depends_on' });
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
const targetName = basename(dep.path);
|
|
188
|
+
if (!umbrellaNames.has(targetName)) {
|
|
189
|
+
edges.push({ from: parsed.name, to: targetName, type: 'depends_on' });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
} else if (dep.url) {
|
|
194
|
+
const remoteName = basename(dep.url).replace(/\.git$/, '');
|
|
195
|
+
if (!pkgNameSet.has(remoteName)) {
|
|
196
|
+
pkgNameSet.add(remoteName);
|
|
197
|
+
nodes.push({ id: remoteName, label: remoteName, type: 'remote', indirect: true });
|
|
198
|
+
}
|
|
199
|
+
edges.push({ from: parsed.name, to: remoteName, type: 'depends_on' });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// target 级依赖
|
|
204
|
+
for (const t of parsed.targets || []) {
|
|
205
|
+
// target → parent package (contains)
|
|
206
|
+
edges.push({ from: parsed.name, to: t.name, type: 'contains' });
|
|
207
|
+
|
|
208
|
+
for (const depName of t.dependencies || []) {
|
|
209
|
+
// target → target 依赖(跳过指向 umbrella 包的)
|
|
210
|
+
if (!umbrellaNames.has(depName)) {
|
|
211
|
+
edges.push({ from: t.name, to: depName, type: 'depends_on' });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return { nodes, edges };
|
|
112
218
|
}
|
|
113
219
|
|
|
114
|
-
/** 获取底层
|
|
220
|
+
/** 获取底层 SpmHelper(向后兼容) */
|
|
115
221
|
getSpmService() {
|
|
116
222
|
return this.#spm;
|
|
117
223
|
}
|