composto-ai 0.2.0 → 0.2.1
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/{chunk-MFNGSHTZ.js → chunk-T2SFR7QS.js} +174 -13
- package/dist/index.js +1 -1
- package/dist/mcp/server.js +1 -1
- package/package.json +1 -1
|
@@ -499,36 +499,89 @@ function detectLanguage(filePath) {
|
|
|
499
499
|
|
|
500
500
|
// src/ir/ast-walker.ts
|
|
501
501
|
var TIER_MAP = {
|
|
502
|
-
// Tier 1 — structural declarations
|
|
502
|
+
// Tier 1 — structural declarations (JS/TS)
|
|
503
503
|
import_statement: "T1_KEEP",
|
|
504
504
|
function_declaration: "T1_KEEP",
|
|
505
505
|
class_declaration: "T1_KEEP",
|
|
506
506
|
interface_declaration: "T1_KEEP",
|
|
507
507
|
type_alias_declaration: "T1_KEEP",
|
|
508
508
|
enum_declaration: "T1_KEEP",
|
|
509
|
-
// Tier
|
|
509
|
+
// Tier 1 — Python
|
|
510
|
+
function_definition: "T1_KEEP",
|
|
511
|
+
class_definition: "T1_KEEP",
|
|
512
|
+
import_from_statement: "T1_KEEP",
|
|
513
|
+
decorated_definition: "T1_KEEP",
|
|
514
|
+
// Tier 1 — Go
|
|
515
|
+
function_item: "T1_KEEP",
|
|
516
|
+
// Rust
|
|
517
|
+
method_declaration: "T1_KEEP",
|
|
518
|
+
// Go
|
|
519
|
+
type_declaration: "T1_KEEP",
|
|
520
|
+
// Go
|
|
521
|
+
import_declaration: "T1_KEEP",
|
|
522
|
+
// Go
|
|
523
|
+
use_declaration: "T1_KEEP",
|
|
524
|
+
// Rust
|
|
525
|
+
struct_item: "T1_KEEP",
|
|
526
|
+
// Rust
|
|
527
|
+
enum_item: "T1_KEEP",
|
|
528
|
+
// Rust
|
|
529
|
+
trait_item: "T1_KEEP",
|
|
530
|
+
// Rust
|
|
531
|
+
impl_item: "T1_KEEP",
|
|
532
|
+
// Rust
|
|
533
|
+
// Tier 2 — control flow (universal)
|
|
510
534
|
if_statement: "T2_CONTROL",
|
|
535
|
+
if_expression: "T2_CONTROL",
|
|
536
|
+
// Rust
|
|
511
537
|
else_clause: "WALK_ONLY",
|
|
538
|
+
elif_clause: "T2_CONTROL",
|
|
539
|
+
// Python
|
|
512
540
|
for_statement: "T2_CONTROL",
|
|
513
541
|
for_in_statement: "T2_CONTROL",
|
|
542
|
+
for_expression: "T2_CONTROL",
|
|
543
|
+
// Rust
|
|
514
544
|
while_statement: "T2_CONTROL",
|
|
515
545
|
do_statement: "T2_CONTROL",
|
|
516
546
|
switch_statement: "T2_CONTROL",
|
|
517
547
|
switch_case: "T2_CONTROL",
|
|
518
548
|
switch_default: "T2_CONTROL",
|
|
549
|
+
match_expression: "T2_CONTROL",
|
|
550
|
+
// Rust
|
|
519
551
|
return_statement: "T2_CONTROL",
|
|
552
|
+
return_expression: "T2_CONTROL",
|
|
553
|
+
// Rust
|
|
520
554
|
throw_statement: "T2_CONTROL",
|
|
555
|
+
raise_statement: "T2_CONTROL",
|
|
556
|
+
// Python
|
|
521
557
|
try_statement: "T2_CONTROL",
|
|
522
558
|
catch_clause: "T2_CONTROL",
|
|
559
|
+
except_clause: "T2_CONTROL",
|
|
560
|
+
// Python
|
|
561
|
+
with_statement: "T2_CONTROL",
|
|
562
|
+
// Python
|
|
563
|
+
defer_statement: "T2_CONTROL",
|
|
564
|
+
// Go
|
|
523
565
|
// Tier 3 — compressible expressions
|
|
524
566
|
lexical_declaration: "T3_COMPRESS",
|
|
525
567
|
expression_statement: "T3_COMPRESS",
|
|
526
|
-
|
|
568
|
+
assignment: "T3_COMPRESS",
|
|
569
|
+
// Python
|
|
570
|
+
short_var_declaration: "T3_COMPRESS",
|
|
571
|
+
// Go
|
|
572
|
+
// Walk-only — containers
|
|
527
573
|
program: "WALK_ONLY",
|
|
574
|
+
module: "WALK_ONLY",
|
|
575
|
+
// Python
|
|
528
576
|
statement_block: "WALK_ONLY",
|
|
577
|
+
block: "WALK_ONLY",
|
|
578
|
+
// Python/Go/Rust
|
|
529
579
|
class_body: "WALK_ONLY",
|
|
580
|
+
// JS/TS
|
|
530
581
|
switch_body: "WALK_ONLY",
|
|
531
|
-
export_statement: "WALK_ONLY"
|
|
582
|
+
export_statement: "WALK_ONLY",
|
|
583
|
+
source_file: "WALK_ONLY"
|
|
584
|
+
// Go/Rust
|
|
532
585
|
};
|
|
533
586
|
function tierOf(nodeType) {
|
|
534
587
|
return TIER_MAP[nodeType] ?? "T4_DROP";
|
|
@@ -644,6 +697,35 @@ function emitTier2(node) {
|
|
|
644
697
|
const paramText = param ? param.text : "...";
|
|
645
698
|
return `CATCH:${paramText}`;
|
|
646
699
|
}
|
|
700
|
+
// Python
|
|
701
|
+
case "raise_statement": {
|
|
702
|
+
const val = node.childCount > 1 ? node.child(1)?.text ?? "" : "";
|
|
703
|
+
return `RAISE:${val.length > 50 ? val.slice(0, 47) + "..." : val}`;
|
|
704
|
+
}
|
|
705
|
+
case "except_clause":
|
|
706
|
+
return "EXCEPT";
|
|
707
|
+
case "elif_clause": {
|
|
708
|
+
const cond = extractCondition(node);
|
|
709
|
+
return `ELIF:${cond}`;
|
|
710
|
+
}
|
|
711
|
+
case "with_statement":
|
|
712
|
+
return "WITH";
|
|
713
|
+
// Rust
|
|
714
|
+
case "if_expression": {
|
|
715
|
+
const cond = extractCondition(node);
|
|
716
|
+
return `IF:${cond}`;
|
|
717
|
+
}
|
|
718
|
+
case "for_expression":
|
|
719
|
+
return "LOOP";
|
|
720
|
+
case "match_expression":
|
|
721
|
+
return "MATCH";
|
|
722
|
+
case "return_expression": {
|
|
723
|
+
const val = node.childCount > 1 ? node.child(1)?.text ?? "" : "";
|
|
724
|
+
return `RET ${val.length > 60 ? val.slice(0, 57) + "..." : val}`.trimEnd();
|
|
725
|
+
}
|
|
726
|
+
// Go
|
|
727
|
+
case "defer_statement":
|
|
728
|
+
return "DEFER";
|
|
647
729
|
default:
|
|
648
730
|
return null;
|
|
649
731
|
}
|
|
@@ -681,6 +763,46 @@ function emitTier1(node) {
|
|
|
681
763
|
const name = node.childForFieldName("name")?.text ?? "Anonymous";
|
|
682
764
|
return `${outPrefix}ENUM:${name}`;
|
|
683
765
|
}
|
|
766
|
+
// Python
|
|
767
|
+
case "function_definition": {
|
|
768
|
+
const name = node.childForFieldName("name")?.text ?? "anonymous";
|
|
769
|
+
const params = node.childForFieldName("parameters")?.text ?? "()";
|
|
770
|
+
const returnType = node.childForFieldName("return_type")?.text ?? "";
|
|
771
|
+
const rt = returnType ? ` -> ${returnType}` : "";
|
|
772
|
+
return `FN:${name}${collapseText(params, 60)}${rt}`;
|
|
773
|
+
}
|
|
774
|
+
case "class_definition": {
|
|
775
|
+
const name = node.childForFieldName("name")?.text ?? "Anonymous";
|
|
776
|
+
const superclass = node.childForFieldName("superclasses")?.text ?? "";
|
|
777
|
+
const sc = superclass ? `(${collapseText(superclass, 40)})` : "";
|
|
778
|
+
return `CLASS:${name}${sc}`;
|
|
779
|
+
}
|
|
780
|
+
case "import_from_statement": {
|
|
781
|
+
return `USE:${collapseText(node.text, 80)}`;
|
|
782
|
+
}
|
|
783
|
+
case "decorated_definition": {
|
|
784
|
+
return null;
|
|
785
|
+
}
|
|
786
|
+
// Go
|
|
787
|
+
case "method_declaration":
|
|
788
|
+
case "type_declaration":
|
|
789
|
+
case "import_declaration": {
|
|
790
|
+
return `${collapseText(node.text, 80)}`;
|
|
791
|
+
}
|
|
792
|
+
// Rust
|
|
793
|
+
case "function_item": {
|
|
794
|
+
const name = node.childForFieldName("name")?.text ?? "anonymous";
|
|
795
|
+
const params = node.childForFieldName("parameters")?.text ?? "()";
|
|
796
|
+
return `FN:${name}${collapseText(params, 60)}`;
|
|
797
|
+
}
|
|
798
|
+
case "struct_item":
|
|
799
|
+
case "enum_item":
|
|
800
|
+
case "trait_item":
|
|
801
|
+
case "impl_item":
|
|
802
|
+
case "use_declaration": {
|
|
803
|
+
const firstLine = node.text.split("\n")[0];
|
|
804
|
+
return collapseText(firstLine, 80);
|
|
805
|
+
}
|
|
684
806
|
default:
|
|
685
807
|
return null;
|
|
686
808
|
}
|
|
@@ -726,6 +848,17 @@ function emitTier3(node) {
|
|
|
726
848
|
return null;
|
|
727
849
|
}
|
|
728
850
|
if (expr.type === "call_expression") {
|
|
851
|
+
const callee = expr.child(0)?.text ?? "";
|
|
852
|
+
if (callee === "ObjectSetPrototypeOf" || callee === "Object.setPrototypeOf") {
|
|
853
|
+
const args = expr.child(1);
|
|
854
|
+
if (args && args.childCount >= 4) {
|
|
855
|
+
const child = args.child(1)?.text ?? "?";
|
|
856
|
+
const parent = args.child(3)?.text ?? "?";
|
|
857
|
+
const shortChild = child.length > 30 ? child.slice(0, 27) + "..." : child;
|
|
858
|
+
const shortParent = parent.length > 30 ? parent.slice(0, 27) + "..." : parent;
|
|
859
|
+
return `EXTENDS:${shortChild} < ${shortParent}`;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
729
862
|
return null;
|
|
730
863
|
}
|
|
731
864
|
return null;
|
|
@@ -743,7 +876,9 @@ function walkNode(node, depth, lines) {
|
|
|
743
876
|
for (let i = 0; i < node.childCount; i++) {
|
|
744
877
|
const child = node.child(i);
|
|
745
878
|
const childType = child.type;
|
|
746
|
-
if (childType === "statement_block" || childType === "class_body"
|
|
879
|
+
if (childType === "statement_block" || childType === "class_body" || childType === "block" || // Python/Go/Rust
|
|
880
|
+
childType === "body" || // Python class/function body
|
|
881
|
+
childType === "declaration_list") {
|
|
747
882
|
walkNode(child, depth + 1, lines);
|
|
748
883
|
}
|
|
749
884
|
}
|
|
@@ -834,7 +969,7 @@ async function astWalkIR(code, filePath) {
|
|
|
834
969
|
const lines = [];
|
|
835
970
|
walkNode(root, 0, lines);
|
|
836
971
|
if (lines.length === 0) return null;
|
|
837
|
-
const
|
|
972
|
+
const pass1 = [];
|
|
838
973
|
let useBlock = [];
|
|
839
974
|
for (const line of lines) {
|
|
840
975
|
if (line.startsWith("USE:")) {
|
|
@@ -843,20 +978,45 @@ async function astWalkIR(code, filePath) {
|
|
|
843
978
|
} else {
|
|
844
979
|
if (useBlock.length > 0) {
|
|
845
980
|
if (useBlock.length <= 3) {
|
|
846
|
-
for (const mod of useBlock)
|
|
981
|
+
for (const mod of useBlock) pass1.push(`USE:${mod}`);
|
|
847
982
|
} else {
|
|
848
|
-
|
|
983
|
+
pass1.push(`USE:[${useBlock.join(", ")}]`);
|
|
849
984
|
}
|
|
850
985
|
useBlock = [];
|
|
851
986
|
}
|
|
852
|
-
|
|
987
|
+
pass1.push(line);
|
|
853
988
|
}
|
|
854
989
|
}
|
|
855
990
|
if (useBlock.length > 0) {
|
|
856
991
|
if (useBlock.length <= 3) {
|
|
857
|
-
for (const mod of useBlock)
|
|
992
|
+
for (const mod of useBlock) pass1.push(`USE:${mod}`);
|
|
858
993
|
} else {
|
|
859
|
-
|
|
994
|
+
pass1.push(`USE:[${useBlock.join(", ")}]`);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
const merged = [];
|
|
998
|
+
let guardBlock = [];
|
|
999
|
+
for (const line of pass1) {
|
|
1000
|
+
const guardMatch = line.match(/^(\s*)IF:(.+?) \u2192 RET/);
|
|
1001
|
+
if (guardMatch) {
|
|
1002
|
+
guardBlock.push(guardMatch[2].trim());
|
|
1003
|
+
continue;
|
|
1004
|
+
}
|
|
1005
|
+
if (guardBlock.length > 0) {
|
|
1006
|
+
if (guardBlock.length < 3) {
|
|
1007
|
+
for (const g of guardBlock) merged.push(` IF:${g} \u2192 RET`);
|
|
1008
|
+
} else {
|
|
1009
|
+
merged.push(` GUARD:[${guardBlock.join(", ")}]`);
|
|
1010
|
+
}
|
|
1011
|
+
guardBlock = [];
|
|
1012
|
+
}
|
|
1013
|
+
merged.push(line);
|
|
1014
|
+
}
|
|
1015
|
+
if (guardBlock.length > 0) {
|
|
1016
|
+
if (guardBlock.length < 3) {
|
|
1017
|
+
for (const g of guardBlock) merged.push(` IF:${g} \u2192 RET`);
|
|
1018
|
+
} else {
|
|
1019
|
+
merged.push(` GUARD:[${guardBlock.join(", ")}]`);
|
|
860
1020
|
}
|
|
861
1021
|
}
|
|
862
1022
|
return merged.join("\n");
|
|
@@ -879,10 +1039,11 @@ ${declarations.join("\n")}`;
|
|
|
879
1039
|
}
|
|
880
1040
|
async function generateL1(code, filePath, health) {
|
|
881
1041
|
const ir = await astWalkIR(code, filePath) ?? fingerprintFile(code, 0.75);
|
|
1042
|
+
const result = ir.length < code.length ? ir : code;
|
|
882
1043
|
if (health) {
|
|
883
|
-
return annotateIR(
|
|
1044
|
+
return annotateIR(result, health);
|
|
884
1045
|
}
|
|
885
|
-
return
|
|
1046
|
+
return result;
|
|
886
1047
|
}
|
|
887
1048
|
function generateL2(delta, health) {
|
|
888
1049
|
const parts = [`FILE: ${delta.file}`];
|
package/dist/index.js
CHANGED
package/dist/mcp/server.js
CHANGED