@pentatonic-ai/ai-agent-sdk 0.10.3 → 0.10.5
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.cjs
CHANGED
|
@@ -878,7 +878,7 @@ function fireAndForgetEmit(clientConfig, sessionOpts, messages, result, model) {
|
|
|
878
878
|
}
|
|
879
879
|
|
|
880
880
|
// src/telemetry.js
|
|
881
|
-
var VERSION = "0.10.
|
|
881
|
+
var VERSION = "0.10.5";
|
|
882
882
|
var TELEMETRY_URL = "https://sdk-telemetry.philip-134.workers.dev";
|
|
883
883
|
function machineId() {
|
|
884
884
|
const raw = typeof process !== "undefined" ? `${process.env?.USER || process.env?.USERNAME || "u"}:${process.platform || "x"}:${process.arch || "x"}` : "browser";
|
package/dist/index.js
CHANGED
|
@@ -847,7 +847,7 @@ function fireAndForgetEmit(clientConfig, sessionOpts, messages, result, model) {
|
|
|
847
847
|
}
|
|
848
848
|
|
|
849
849
|
// src/telemetry.js
|
|
850
|
-
var VERSION = "0.10.
|
|
850
|
+
var VERSION = "0.10.5";
|
|
851
851
|
var TELEMETRY_URL = "https://sdk-telemetry.philip-134.workers.dev";
|
|
852
852
|
function machineId() {
|
|
853
853
|
const raw = typeof process !== "undefined" ? `${process.env?.USER || process.env?.USERNAME || "u"}:${process.platform || "x"}:${process.arch || "x"}` : "browser";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pentatonic-ai/ai-agent-sdk",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.5",
|
|
4
4
|
"description": "TES SDK — LLM observability and lifecycle tracking via Pentatonic Thing Event System. Track token usage, tool calls, and conversations. Manage things through event-sourced lifecycle stages with AI enrichment and vector search.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -7,10 +7,13 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|
|
7
7
|
|
|
8
8
|
COPY worker.py .
|
|
9
9
|
# Pure helper modules — sibling imports inside worker.py
|
|
10
|
-
# (noise_filter, confidence, entity_id). entity_id.py is
|
|
11
|
-
# extractor-sync's copy (per-service build contexts
|
|
12
|
-
# tests/test_entity_id_parity.py guards drift).
|
|
13
|
-
#
|
|
14
|
-
|
|
10
|
+
# (noise_filter, confidence, entity_id, sensitive_filter). entity_id.py is
|
|
11
|
+
# byte-identical to extractor-sync's copy (per-service build contexts
|
|
12
|
+
# prevent a shared module; tests/test_entity_id_parity.py guards drift).
|
|
13
|
+
# sensitive_filter was added in #67 (interpersonal-gossip guard); if you
|
|
14
|
+
# add a new sibling module, add it here too — missing COPY makes the
|
|
15
|
+
# container crash-loop on import at startup (observed 2026-06-08 deploy).
|
|
16
|
+
# The test_*.py files are intentionally excluded; pytest only, not runtime.
|
|
17
|
+
COPY noise_filter.py confidence.py entity_id.py sensitive_filter.py ./
|
|
15
18
|
|
|
16
19
|
CMD ["python", "worker.py"]
|
|
@@ -761,6 +761,25 @@ SKIP_ATTRIBUTE_SOURCES = set(
|
|
|
761
761
|
)
|
|
762
762
|
DISTILL_MAX_AGE_DAYS = int(os.environ.get("DISTILL_MAX_AGE_DAYS", "90"))
|
|
763
763
|
|
|
764
|
+
# Layer-1 content pre-filter (cascade tier 1 — the cheap deterministic gate in
|
|
765
|
+
# front of the student/7B). Skips events with NO extractable signal BEFORE the
|
|
766
|
+
# LLM, so GPU is spent only on text that can yield facts.
|
|
767
|
+
# - bytes-garbage: a binary doc (raw PDF bytes) stored as text decodes to a
|
|
768
|
+
# wall of U+FFFD replacement chars. `build_event_block` feeds `content` to
|
|
769
|
+
# the LLM, so it sees the garbage and extracts nothing (live 2026-06-10:
|
|
770
|
+
# 35,296/39,453 pentatonic-team `doc` events are bytes-garbage). HIGH
|
|
771
|
+
# PRECISION — real text effectively never crosses a 5–10% replacement-char
|
|
772
|
+
# ratio, so this is a zero-quality-loss skip. (Durable fix = extract PDF
|
|
773
|
+
# text at INGEST; this stops the GPU waste meanwhile.)
|
|
774
|
+
# - too-short: trivially short content (one-line acks / emoji) has no facts.
|
|
775
|
+
# Conservative and OFF by default (0) to guarantee zero quality loss; tune
|
|
776
|
+
# up once layer-2 (the student model) owns the borderline cases.
|
|
777
|
+
SKIP_BYTES_GARBAGE = os.environ.get(
|
|
778
|
+
"DISTILL_SKIP_BYTES_GARBAGE", "true"
|
|
779
|
+
).strip().lower() not in ("false", "0", "no", "off")
|
|
780
|
+
GARBAGE_CHAR_RATIO = float(os.environ.get("DISTILL_GARBAGE_CHAR_RATIO", "0.10"))
|
|
781
|
+
MIN_CONTENT_CHARS = int(os.environ.get("DISTILL_MIN_CONTENT_CHARS", "0"))
|
|
782
|
+
|
|
764
783
|
|
|
765
784
|
def claim_next_batch(conn: psycopg.Connection) -> list[dict[str, Any]]:
|
|
766
785
|
"""Atomically claim up to BATCH_SIZE pending items. SKIP LOCKED so
|
|
@@ -843,6 +862,43 @@ def claim_next_batch(conn: psycopg.Connection) -> list[dict[str, Any]]:
|
|
|
843
862
|
""",
|
|
844
863
|
(DISTILL_MAX_AGE_DAYS, DISTILL_MAX_AGE_DAYS),
|
|
845
864
|
)
|
|
865
|
+
# Pre-filter: bytes-garbage content. A binary doc (raw PDF bytes)
|
|
866
|
+
# stored as text decodes to mostly U+FFFD (chr(65533)); the LLM
|
|
867
|
+
# extracts nothing from it. Skip when the replacement-char ratio
|
|
868
|
+
# exceeds GARBAGE_CHAR_RATIO — real text never crosses it, so no
|
|
869
|
+
# quality loss. Scoped to the pending set; one cheap UPDATE/cycle.
|
|
870
|
+
if SKIP_BYTES_GARBAGE:
|
|
871
|
+
cur.execute(
|
|
872
|
+
"""
|
|
873
|
+
UPDATE distillation_queue dq SET
|
|
874
|
+
status = 'done',
|
|
875
|
+
completed_at = NOW(),
|
|
876
|
+
last_error = 'filtered: bytes_garbage'
|
|
877
|
+
FROM events e
|
|
878
|
+
WHERE dq.event_id = e.id
|
|
879
|
+
AND dq.status = 'pending'
|
|
880
|
+
AND length(e.content) > 0
|
|
881
|
+
AND (length(e.content) - length(replace(e.content, chr(65533), '')))::float
|
|
882
|
+
/ length(e.content) > %s
|
|
883
|
+
""",
|
|
884
|
+
(GARBAGE_CHAR_RATIO,),
|
|
885
|
+
)
|
|
886
|
+
# Pre-filter: trivially-short content (one-line acks / emoji). OFF by
|
|
887
|
+
# default (MIN_CONTENT_CHARS=0) so it never costs a fact unless tuned on.
|
|
888
|
+
if MIN_CONTENT_CHARS > 0:
|
|
889
|
+
cur.execute(
|
|
890
|
+
"""
|
|
891
|
+
UPDATE distillation_queue dq SET
|
|
892
|
+
status = 'done',
|
|
893
|
+
completed_at = NOW(),
|
|
894
|
+
last_error = 'filtered: too_short'
|
|
895
|
+
FROM events e
|
|
896
|
+
WHERE dq.event_id = e.id
|
|
897
|
+
AND dq.status = 'pending'
|
|
898
|
+
AND length(trim(e.content)) < %s
|
|
899
|
+
""",
|
|
900
|
+
(MIN_CONTENT_CHARS,),
|
|
901
|
+
)
|
|
846
902
|
|
|
847
903
|
with conn.cursor(row_factory=psycopg.rows.dict_row) as cur:
|
|
848
904
|
cur.execute(
|