@tasksai/install 0.1.28 → 0.1.29
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 +1 -1
- package/runtime/server.py +75 -1
package/package.json
CHANGED
package/runtime/server.py
CHANGED
|
@@ -125,7 +125,7 @@ if not LICENSE_KEY:
|
|
|
125
125
|
print("Find your key in your purchase confirmation email.", file=sys.stderr, flush=True)
|
|
126
126
|
sys.exit(1)
|
|
127
127
|
|
|
128
|
-
SERVER_VERSION = "2.4.
|
|
128
|
+
SERVER_VERSION = "2.4.5"
|
|
129
129
|
|
|
130
130
|
AUTH_HEADERS = {
|
|
131
131
|
"Authorization": f"Bearer {LICENSE_KEY}",
|
|
@@ -1436,11 +1436,85 @@ def write_markdown(path, title, content_markdown, product_name):
|
|
|
1436
1436
|
path.write_text("\n\n".join(part for part in parts if part), encoding="utf-8")
|
|
1437
1437
|
|
|
1438
1438
|
|
|
1439
|
+
def reconcile_public_copy_counts(content_markdown):
|
|
1440
|
+
"""Replace stale public-copy counts with deterministic local counts.
|
|
1441
|
+
|
|
1442
|
+
AI hosts sometimes leave ``NOT VERIFIED`` or an estimated count beside a
|
|
1443
|
+
marked public-copy body. The local runtime can resolve that mechanical
|
|
1444
|
+
value without transmitting the document. It changes only count lines tied
|
|
1445
|
+
to balanced PUBLIC COPY markers and a detectable numeric maximum.
|
|
1446
|
+
"""
|
|
1447
|
+
start_marker = "<!-- PUBLIC COPY START -->"
|
|
1448
|
+
end_marker = "<!-- PUBLIC COPY END -->"
|
|
1449
|
+
if content_markdown.count(start_marker) != content_markdown.count(end_marker):
|
|
1450
|
+
return content_markdown
|
|
1451
|
+
|
|
1452
|
+
blocks = list(
|
|
1453
|
+
re.finditer(
|
|
1454
|
+
re.escape(start_marker) + r"\n?(.*?)\n?" + re.escape(end_marker),
|
|
1455
|
+
content_markdown,
|
|
1456
|
+
re.DOTALL,
|
|
1457
|
+
)
|
|
1458
|
+
)
|
|
1459
|
+
if not blocks:
|
|
1460
|
+
return content_markdown
|
|
1461
|
+
|
|
1462
|
+
count_pattern = re.compile(
|
|
1463
|
+
r"(?im)^(?P<prefix>\s*(?:\*\*)?Deterministic count:(?:\*\*)?\s*)"
|
|
1464
|
+
r"(?P<actual>NOT VERIFIED|[\d,]+)"
|
|
1465
|
+
r"(?:\s*/\s*(?P<target>[\d,]+)\s*(?P<unit>words|characters))?\s*$"
|
|
1466
|
+
)
|
|
1467
|
+
limit_patterns = (
|
|
1468
|
+
re.compile(r"(?i)\bmaximum(?:\s+public[- ]copy\s+length)?\s+(?:is\s+)?([\d,]+)\s*(words|characters)\b"),
|
|
1469
|
+
re.compile(r"(?i)\bmax(?:imum)?\s*[:=]?\s*([\d,]+)\s*(words|characters)\b"),
|
|
1470
|
+
re.compile(r"(?i)\b([\d,]+)[ -](word|character)\s+maximum\b"),
|
|
1471
|
+
)
|
|
1472
|
+
|
|
1473
|
+
replacements = []
|
|
1474
|
+
count_matches = list(count_pattern.finditer(content_markdown))
|
|
1475
|
+
for block in blocks:
|
|
1476
|
+
following = [match for match in count_matches if match.start() >= block.end()]
|
|
1477
|
+
if not following:
|
|
1478
|
+
continue
|
|
1479
|
+
count_match = min(following, key=lambda match: match.start() - block.end())
|
|
1480
|
+
if count_match.start() - block.end() > 2000:
|
|
1481
|
+
continue
|
|
1482
|
+
|
|
1483
|
+
target_text = count_match.group("target")
|
|
1484
|
+
unit = (count_match.group("unit") or "").lower()
|
|
1485
|
+
if not target_text or not unit:
|
|
1486
|
+
limit_match = None
|
|
1487
|
+
for pattern in limit_patterns:
|
|
1488
|
+
limit_match = pattern.search(content_markdown)
|
|
1489
|
+
if limit_match:
|
|
1490
|
+
break
|
|
1491
|
+
if not limit_match:
|
|
1492
|
+
continue
|
|
1493
|
+
target_text = limit_match.group(1)
|
|
1494
|
+
unit = limit_match.group(2).lower()
|
|
1495
|
+
if unit == "word":
|
|
1496
|
+
unit = "words"
|
|
1497
|
+
elif unit == "character":
|
|
1498
|
+
unit = "characters"
|
|
1499
|
+
|
|
1500
|
+
target = int(target_text.replace(",", ""))
|
|
1501
|
+
body = block.group(1)
|
|
1502
|
+
actual = len(body) if unit == "characters" else len(re.findall(r"\S+", body))
|
|
1503
|
+
replacement = f"{count_match.group('prefix')}{actual} / {target} {unit}"
|
|
1504
|
+
replacements.append((count_match.start(), count_match.end(), replacement))
|
|
1505
|
+
|
|
1506
|
+
corrected = content_markdown
|
|
1507
|
+
for start, end, replacement in reversed(replacements):
|
|
1508
|
+
corrected = corrected[:start] + replacement + corrected[end:]
|
|
1509
|
+
return corrected
|
|
1510
|
+
|
|
1511
|
+
|
|
1439
1512
|
def save_document(arguments, product_name):
|
|
1440
1513
|
"""Save AI-produced final content to a local downloadable file."""
|
|
1441
1514
|
content_markdown = (arguments.get("content_markdown") or arguments.get("content") or "").strip()
|
|
1442
1515
|
if not content_markdown:
|
|
1443
1516
|
raise ValueError("content_markdown is required.")
|
|
1517
|
+
content_markdown = reconcile_public_copy_counts(content_markdown)
|
|
1444
1518
|
|
|
1445
1519
|
title = (arguments.get("title") or "").strip()
|
|
1446
1520
|
skill_id = (arguments.get("skill_id") or "").strip()
|