@tasksai/install 0.1.32 → 0.1.34

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tasksai/install",
3
- "version": "0.1.32",
3
+ "version": "0.1.34",
4
4
  "description": "Shared TasksAI MCP installer CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,3 +2,4 @@ mcp>=1.0.0,<2.0.0
2
2
  httpx>=0.27.0
3
3
  python-dotenv>=1.0.0
4
4
  python-docx>=1.1.2
5
+ pywin32>=311; sys_platform == "win32"
@@ -58,6 +58,7 @@ DEFAULT_THRESHOLDS = {"high": 90, "medium": 45}
58
58
  DEFAULT_RESULT_COUNT = 3
59
59
  MAXIMUM_RESULT_COUNT = 10
60
60
  DEFAULT_RESULT_COUNTS = {"realtor": 5}
61
+ MINIMUM_RESULT_COUNTS = {"realtor": 3}
61
62
  REALTOR_ACTION_WORDS = {
62
63
  "assemble", "build", "create", "develop", "document", "draft",
63
64
  "generate", "make", "prepare", "produce", "write", "writing",
@@ -69,6 +70,8 @@ REALTOR_DISCOVERY_WORDS = {
69
70
  DEFAULT_TOKEN_ALIASES = {
70
71
  "realtor": {
71
72
  "assemble": "create",
73
+ "bill": "commission",
74
+ "billing": "commission",
72
75
  "build": "create",
73
76
  "develop": "create",
74
77
  "draft": "create",
@@ -76,6 +79,8 @@ DEFAULT_TOKEN_ALIASES = {
76
79
  "generate": "create",
77
80
  "home": "property",
78
81
  "house": "property",
82
+ "invoice": "commission",
83
+ "invoicing": "commission",
79
84
  "listed": "listing",
80
85
  "listings": "listing",
81
86
  "list": "listing",
@@ -371,13 +376,20 @@ def _resolve_config(product_id: str, config: Mapping[str, object] | None) -> tup
371
376
  product_default_count = DEFAULT_RESULT_COUNTS.get(
372
377
  _canonical_product_id(product_id), DEFAULT_RESULT_COUNT
373
378
  )
379
+ product_minimum_count = MINIMUM_RESULT_COUNTS.get(
380
+ _canonical_product_id(product_id), 0
381
+ )
382
+ minimum_count = source.get("minimum_result_count", product_minimum_count)
374
383
  default_count = source.get("default_result_count", product_default_count)
375
384
  maximum_count = source.get("maximum_result_count", MAXIMUM_RESULT_COUNT)
376
385
  if not isinstance(default_count, int) or isinstance(default_count, bool) or default_count < 1:
377
386
  default_count = product_default_count
387
+ if not isinstance(minimum_count, int) or isinstance(minimum_count, bool) or minimum_count < 0:
388
+ minimum_count = product_minimum_count
378
389
  if not isinstance(maximum_count, int) or isinstance(maximum_count, bool) or maximum_count < 1:
379
390
  maximum_count = MAXIMUM_RESULT_COUNT
380
391
  maximum_count = min(maximum_count, MAXIMUM_RESULT_COUNT)
392
+ minimum_count = min(minimum_count, maximum_count)
381
393
  default_count = min(default_count, maximum_count)
382
394
 
383
395
  configured_abbreviations = source.get("abbreviations", {})
@@ -388,6 +400,7 @@ def _resolve_config(product_id: str, config: Mapping[str, object] | None) -> tup
388
400
  "stop_words": stop_words,
389
401
  "context_words": context_words,
390
402
  "thresholds": thresholds,
403
+ "minimum_result_count": minimum_count,
391
404
  "default_result_count": default_count,
392
405
  "maximum_result_count": maximum_count,
393
406
  "abbreviations": configured_abbreviations,
@@ -634,7 +647,11 @@ def match_skills(
634
647
  requested_count = policy["default_result_count"] if result_count is None else result_count
635
648
  if not isinstance(requested_count, int) or isinstance(requested_count, bool):
636
649
  requested_count = policy["default_result_count"]
637
- requested_count = max(1, min(requested_count, policy["maximum_result_count"]))
650
+ requested_count = max(
651
+ 1,
652
+ policy["minimum_result_count"],
653
+ min(requested_count, policy["maximum_result_count"]),
654
+ )
638
655
 
639
656
  if len(scoped_skills) != len(skills):
640
657
  diagnostics.append("product_mismatches_filtered")
@@ -645,12 +662,24 @@ def match_skills(
645
662
  if skill.get("id")
646
663
  ]
647
664
  ranked.sort(key=_sort_key)
665
+ diversified = _diversify(ranked)
648
666
  qualified = [
649
667
  result
650
- for result in _diversify(ranked)
668
+ for result in diversified
651
669
  if result["confidence"] in {"high", "medium"}
652
670
  ]
653
671
  selected = qualified[:requested_count]
672
+ minimum_count = min(policy["minimum_result_count"], requested_count)
673
+ if len(selected) < minimum_count:
674
+ selected_ids = {result["skill_id"] for result in selected}
675
+ for result in diversified:
676
+ if result["skill_id"] in selected_ids:
677
+ continue
678
+ selected.append(result)
679
+ selected_ids.add(result["skill_id"])
680
+ if len(selected) >= minimum_count:
681
+ break
682
+ diagnostics.append("minimum_results_filled")
654
683
 
655
684
  public_results = []
656
685
  for result in selected:
package/src/index.js CHANGED
@@ -475,7 +475,7 @@ async function configureMcpClient({ client, vertical, installDir, runtimeDir, ve
475
475
 
476
476
  function buildMcpServerConfig({ client, vertical, installDir, runtimeDir, vendorDir }) {
477
477
  return {
478
- command: "python3",
478
+ command: pythonCommandForPlatform(),
479
479
  args: [path.join(runtimeDir, "server.py")],
480
480
  env: {
481
481
  TASKSAI_PRODUCT_ID: vertical.product_id,
@@ -487,6 +487,10 @@ function buildMcpServerConfig({ client, vertical, installDir, runtimeDir, vendor
487
487
  };
488
488
  }
489
489
 
490
+ function pythonCommandForPlatform(platform = process.platform) {
491
+ return platform === "win32" ? "python" : "python3";
492
+ }
493
+
490
494
  async function jsonConfigHasServer(configPath, productId) {
491
495
  const config = await readJson(configPath);
492
496
  return Boolean(config.mcpServers?.[productId]);
@@ -1356,6 +1360,7 @@ export {
1356
1360
  parseArgs,
1357
1361
  parseEnv,
1358
1362
  parseSource,
1363
+ pythonCommandForPlatform,
1359
1364
  safeReportDoctorPassed,
1360
1365
  verifyProductionSource,
1361
1366
  verifyRuntimeHealth,