projscan 1.6.2 → 1.8.0
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/dist/core/applyFix.js +5 -46
- package/dist/core/applyFix.js.map +1 -1
- package/dist/core/embeddings.d.ts +9 -0
- package/dist/core/embeddings.js +45 -5
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/languages/LanguageAdapter.d.ts +1 -1
- package/dist/core/languages/cppAdapter.d.ts +2 -0
- package/dist/core/languages/cppAdapter.js +145 -0
- package/dist/core/languages/cppAdapter.js.map +1 -0
- package/dist/core/languages/cppCallSites.d.ts +13 -0
- package/dist/core/languages/cppCallSites.js +62 -0
- package/dist/core/languages/cppCallSites.js.map +1 -0
- package/dist/core/languages/cppCyclomatic.d.ts +25 -0
- package/dist/core/languages/cppCyclomatic.js +82 -0
- package/dist/core/languages/cppCyclomatic.js.map +1 -0
- package/dist/core/languages/cppExports.d.ts +13 -0
- package/dist/core/languages/cppExports.js +120 -0
- package/dist/core/languages/cppExports.js.map +1 -0
- package/dist/core/languages/cppFunctions.d.ts +30 -0
- package/dist/core/languages/cppFunctions.js +281 -0
- package/dist/core/languages/cppFunctions.js.map +1 -0
- package/dist/core/languages/cppImports.d.ts +25 -0
- package/dist/core/languages/cppImports.js +77 -0
- package/dist/core/languages/cppImports.js.map +1 -0
- package/dist/core/languages/cppManifests.d.ts +18 -0
- package/dist/core/languages/cppManifests.js +41 -0
- package/dist/core/languages/cppManifests.js.map +1 -0
- package/dist/core/languages/kotlinAdapter.d.ts +2 -0
- package/dist/core/languages/kotlinAdapter.js +141 -0
- package/dist/core/languages/kotlinAdapter.js.map +1 -0
- package/dist/core/languages/kotlinCallSites.d.ts +15 -0
- package/dist/core/languages/kotlinCallSites.js +62 -0
- package/dist/core/languages/kotlinCallSites.js.map +1 -0
- package/dist/core/languages/kotlinCyclomatic.d.ts +24 -0
- package/dist/core/languages/kotlinCyclomatic.js +54 -0
- package/dist/core/languages/kotlinCyclomatic.js.map +1 -0
- package/dist/core/languages/kotlinExports.d.ts +13 -0
- package/dist/core/languages/kotlinExports.js +103 -0
- package/dist/core/languages/kotlinExports.js.map +1 -0
- package/dist/core/languages/kotlinFunctions.d.ts +27 -0
- package/dist/core/languages/kotlinFunctions.js +147 -0
- package/dist/core/languages/kotlinFunctions.js.map +1 -0
- package/dist/core/languages/kotlinImports.d.ts +25 -0
- package/dist/core/languages/kotlinImports.js +74 -0
- package/dist/core/languages/kotlinImports.js.map +1 -0
- package/dist/core/languages/kotlinManifests.d.ts +20 -0
- package/dist/core/languages/kotlinManifests.js +46 -0
- package/dist/core/languages/kotlinManifests.js.map +1 -0
- package/dist/core/languages/registry.js +16 -1
- package/dist/core/languages/registry.js.map +1 -1
- package/dist/core/languages/swiftAdapter.d.ts +2 -0
- package/dist/core/languages/swiftAdapter.js +130 -0
- package/dist/core/languages/swiftAdapter.js.map +1 -0
- package/dist/core/languages/swiftCallSites.d.ts +14 -0
- package/dist/core/languages/swiftCallSites.js +60 -0
- package/dist/core/languages/swiftCallSites.js.map +1 -0
- package/dist/core/languages/swiftCyclomatic.d.ts +24 -0
- package/dist/core/languages/swiftCyclomatic.js +54 -0
- package/dist/core/languages/swiftCyclomatic.js.map +1 -0
- package/dist/core/languages/swiftExports.d.ts +13 -0
- package/dist/core/languages/swiftExports.js +95 -0
- package/dist/core/languages/swiftExports.js.map +1 -0
- package/dist/core/languages/swiftFunctions.d.ts +28 -0
- package/dist/core/languages/swiftFunctions.js +162 -0
- package/dist/core/languages/swiftFunctions.js.map +1 -0
- package/dist/core/languages/swiftImports.d.ts +26 -0
- package/dist/core/languages/swiftImports.js +45 -0
- package/dist/core/languages/swiftImports.js.map +1 -0
- package/dist/core/languages/swiftManifests.d.ts +17 -0
- package/dist/core/languages/swiftManifests.js +49 -0
- package/dist/core/languages/swiftManifests.js.map +1 -0
- package/dist/core/languages/treeSitterLoader.js +21 -1
- package/dist/core/languages/treeSitterLoader.js.map +1 -1
- package/dist/core/memory.d.ts +30 -0
- package/dist/core/memory.js +42 -0
- package/dist/core/memory.js.map +1 -1
- package/dist/core/session.d.ts +23 -4
- package/dist/core/session.js +28 -8
- package/dist/core/session.js.map +1 -1
- package/dist/core/taint.d.ts +17 -0
- package/dist/core/taint.js +19 -1
- package/dist/core/taint.js.map +1 -1
- package/dist/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/grammars/tree-sitter-kotlin.wasm +0 -0
- package/dist/grammars/tree-sitter-swift.wasm +0 -0
- package/dist/mcp/server.js +107 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/sessionTouchScanner.js +8 -2
- package/dist/mcp/sessionTouchScanner.js.map +1 -1
- package/dist/mcp/tools/_shared.d.ts +25 -1
- package/dist/mcp/tools/_shared.js.map +1 -1
- package/dist/mcp/tools/costSummary.d.ts +26 -0
- package/dist/mcp/tools/costSummary.js +152 -0
- package/dist/mcp/tools/costSummary.js.map +1 -0
- package/dist/mcp/tools/fixSuggest.js +23 -2
- package/dist/mcp/tools/fixSuggest.js.map +1 -1
- package/dist/mcp/tools/memory.js +37 -4
- package/dist/mcp/tools/memory.js.map +1 -1
- package/dist/mcp/tools/reviewWatch.d.ts +7 -0
- package/dist/mcp/tools/reviewWatch.js +228 -0
- package/dist/mcp/tools/reviewWatch.js.map +1 -0
- package/dist/mcp/tools.js +4 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/tool-manifest.json +52 -4
- package/dist/utils/atomicWrite.d.ts +26 -0
- package/dist/utils/atomicWrite.js +69 -0
- package/dist/utils/atomicWrite.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
const SWIFT_DECISION_NODES = new Set([
|
|
2
|
+
'if_statement',
|
|
3
|
+
'guard_statement',
|
|
4
|
+
'for_statement',
|
|
5
|
+
'while_statement',
|
|
6
|
+
'repeat_while_statement',
|
|
7
|
+
'do_statement',
|
|
8
|
+
'catch_block',
|
|
9
|
+
'catch_clause',
|
|
10
|
+
]);
|
|
11
|
+
/**
|
|
12
|
+
* Per-function McCabe CC for Swift. Walks `function_declaration` nodes
|
|
13
|
+
* (top-level + class/struct/protocol/extension methods). Methods inside
|
|
14
|
+
* `class Foo { func m() }` are named `Foo.m`. Closures and trailing-closure
|
|
15
|
+
* blocks aren't extracted as separate functions; their decision points
|
|
16
|
+
* fold into the enclosing function (matches projscan's convention for
|
|
17
|
+
* Rust closures and Go func literals).
|
|
18
|
+
*
|
|
19
|
+
* `switch` cases each count as +1; the `default` arm does not. Optional
|
|
20
|
+
* chaining (`?.`) and nil-coalescing (`??`) are NOT counted.
|
|
21
|
+
*/
|
|
22
|
+
export function extractSwiftFunctions(root) {
|
|
23
|
+
const out = [];
|
|
24
|
+
walk(root, null, out);
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
function walk(node, ownerName, out) {
|
|
28
|
+
if (node.type === 'class_declaration' ||
|
|
29
|
+
node.type === 'protocol_declaration' ||
|
|
30
|
+
node.type === 'extension_declaration') {
|
|
31
|
+
const name = nameOfDecl(node) ?? ownerName;
|
|
32
|
+
const body = bodyOf(node);
|
|
33
|
+
if (body) {
|
|
34
|
+
for (const child of body.namedChildren)
|
|
35
|
+
walk(child, name, out);
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (node.type === 'function_declaration' ||
|
|
40
|
+
node.type === 'init_declaration' ||
|
|
41
|
+
node.type === 'deinit_declaration' ||
|
|
42
|
+
node.type === 'subscript_declaration') {
|
|
43
|
+
let baseName;
|
|
44
|
+
if (node.type === 'init_declaration')
|
|
45
|
+
baseName = 'init';
|
|
46
|
+
else if (node.type === 'deinit_declaration')
|
|
47
|
+
baseName = 'deinit';
|
|
48
|
+
else if (node.type === 'subscript_declaration')
|
|
49
|
+
baseName = 'subscript';
|
|
50
|
+
else
|
|
51
|
+
baseName = nameOfDecl(node) ?? '<anonymous>';
|
|
52
|
+
const fnName = ownerName ? `${ownerName}.${baseName}` : baseName;
|
|
53
|
+
const line = node.startPosition.row + 1;
|
|
54
|
+
const endLine = node.endPosition.row + 1;
|
|
55
|
+
const { cc, callSites } = analyzeBody(node);
|
|
56
|
+
out.push({ name: fnName, line, endLine, cyclomaticComplexity: cc, callSites });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
for (const child of node.namedChildren)
|
|
60
|
+
walk(child, ownerName, out);
|
|
61
|
+
}
|
|
62
|
+
function nameOfDecl(node) {
|
|
63
|
+
if (node.childForFieldName) {
|
|
64
|
+
const id = node.childForFieldName('name');
|
|
65
|
+
if (id && id.text)
|
|
66
|
+
return id.text;
|
|
67
|
+
}
|
|
68
|
+
for (const c of node.namedChildren) {
|
|
69
|
+
if (c.type === 'simple_identifier' || c.type === 'identifier' || c.type === 'type_identifier') {
|
|
70
|
+
return c.text;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
function bodyOf(node) {
|
|
76
|
+
if (node.childForFieldName) {
|
|
77
|
+
const b = node.childForFieldName('body');
|
|
78
|
+
if (b)
|
|
79
|
+
return b;
|
|
80
|
+
}
|
|
81
|
+
for (const c of node.namedChildren) {
|
|
82
|
+
if (c.type === 'class_body' ||
|
|
83
|
+
c.type === 'protocol_body' ||
|
|
84
|
+
c.type === 'function_body' ||
|
|
85
|
+
c.type === 'extension_body') {
|
|
86
|
+
return c;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function analyzeBody(fnNode) {
|
|
92
|
+
let count = 0;
|
|
93
|
+
const calls = new Set();
|
|
94
|
+
const body = bodyOf(fnNode);
|
|
95
|
+
if (!body)
|
|
96
|
+
return { cc: 1, callSites: [] };
|
|
97
|
+
walkSkipNested(body, (n) => {
|
|
98
|
+
if (SWIFT_DECISION_NODES.has(n.type)) {
|
|
99
|
+
count++;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (n.type === 'switch_entry') {
|
|
103
|
+
// The default arm has no value child (no case_label patterns) — non-
|
|
104
|
+
// default arms always carry one or more case_label / case_pattern
|
|
105
|
+
// children. Mirrors the kotlin/cpp structural-detection approach.
|
|
106
|
+
const isDefault = !n.namedChildren.some((c) => c.type === 'switch_pattern' || c.type === 'case_label');
|
|
107
|
+
if (!isDefault)
|
|
108
|
+
count++;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (n.type === 'conjunction_expression' || n.type === 'disjunction_expression') {
|
|
112
|
+
count++;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (n.type === 'call_expression') {
|
|
116
|
+
const fn = n.childForFieldName ? n.childForFieldName('function') : n.namedChildren[0] ?? null;
|
|
117
|
+
const name = bareName(fn);
|
|
118
|
+
if (name)
|
|
119
|
+
calls.add(name);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
return { cc: count + 1, callSites: [...calls] };
|
|
123
|
+
}
|
|
124
|
+
function bareName(node) {
|
|
125
|
+
if (!node)
|
|
126
|
+
return null;
|
|
127
|
+
switch (node.type) {
|
|
128
|
+
case 'simple_identifier':
|
|
129
|
+
case 'identifier':
|
|
130
|
+
case 'type_identifier':
|
|
131
|
+
return node.text;
|
|
132
|
+
case 'navigation_expression': {
|
|
133
|
+
const last = node.namedChildren[node.namedChildren.length - 1];
|
|
134
|
+
return last ? bareName(last) : null;
|
|
135
|
+
}
|
|
136
|
+
case 'navigation_suffix': {
|
|
137
|
+
for (const c of node.namedChildren) {
|
|
138
|
+
const n = bareName(c);
|
|
139
|
+
if (n)
|
|
140
|
+
return n;
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
default:
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function walkSkipNested(node, visit) {
|
|
149
|
+
visit(node);
|
|
150
|
+
for (const child of node.namedChildren) {
|
|
151
|
+
if (child.type === 'function_declaration' ||
|
|
152
|
+
child.type === 'init_declaration' ||
|
|
153
|
+
child.type === 'class_declaration' ||
|
|
154
|
+
child.type === 'protocol_declaration' ||
|
|
155
|
+
child.type === 'lambda_literal' ||
|
|
156
|
+
child.type === 'closure_expression') {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
walkSkipNested(child, visit);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=swiftFunctions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swiftFunctions.js","sourceRoot":"","sources":["../../../src/core/languages/swiftFunctions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AstImport } from '../ast.js';
|
|
2
|
+
interface TsNode {
|
|
3
|
+
type: string;
|
|
4
|
+
text: string;
|
|
5
|
+
startPosition: {
|
|
6
|
+
row: number;
|
|
7
|
+
column: number;
|
|
8
|
+
};
|
|
9
|
+
namedChildren: TsNode[];
|
|
10
|
+
childForFieldName?: (name: string) => TsNode | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Extract Swift `import` statements from a tree-sitter-swift AST.
|
|
14
|
+
*
|
|
15
|
+
* Handled forms:
|
|
16
|
+
* import Foundation → source = "Foundation"
|
|
17
|
+
* import struct Foo.Bar → source = "Foo.Bar"
|
|
18
|
+
* import class Foo.Bar.Baz → source = "Foo.Bar.Baz"
|
|
19
|
+
* @testable import MyModule → source = "MyModule"
|
|
20
|
+
* @_implementationOnly import Private → source = "Private"
|
|
21
|
+
*
|
|
22
|
+
* Swift modules don't expose individual symbols at import time the way
|
|
23
|
+
* JS named imports do; the import binds the whole module / submodule.
|
|
24
|
+
*/
|
|
25
|
+
export declare function extractSwiftImports(root: TsNode): AstImport[];
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract Swift `import` statements from a tree-sitter-swift AST.
|
|
3
|
+
*
|
|
4
|
+
* Handled forms:
|
|
5
|
+
* import Foundation → source = "Foundation"
|
|
6
|
+
* import struct Foo.Bar → source = "Foo.Bar"
|
|
7
|
+
* import class Foo.Bar.Baz → source = "Foo.Bar.Baz"
|
|
8
|
+
* @testable import MyModule → source = "MyModule"
|
|
9
|
+
* @_implementationOnly import Private → source = "Private"
|
|
10
|
+
*
|
|
11
|
+
* Swift modules don't expose individual symbols at import time the way
|
|
12
|
+
* JS named imports do; the import binds the whole module / submodule.
|
|
13
|
+
*/
|
|
14
|
+
export function extractSwiftImports(root) {
|
|
15
|
+
const imports = [];
|
|
16
|
+
walk(root, (n) => {
|
|
17
|
+
if (n.type !== 'import_declaration')
|
|
18
|
+
return;
|
|
19
|
+
const source = readImportPath(n);
|
|
20
|
+
if (!source)
|
|
21
|
+
return;
|
|
22
|
+
imports.push({
|
|
23
|
+
source,
|
|
24
|
+
kind: 'static',
|
|
25
|
+
specifiers: [],
|
|
26
|
+
typeOnly: false,
|
|
27
|
+
line: n.startPosition.row + 1,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
return imports;
|
|
31
|
+
}
|
|
32
|
+
function readImportPath(node) {
|
|
33
|
+
const text = node.text.trim();
|
|
34
|
+
let body = text.replace(/^\s*(@[A-Za-z_][\w]*\s*)+/, '');
|
|
35
|
+
body = body.replace(/^\s*import\b/, '').trim();
|
|
36
|
+
body = body.replace(/^(typealias|struct|class|enum|protocol|let|var|func)\b\s*/, '');
|
|
37
|
+
const m = /^[A-Za-z_][\w.]*/.exec(body);
|
|
38
|
+
return m ? m[0] : '';
|
|
39
|
+
}
|
|
40
|
+
function walk(node, visit) {
|
|
41
|
+
visit(node);
|
|
42
|
+
for (const child of node.namedChildren)
|
|
43
|
+
walk(child, visit);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=swiftImports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swiftImports.js","sourceRoot":"","sources":["../../../src/core/languages/swiftImports.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QACf,IAAI,CAAC,CAAC,IAAI,KAAK,oBAAoB;YAAE,OAAO;QAC5C,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,OAAO,CAAC,IAAI,CAAC;YACX,MAAM;YACN,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;IACzD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,2DAA2D,EAC3D,EAAE,CACH,CAAC;IACF,MAAM,CAAC,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvB,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,KAA0B;IACpD,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa;QAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FileEntry } from '../../types.js';
|
|
2
|
+
export interface SwiftProjectInfo {
|
|
3
|
+
/**
|
|
4
|
+
* Detected Swift source roots. For SwiftPM projects this is typically
|
|
5
|
+
* `Sources/<Module>` per declared target; we fall back to the conventional
|
|
6
|
+
* `Sources/` and the repo root when no Package.swift exists.
|
|
7
|
+
*/
|
|
8
|
+
packageRoots: string[];
|
|
9
|
+
/** Did we see a Package.swift / .xcodeproj manifest? Used for diagnostics only. */
|
|
10
|
+
hasManifest: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Detect Swift source roots. We don't parse Package.swift; instead we
|
|
14
|
+
* survey the .swift file paths and pick whichever conventional roots
|
|
15
|
+
* actually contain Swift sources.
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectSwiftProject(rootPath: string, files: FileEntry[]): Promise<SwiftProjectInfo | null>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const COMMON_SWIFT_ROOTS = ['Sources', 'Tests', '.'];
|
|
4
|
+
/**
|
|
5
|
+
* Detect Swift source roots. We don't parse Package.swift; instead we
|
|
6
|
+
* survey the .swift file paths and pick whichever conventional roots
|
|
7
|
+
* actually contain Swift sources.
|
|
8
|
+
*/
|
|
9
|
+
export async function detectSwiftProject(rootPath, files) {
|
|
10
|
+
const swiftFiles = files.filter((f) => f.relativePath.endsWith('.swift'));
|
|
11
|
+
if (swiftFiles.length === 0)
|
|
12
|
+
return null;
|
|
13
|
+
const hasManifest = await hasSwiftManifest(rootPath);
|
|
14
|
+
const packageRoots = [];
|
|
15
|
+
for (const candidate of COMMON_SWIFT_ROOTS) {
|
|
16
|
+
if (candidate === '.') {
|
|
17
|
+
if (swiftFiles.some((f) => !f.relativePath.includes('/')))
|
|
18
|
+
packageRoots.push('.');
|
|
19
|
+
}
|
|
20
|
+
else if (swiftFiles.some((f) => f.relativePath.startsWith(candidate + '/'))) {
|
|
21
|
+
packageRoots.push(candidate);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (packageRoots.length === 0)
|
|
25
|
+
packageRoots.push('.');
|
|
26
|
+
return { packageRoots, hasManifest };
|
|
27
|
+
}
|
|
28
|
+
async function hasSwiftManifest(rootPath) {
|
|
29
|
+
const candidates = ['Package.swift', 'Package.resolved'];
|
|
30
|
+
for (const c of candidates) {
|
|
31
|
+
try {
|
|
32
|
+
await fs.access(path.join(rootPath, c));
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// try next
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const entries = await fs.readdir(rootPath, { withFileTypes: true });
|
|
41
|
+
if (entries.some((e) => e.isDirectory() && e.name.endsWith('.xcodeproj')))
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// ignore
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=swiftManifests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swiftManifests.js","sourceRoot":"","sources":["../../../src/core/languages/swiftManifests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAc7B,MAAM,kBAAkB,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,KAAkB;IAElB,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,SAAS,IAAI,kBAAkB,EAAE,CAAC;QAC3C,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;YACtB,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpF,CAAC;aAAM,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;YAC9E,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AACvC,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IAC9C,MAAM,UAAU,GAAG,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -28,7 +28,27 @@ function grammarDirs() {
|
|
|
28
28
|
const nodeModulesRust = path.join(repoRoot, 'node_modules', 'tree-sitter-rust');
|
|
29
29
|
const nodeModulesPhp = path.join(repoRoot, 'node_modules', 'tree-sitter-php');
|
|
30
30
|
const nodeModulesCSharp = path.join(repoRoot, 'node_modules', 'tree-sitter-c-sharp');
|
|
31
|
-
|
|
31
|
+
// 1.7+ — Kotlin doesn't ship a prebuilt wasm in the npm tarball; we
|
|
32
|
+
// build it locally during `npm run build` (see scripts/copy-wasm.mjs's
|
|
33
|
+
// ensureBuiltWasm). At test time (vitest running off src/) the wasm
|
|
34
|
+
// sits inside the package directory, so probe it there too.
|
|
35
|
+
const nodeModulesKotlin = path.join(repoRoot, 'node_modules', 'tree-sitter-kotlin');
|
|
36
|
+
const nodeModulesSwift = path.join(repoRoot, 'node_modules', 'tree-sitter-swift');
|
|
37
|
+
const nodeModulesCpp = path.join(repoRoot, 'node_modules', 'tree-sitter-cpp');
|
|
38
|
+
return [
|
|
39
|
+
distDir,
|
|
40
|
+
nodeModulesWebTs,
|
|
41
|
+
nodeModulesPy,
|
|
42
|
+
nodeModulesGo,
|
|
43
|
+
nodeModulesJava,
|
|
44
|
+
nodeModulesRuby,
|
|
45
|
+
nodeModulesRust,
|
|
46
|
+
nodeModulesPhp,
|
|
47
|
+
nodeModulesCSharp,
|
|
48
|
+
nodeModulesKotlin,
|
|
49
|
+
nodeModulesSwift,
|
|
50
|
+
nodeModulesCpp,
|
|
51
|
+
];
|
|
32
52
|
}
|
|
33
53
|
function findWasm(filename) {
|
|
34
54
|
for (const dir of grammarDirs()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"treeSitterLoader.js","sourceRoot":"","sources":["../../../src/core/languages/treeSitterLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,QAAQ,CAAC;AAEnD,IAAI,iBAAiB,GAAyB,IAAI,CAAC;AACnD,MAAM,aAAa,GAAG,IAAI,GAAG,EAA6B,CAAC;AAE3D;;;;;GAKG;AACH,SAAS,WAAW;IAClB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC;IAChF,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,oBAAoB,CAAC,CAAC;IAChF,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAC5E,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAChF,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAChF,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAChF,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC;IAC9E,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAC;IACrF,
|
|
1
|
+
{"version":3,"file":"treeSitterLoader.js","sourceRoot":"","sources":["../../../src/core/languages/treeSitterLoader.ts"],"names":[],"mappings":"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"}
|
package/dist/core/memory.d.ts
CHANGED
|
@@ -127,6 +127,36 @@ export declare function recordRun(memory: ProjectMemory, currentIds: Iterable<st
|
|
|
127
127
|
* These are the suggestions to surface in the doctor's "Tip" line.
|
|
128
128
|
*/
|
|
129
129
|
export declare function findStableRules(memory: ProjectMemory): RuleObservation[];
|
|
130
|
+
/**
|
|
131
|
+
* 1.7+ — Confidence label for a rule, derived from observed fix-rate.
|
|
132
|
+
*
|
|
133
|
+
* "high" — the user has actively fixed instances of this rule
|
|
134
|
+
* (`fixedCount > 0`). Suggestions for this rule should be
|
|
135
|
+
* surfaced prominently; the user has shown they care.
|
|
136
|
+
* "low" — the rule has surfaced across ≥ STABLE_RULE_RUN_COUNT runs
|
|
137
|
+
* over ≥ STABLE_RULE_DAYS days but has never been fixed
|
|
138
|
+
* (`fixedCount === 0`). The user is effectively tolerating
|
|
139
|
+
* it; suggestions should be deprioritized.
|
|
140
|
+
* "medium" — anything in between (insufficient signal, or recent rule).
|
|
141
|
+
*
|
|
142
|
+
* Returns "medium" if the memory has no observation for this rule yet.
|
|
143
|
+
*
|
|
144
|
+
* Project Memory's "loop #3" — rules with low confidence in a given repo
|
|
145
|
+
* stop crowding out rules the user actually acts on. The advisor stays
|
|
146
|
+
* useful instead of becoming background noise.
|
|
147
|
+
*/
|
|
148
|
+
export type RuleConfidence = 'high' | 'medium' | 'low';
|
|
149
|
+
export declare function computeRuleConfidence(memory: ProjectMemory, ruleId: string): RuleConfidence;
|
|
150
|
+
/**
|
|
151
|
+
* 1.7+ — A simple numeric score in [0, 1] that ranks suggestions by how
|
|
152
|
+
* likely the user is to act on them. Pairs with `computeRuleConfidence`
|
|
153
|
+
* for callers that want a single comparable number for sorting.
|
|
154
|
+
*
|
|
155
|
+
* high → 1.0 + (small bonus for higher fix-rate)
|
|
156
|
+
* medium → 0.5 (neutral)
|
|
157
|
+
* low → 0.0 + (small penalty for run-count that ages further)
|
|
158
|
+
*/
|
|
159
|
+
export declare function computeRuleConfidenceScore(memory: ProjectMemory, ruleId: string): number;
|
|
130
160
|
/** Drop a single rule's history. Returns true if the rule existed. */
|
|
131
161
|
export declare function forgetRule(memory: ProjectMemory, ruleId: string): boolean;
|
|
132
162
|
/**
|
package/dist/core/memory.js
CHANGED
|
@@ -167,6 +167,48 @@ export function findStableRules(memory) {
|
|
|
167
167
|
out.sort((a, b) => b.runCount - a.runCount);
|
|
168
168
|
return out;
|
|
169
169
|
}
|
|
170
|
+
export function computeRuleConfidence(memory, ruleId) {
|
|
171
|
+
const obs = memory.rules[ruleId];
|
|
172
|
+
if (!obs)
|
|
173
|
+
return 'medium';
|
|
174
|
+
if (obs.fixedCount > 0)
|
|
175
|
+
return 'high';
|
|
176
|
+
if (obs.runCount < STABLE_RULE_RUN_COUNT)
|
|
177
|
+
return 'medium';
|
|
178
|
+
const ageMs = Date.now() - Date.parse(obs.firstSeenAt);
|
|
179
|
+
const stableMs = STABLE_RULE_DAYS * MS_PER_DAY;
|
|
180
|
+
// Guard against future-dated timestamps (clock skew, corrupt memory):
|
|
181
|
+
// a negative age must NOT trip the "low" branch — fall back to medium
|
|
182
|
+
// until the wall clock catches up or the memory is regenerated.
|
|
183
|
+
if (Number.isFinite(ageMs) && ageMs > 0 && ageMs >= stableMs)
|
|
184
|
+
return 'low';
|
|
185
|
+
return 'medium';
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 1.7+ — A simple numeric score in [0, 1] that ranks suggestions by how
|
|
189
|
+
* likely the user is to act on them. Pairs with `computeRuleConfidence`
|
|
190
|
+
* for callers that want a single comparable number for sorting.
|
|
191
|
+
*
|
|
192
|
+
* high → 1.0 + (small bonus for higher fix-rate)
|
|
193
|
+
* medium → 0.5 (neutral)
|
|
194
|
+
* low → 0.0 + (small penalty for run-count that ages further)
|
|
195
|
+
*/
|
|
196
|
+
export function computeRuleConfidenceScore(memory, ruleId) {
|
|
197
|
+
const obs = memory.rules[ruleId];
|
|
198
|
+
if (!obs)
|
|
199
|
+
return 0.5;
|
|
200
|
+
const label = computeRuleConfidence(memory, ruleId);
|
|
201
|
+
if (label === 'high') {
|
|
202
|
+
const fixRate = obs.runCount > 0 ? obs.fixedCount / obs.runCount : 0;
|
|
203
|
+
return Math.min(1, 0.6 + 0.4 * fixRate);
|
|
204
|
+
}
|
|
205
|
+
if (label === 'low') {
|
|
206
|
+
// The longer a rule has been ignored, the lower its score.
|
|
207
|
+
const decay = Math.min(1, obs.runCount / 10);
|
|
208
|
+
return Math.max(0, 0.2 - 0.2 * decay);
|
|
209
|
+
}
|
|
210
|
+
return 0.5;
|
|
211
|
+
}
|
|
170
212
|
/** Drop a single rule's history. Returns true if the rule existed. */
|
|
171
213
|
export function forgetRule(memory, ruleId) {
|
|
172
214
|
if (!memory.rules[ruleId])
|
package/dist/core/memory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/core/memory.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/core/memory.ts"],"names":[],"mappings":"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"}
|
package/dist/core/session.d.ts
CHANGED
|
@@ -75,16 +75,35 @@ export declare function recordTouch(session: Session, file: string, source: Touc
|
|
|
75
75
|
/**
|
|
76
76
|
* Append an event to the session's bounded log. The log keeps the last
|
|
77
77
|
* MAX_EVENTS entries and drops the oldest when over capacity.
|
|
78
|
+
*
|
|
79
|
+
* 1.7+ — bound BEFORE append (rather than after) so that two interleaved
|
|
80
|
+
* recordEvent calls can't both observe `length === MAX_EVENTS`, both push,
|
|
81
|
+
* and leave the array one-over. Drops the single oldest entry on overflow,
|
|
82
|
+
* which keeps the steady-state size at exactly MAX_EVENTS.
|
|
78
83
|
*/
|
|
79
84
|
export declare function recordEvent(session: Session, kind: string, data?: Record<string, unknown>): void;
|
|
80
85
|
/**
|
|
81
86
|
* Persist the session to disk. Best-effort; failures are swallowed so
|
|
82
87
|
* a transient write error doesn't break the calling tool.
|
|
83
88
|
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
89
|
+
* 1.8+ — uses atomicWriteFile (tmp + fsync + rename + parent-dir fsync)
|
|
90
|
+
* instead of a naive fs.writeFile. Two reasons:
|
|
91
|
+
*
|
|
92
|
+
* 1. Crash safety. A naive writeFile can leave the file truncated to
|
|
93
|
+
* zero bytes if the process is killed mid-write — and on next
|
|
94
|
+
* startup the corrupt file is treated as a new session, losing the
|
|
95
|
+
* touched-file map and event log.
|
|
96
|
+
*
|
|
97
|
+
* 2. Concurrent processes. The previous "last-write-wins" comment was
|
|
98
|
+
* true at the *file* level: two writers could clobber each other.
|
|
99
|
+
* With atomic rename the in-flight tmp paths are unique (random
|
|
100
|
+
* UUID suffix), so the only collision point is the rename — which
|
|
101
|
+
* is atomic at the journal-record level on every supported FS.
|
|
102
|
+
* Either A wins or B wins; neither sees a half-written read.
|
|
103
|
+
*
|
|
104
|
+
* The session payload is JSON; we still don't merge concurrent writes
|
|
105
|
+
* (one writer's view may shadow another's recent touches by a few
|
|
106
|
+
* seconds), but corruption is no longer possible.
|
|
88
107
|
*/
|
|
89
108
|
export declare function saveSession(rootPath: string, session: Session): Promise<void>;
|
|
90
109
|
/**
|
package/dist/core/session.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { atomicWriteFile } from '../utils/atomicWrite.js';
|
|
4
5
|
/**
|
|
5
6
|
* Session — durable cross-invocation state for projscan (1.4+).
|
|
6
7
|
*
|
|
@@ -99,6 +100,11 @@ export function recordTouch(session, file, source) {
|
|
|
99
100
|
/**
|
|
100
101
|
* Append an event to the session's bounded log. The log keeps the last
|
|
101
102
|
* MAX_EVENTS entries and drops the oldest when over capacity.
|
|
103
|
+
*
|
|
104
|
+
* 1.7+ — bound BEFORE append (rather than after) so that two interleaved
|
|
105
|
+
* recordEvent calls can't both observe `length === MAX_EVENTS`, both push,
|
|
106
|
+
* and leave the array one-over. Drops the single oldest entry on overflow,
|
|
107
|
+
* which keeps the steady-state size at exactly MAX_EVENTS.
|
|
102
108
|
*/
|
|
103
109
|
export function recordEvent(session, kind, data) {
|
|
104
110
|
const event = {
|
|
@@ -106,27 +112,41 @@ export function recordEvent(session, kind, data) {
|
|
|
106
112
|
kind,
|
|
107
113
|
...(data ? { data } : {}),
|
|
108
114
|
};
|
|
109
|
-
session.events.
|
|
110
|
-
|
|
111
|
-
session.events = session.events.slice(-MAX_EVENTS);
|
|
115
|
+
if (session.events.length >= MAX_EVENTS) {
|
|
116
|
+
session.events = session.events.slice(-(MAX_EVENTS - 1));
|
|
112
117
|
}
|
|
118
|
+
session.events.push(event);
|
|
113
119
|
session.lastActivityAt = event.at;
|
|
114
120
|
}
|
|
115
121
|
/**
|
|
116
122
|
* Persist the session to disk. Best-effort; failures are swallowed so
|
|
117
123
|
* a transient write error doesn't break the calling tool.
|
|
118
124
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
125
|
+
* 1.8+ — uses atomicWriteFile (tmp + fsync + rename + parent-dir fsync)
|
|
126
|
+
* instead of a naive fs.writeFile. Two reasons:
|
|
127
|
+
*
|
|
128
|
+
* 1. Crash safety. A naive writeFile can leave the file truncated to
|
|
129
|
+
* zero bytes if the process is killed mid-write — and on next
|
|
130
|
+
* startup the corrupt file is treated as a new session, losing the
|
|
131
|
+
* touched-file map and event log.
|
|
132
|
+
*
|
|
133
|
+
* 2. Concurrent processes. The previous "last-write-wins" comment was
|
|
134
|
+
* true at the *file* level: two writers could clobber each other.
|
|
135
|
+
* With atomic rename the in-flight tmp paths are unique (random
|
|
136
|
+
* UUID suffix), so the only collision point is the rename — which
|
|
137
|
+
* is atomic at the journal-record level on every supported FS.
|
|
138
|
+
* Either A wins or B wins; neither sees a half-written read.
|
|
139
|
+
*
|
|
140
|
+
* The session payload is JSON; we still don't merge concurrent writes
|
|
141
|
+
* (one writer's view may shadow another's recent touches by a few
|
|
142
|
+
* seconds), but corruption is no longer possible.
|
|
123
143
|
*/
|
|
124
144
|
export async function saveSession(rootPath, session) {
|
|
125
145
|
try {
|
|
126
146
|
const dir = path.join(rootPath, SESSION_DIR);
|
|
127
147
|
await fs.mkdir(dir, { recursive: true });
|
|
128
148
|
const filePath = sessionFilePath(rootPath);
|
|
129
|
-
await
|
|
149
|
+
await atomicWriteFile(filePath, JSON.stringify(session, null, 2));
|
|
130
150
|
}
|
|
131
151
|
catch {
|
|
132
152
|
// Swallow — sessions are best-effort.
|
package/dist/core/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACxC,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;AAyChE,MAAM,WAAW,GAAG,iBAAiB,CAAC;AACtC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AACxC,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAAgB,EAChB,gBAAwB,uBAAuB;IAE/C,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7D,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7D,CAAC;IAED,qEAAqE;IACrE,uEAAuE;IACvE,cAAc;IACd,IAAI,MAAM,CAAC,aAAa,KAAK,sBAAsB,EAAE,CAAC;QACpD,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7D,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACzD,IACE,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC;QAChC,GAAG,CAAC,OAAO,EAAE,GAAG,cAAc,GAAG,aAAa,EAC9C,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7D,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB,EAAE,IAAY,EAAE,MAAmB;IAC7E,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,UAAU;QAAE,OAAO;IACxB,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IAClD,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;QACpB,QAAQ,CAAC,aAAa,GAAG,MAAM,CAAC;QAChC,yEAAyE;QACzE,mEAAmE;IACrE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG;YACjC,IAAI,EAAE,UAAU;YAChB,MAAM;YACN,aAAa,EAAE,MAAM;YACrB,KAAK,EAAE,CAAC;SACT,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB,EAAE,IAAY,EAAE,IAA8B;IACxF,MAAM,KAAK,GAAiB;QAC1B,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,IAAI;QACJ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1B,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QACxC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,CAAC,cAAc,GAAG,KAAK,CAAC,EAAE,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAgB;IAClE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC7C,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;IACD,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAS;IACnC,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC9B,OAAO;QACL,aAAa,EAAE,sBAAsB;QACrC,EAAE,EAAE,UAAU,EAAE;QAChB,SAAS,EAAE,GAAG;QACd,cAAc,EAAE,GAAG;QACnB,YAAY,EAAE,EAAE;QAChB,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,0EAA0E;IAC1E,0EAA0E;IAC1E,oEAAoE;IACpE,uDAAuD;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxE,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5C,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;IACpC,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO,CACL,OAAO,CAAC,CAAC,aAAa,KAAK,QAAQ;QACnC,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QACxB,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;QAC/B,OAAO,CAAC,CAAC,cAAc,KAAK,QAAQ;QACpC,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CACxB,CAAC;AACJ,CAAC"}
|