composto-ai 0.7.0 → 0.7.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/index.js CHANGED
@@ -843,8 +843,9 @@ function emitTier1(node) {
843
843
  const outPrefix = exported ? "OUT " : "";
844
844
  switch (node.type) {
845
845
  case "import_statement": {
846
- const text = collapseText(node.text, 80);
847
- return `USE:${text}`;
846
+ const source = node.childForFieldName("source")?.text;
847
+ if (source) return `USE:${source.slice(1, -1)}`;
848
+ return `USE:${collapseText(node.text, 80)}`;
848
849
  }
849
850
  case "function_declaration": {
850
851
  const name = node.childForFieldName("name")?.text ?? "anonymous";
@@ -974,9 +975,30 @@ function emitTier3(node) {
974
975
  }
975
976
  if (node.parent?.type === "statement_block") return null;
976
977
  const vt = value.type;
977
- if (vt === "number" || vt === "true" || vt === "false") return null;
978
- if (vt === "object" || vt === "array") return null;
979
- if (vt === "new_expression" || vt === "call_expression") return null;
978
+ if (vt === "number" || vt === "true" || vt === "false") {
979
+ return `VAR:${name} = ${value.text}`;
980
+ }
981
+ if (vt === "array") {
982
+ return `VAR:${name}[${value.namedChildCount}]`;
983
+ }
984
+ if (vt === "object") {
985
+ const keys = [];
986
+ for (let i = 0; i < value.namedChildCount; i++) {
987
+ const member = value.namedChild(i);
988
+ keys.push(member.childForFieldName("key")?.text ?? member.text);
989
+ if (keys.length >= 6) break;
990
+ }
991
+ const more = value.namedChildCount > keys.length ? ", ..." : "";
992
+ return `VAR:${name}{${collapseText(keys.join(", "), 50)}${more}}`;
993
+ }
994
+ if (vt === "new_expression") {
995
+ const ctor = value.childForFieldName("constructor")?.text ?? "?";
996
+ return `VAR:${name} = new ${ctor}(...)`;
997
+ }
998
+ if (vt === "call_expression") {
999
+ const callee = value.childForFieldName("function")?.text ?? "?";
1000
+ return `VAR:${name} = ${collapseText(callee, 40)}(...)`;
1001
+ }
980
1002
  const valText = value.text.replace(/"[^"]*"/g, '""').replace(/'[^']*'/g, "''").replace(/`[^`]*`/g, "``");
981
1003
  return `VAR:${name} = ${collapseText(valText, 50)}`;
982
1004
  }
@@ -1137,29 +1159,27 @@ async function astWalkIR(code, filePath) {
1137
1159
  }
1138
1160
  const merged = [];
1139
1161
  let guardBlock = [];
1162
+ const guardValue = (ret) => ret.replace(/^RET\s+/, "");
1163
+ const flushGuards = () => {
1164
+ if (guardBlock.length === 0) return;
1165
+ if (guardBlock.length < 3) {
1166
+ for (const g of guardBlock) merged.push(`${g.indent}IF:${g.cond} \u2192 ${g.ret}`);
1167
+ } else {
1168
+ const entries = guardBlock.map((g) => `${g.cond} \u2192 ${guardValue(g.ret)}`);
1169
+ merged.push(`${guardBlock[0].indent}GUARD:[${entries.join(", ")}]`);
1170
+ }
1171
+ guardBlock = [];
1172
+ };
1140
1173
  for (const line of pass1) {
1141
- const guardMatch = line.match(/^(\s*)IF:(.+?) \u2192 RET/);
1174
+ const guardMatch = line.match(/^(\s*)IF:(.+?) \u2192 (.+)$/);
1142
1175
  if (guardMatch) {
1143
- guardBlock.push(guardMatch[2].trim());
1176
+ guardBlock.push({ indent: guardMatch[1], cond: guardMatch[2].trim(), ret: guardMatch[3].trim() });
1144
1177
  continue;
1145
1178
  }
1146
- if (guardBlock.length > 0) {
1147
- if (guardBlock.length < 3) {
1148
- for (const g of guardBlock) merged.push(` IF:${g} \u2192 RET`);
1149
- } else {
1150
- merged.push(` GUARD:[${guardBlock.join(", ")}]`);
1151
- }
1152
- guardBlock = [];
1153
- }
1179
+ flushGuards();
1154
1180
  merged.push(line);
1155
1181
  }
1156
- if (guardBlock.length > 0) {
1157
- if (guardBlock.length < 3) {
1158
- for (const g of guardBlock) merged.push(` IF:${g} \u2192 RET`);
1159
- } else {
1160
- merged.push(` GUARD:[${guardBlock.join(", ")}]`);
1161
- }
1162
- }
1182
+ flushGuards();
1163
1183
  return merged.join("\n");
1164
1184
  }
1165
1185
 
@@ -3593,7 +3613,16 @@ function renderSummary(s) {
3593
3613
  }
3594
3614
 
3595
3615
  // src/index.ts
3616
+ import { createRequire } from "module";
3596
3617
  import { join as join13, resolve as resolve2 } from "path";
3618
+ var PKG_VERSION = (() => {
3619
+ try {
3620
+ const req = createRequire(import.meta.url);
3621
+ return req("../package.json").version;
3622
+ } catch {
3623
+ return "0.0.0";
3624
+ }
3625
+ })();
3597
3626
  async function readStdin() {
3598
3627
  if (process.stdin.isTTY) return "";
3599
3628
  const chunks = [];
@@ -3754,10 +3783,11 @@ switch (command) {
3754
3783
  break;
3755
3784
  }
3756
3785
  case "version":
3757
- console.log("composto v0.4.2");
3786
+ console.log(`composto v${PKG_VERSION}`);
3758
3787
  break;
3759
3788
  default:
3760
- console.log("composto v0.4.2 \u2014 less tokens, more insight\n");
3789
+ console.log(`composto v${PKG_VERSION} \u2014 less tokens, more insight
3790
+ `);
3761
3791
  console.log("Commands:");
3762
3792
  console.log(" scan [path] Scan codebase for issues");
3763
3793
  console.log(" trends [path] Analyze codebase health trends");
@@ -5,7 +5,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
6
  import { z } from "zod";
7
7
  import { readFileSync as readFileSync4 } from "fs";
8
- import { resolve as resolve2, relative as relative2, join as join6 } from "path";
8
+ import { fileURLToPath as fileURLToPath3 } from "url";
9
+ import { resolve as resolve2, relative as relative2, join as join6, dirname as dirname5 } from "path";
9
10
 
10
11
  // src/ir/structure.ts
11
12
  var CLASSIFIERS = [
@@ -650,8 +651,9 @@ function emitTier1(node) {
650
651
  const outPrefix = exported ? "OUT " : "";
651
652
  switch (node.type) {
652
653
  case "import_statement": {
653
- const text = collapseText(node.text, 80);
654
- return `USE:${text}`;
654
+ const source = node.childForFieldName("source")?.text;
655
+ if (source) return `USE:${source.slice(1, -1)}`;
656
+ return `USE:${collapseText(node.text, 80)}`;
655
657
  }
656
658
  case "function_declaration": {
657
659
  const name = node.childForFieldName("name")?.text ?? "anonymous";
@@ -781,9 +783,30 @@ function emitTier3(node) {
781
783
  }
782
784
  if (node.parent?.type === "statement_block") return null;
783
785
  const vt = value.type;
784
- if (vt === "number" || vt === "true" || vt === "false") return null;
785
- if (vt === "object" || vt === "array") return null;
786
- if (vt === "new_expression" || vt === "call_expression") return null;
786
+ if (vt === "number" || vt === "true" || vt === "false") {
787
+ return `VAR:${name} = ${value.text}`;
788
+ }
789
+ if (vt === "array") {
790
+ return `VAR:${name}[${value.namedChildCount}]`;
791
+ }
792
+ if (vt === "object") {
793
+ const keys = [];
794
+ for (let i = 0; i < value.namedChildCount; i++) {
795
+ const member = value.namedChild(i);
796
+ keys.push(member.childForFieldName("key")?.text ?? member.text);
797
+ if (keys.length >= 6) break;
798
+ }
799
+ const more = value.namedChildCount > keys.length ? ", ..." : "";
800
+ return `VAR:${name}{${collapseText(keys.join(", "), 50)}${more}}`;
801
+ }
802
+ if (vt === "new_expression") {
803
+ const ctor = value.childForFieldName("constructor")?.text ?? "?";
804
+ return `VAR:${name} = new ${ctor}(...)`;
805
+ }
806
+ if (vt === "call_expression") {
807
+ const callee = value.childForFieldName("function")?.text ?? "?";
808
+ return `VAR:${name} = ${collapseText(callee, 40)}(...)`;
809
+ }
787
810
  const valText = value.text.replace(/"[^"]*"/g, '""').replace(/'[^']*'/g, "''").replace(/`[^`]*`/g, "``");
788
811
  return `VAR:${name} = ${collapseText(valText, 50)}`;
789
812
  }
@@ -944,29 +967,27 @@ async function astWalkIR(code, filePath) {
944
967
  }
945
968
  const merged = [];
946
969
  let guardBlock = [];
970
+ const guardValue = (ret) => ret.replace(/^RET\s+/, "");
971
+ const flushGuards = () => {
972
+ if (guardBlock.length === 0) return;
973
+ if (guardBlock.length < 3) {
974
+ for (const g of guardBlock) merged.push(`${g.indent}IF:${g.cond} \u2192 ${g.ret}`);
975
+ } else {
976
+ const entries = guardBlock.map((g) => `${g.cond} \u2192 ${guardValue(g.ret)}`);
977
+ merged.push(`${guardBlock[0].indent}GUARD:[${entries.join(", ")}]`);
978
+ }
979
+ guardBlock = [];
980
+ };
947
981
  for (const line of pass1) {
948
- const guardMatch = line.match(/^(\s*)IF:(.+?) \u2192 RET/);
982
+ const guardMatch = line.match(/^(\s*)IF:(.+?) \u2192 (.+)$/);
949
983
  if (guardMatch) {
950
- guardBlock.push(guardMatch[2].trim());
984
+ guardBlock.push({ indent: guardMatch[1], cond: guardMatch[2].trim(), ret: guardMatch[3].trim() });
951
985
  continue;
952
986
  }
953
- if (guardBlock.length > 0) {
954
- if (guardBlock.length < 3) {
955
- for (const g of guardBlock) merged.push(` IF:${g} \u2192 RET`);
956
- } else {
957
- merged.push(` GUARD:[${guardBlock.join(", ")}]`);
958
- }
959
- guardBlock = [];
960
- }
987
+ flushGuards();
961
988
  merged.push(line);
962
989
  }
963
- if (guardBlock.length > 0) {
964
- if (guardBlock.length < 3) {
965
- for (const g of guardBlock) merged.push(` IF:${g} \u2192 RET`);
966
- } else {
967
- merged.push(` GUARD:[${guardBlock.join(", ")}]`);
968
- }
969
- }
990
+ flushGuards();
970
991
  return merged.join("\n");
971
992
  }
972
993
 
@@ -2381,9 +2402,22 @@ var MemoryAPI = class {
2381
2402
 
2382
2403
  // src/mcp/server.ts
2383
2404
  var ALL_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs"];
2405
+ var PKG_VERSION = (() => {
2406
+ try {
2407
+ const pkgPath = join6(
2408
+ dirname5(fileURLToPath3(import.meta.url)),
2409
+ "..",
2410
+ "..",
2411
+ "package.json"
2412
+ );
2413
+ return JSON.parse(readFileSync4(pkgPath, "utf-8")).version;
2414
+ } catch {
2415
+ return "0.0.0";
2416
+ }
2417
+ })();
2384
2418
  var server = new McpServer({
2385
2419
  name: "composto",
2386
- version: "0.4.2"
2420
+ version: PKG_VERSION
2387
2421
  });
2388
2422
  server.tool(
2389
2423
  "composto_ir",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "composto-ai",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Proactive AI team companion — less tokens, more insight",
5
5
  "type": "module",
6
6
  "bin": {