ultimate-pi 0.4.1 → 0.5.0
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/.agents/skills/harness-decisions/SKILL.md +15 -0
- package/.agents/skills/scrapling-web/SKILL.md +45 -40
- package/.agents/skills/wiki-autoresearch/SKILL.md +3 -3
- package/.pi/SYSTEM.md +12 -13
- package/.pi/agents/pi-pi/agent-expert.md +3 -3
- package/.pi/extensions/harness-web-guard.ts +95 -0
- package/.pi/extensions/harness-web-tools.ts +209 -0
- package/.pi/extensions/lib/harness-web/run-cli.ts +92 -0
- package/.pi/harness/env.harness.template +3 -1
- package/.pi/prompts/harness-setup.md +46 -0
- package/.pi/scripts/harness-cli-verify.sh +12 -3
- package/.pi/scripts/harness-searxng-bootstrap.mjs +270 -0
- package/.pi/scripts/harness-web-search.md +24 -5
- package/.pi/scripts/harness-web.py +24 -7
- package/.pi/scripts/harness_web/config.py +37 -3
- package/.pi/scripts/harness_web/output.py +8 -2
- package/.pi/scripts/harness_web/search.py +22 -0
- package/.pi/scripts/harness_web/search_ddg.py +1 -5
- package/.pi/scripts/harness_web/search_searxng.py +100 -0
- package/CHANGELOG.md +12 -0
- package/package.json +2 -2
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""SearXNG JSON search API (self-hosted instances)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import ssl
|
|
7
|
+
from typing import Any
|
|
8
|
+
from urllib.error import HTTPError, URLError
|
|
9
|
+
from urllib.parse import urlencode
|
|
10
|
+
from urllib.request import ProxyHandler, Request, build_opener, urlopen
|
|
11
|
+
|
|
12
|
+
from .config import HarnessWebConfig
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _open_url(url: str, *, config: HarnessWebConfig) -> tuple[int, str]:
|
|
16
|
+
req = Request(
|
|
17
|
+
url,
|
|
18
|
+
headers={"Accept": "application/json", "User-Agent": "ultimate-pi-harness-web/1.0"},
|
|
19
|
+
method="GET",
|
|
20
|
+
)
|
|
21
|
+
if config.proxy:
|
|
22
|
+
opener = build_opener(ProxyHandler({"http": config.proxy, "https": config.proxy}))
|
|
23
|
+
resp = opener.open(req, timeout=config.timeout_sec)
|
|
24
|
+
else:
|
|
25
|
+
ctx = ssl.create_default_context()
|
|
26
|
+
resp = urlopen(req, timeout=config.timeout_sec, context=ctx)
|
|
27
|
+
try:
|
|
28
|
+
status = getattr(resp, "status", 200) or 200
|
|
29
|
+
body = resp.read().decode("utf-8", errors="replace")
|
|
30
|
+
return status, body
|
|
31
|
+
finally:
|
|
32
|
+
resp.close()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _parse_results(payload: Any, limit: int) -> list[dict[str, str]]:
|
|
36
|
+
raw = payload.get("results") if isinstance(payload, dict) else None
|
|
37
|
+
if not isinstance(raw, list):
|
|
38
|
+
return []
|
|
39
|
+
out: list[dict[str, str]] = []
|
|
40
|
+
for item in raw:
|
|
41
|
+
if len(out) >= limit:
|
|
42
|
+
break
|
|
43
|
+
if not isinstance(item, dict):
|
|
44
|
+
continue
|
|
45
|
+
url = (item.get("url") or "").strip()
|
|
46
|
+
if not url.startswith("http"):
|
|
47
|
+
continue
|
|
48
|
+
title = (item.get("title") or "").strip()
|
|
49
|
+
description = (item.get("content") or item.get("snippet") or "").strip()
|
|
50
|
+
out.append({"url": url, "title": title, "description": description})
|
|
51
|
+
return out
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def search_searxng(
|
|
55
|
+
query: str,
|
|
56
|
+
*,
|
|
57
|
+
limit: int,
|
|
58
|
+
config: HarnessWebConfig,
|
|
59
|
+
) -> list[dict[str, str]]:
|
|
60
|
+
base = config.searxng_url
|
|
61
|
+
if not base:
|
|
62
|
+
raise SystemExit("HARNESS_WEB_SEARXNG_URL is not set")
|
|
63
|
+
|
|
64
|
+
qs = urlencode({"q": query, "format": "json", "pageno": "1"})
|
|
65
|
+
url = f"{base}/search?{qs}"
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
status, body = _open_url(url, config=config)
|
|
69
|
+
except HTTPError as err:
|
|
70
|
+
status = err.code
|
|
71
|
+
body = err.read().decode("utf-8", errors="replace") if err.fp else ""
|
|
72
|
+
except URLError as err:
|
|
73
|
+
raise SystemExit(
|
|
74
|
+
f"SearXNG request failed ({err.reason}). "
|
|
75
|
+
f"Is the instance running at {base}? "
|
|
76
|
+
"Run: node \"$UP_PKG/.pi/scripts/harness-searxng-bootstrap.mjs\""
|
|
77
|
+
) from err
|
|
78
|
+
|
|
79
|
+
if status == 403:
|
|
80
|
+
raise SystemExit(
|
|
81
|
+
"SearXNG returned 403 for format=json. Enable json under search.formats "
|
|
82
|
+
"in settings.yml (see .searxng/core-config/settings.yml or SearXNG docs)."
|
|
83
|
+
)
|
|
84
|
+
if status != 200:
|
|
85
|
+
snippet = body[:200].replace("\n", " ")
|
|
86
|
+
raise SystemExit(f"SearXNG search failed (HTTP {status}): {snippet}")
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
payload = json.loads(body)
|
|
90
|
+
except json.JSONDecodeError as err:
|
|
91
|
+
raise SystemExit(f"SearXNG returned non-JSON response from {url}") from err
|
|
92
|
+
|
|
93
|
+
results = _parse_results(payload, limit)
|
|
94
|
+
if not results and isinstance(payload, dict):
|
|
95
|
+
unresponsive = payload.get("unresponsive_engines")
|
|
96
|
+
if unresponsive:
|
|
97
|
+
raise SystemExit(
|
|
98
|
+
f"SearXNG returned no results; upstream engines unresponsive: {unresponsive}"
|
|
99
|
+
)
|
|
100
|
+
return results
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [v0.5.0] — 2026-05-17
|
|
8
|
+
|
|
9
|
+
### ✨ Features
|
|
10
|
+
|
|
11
|
+
- **web_search / web_fetch pi tools:** wrap `harness-web.py` with session injection and a bash guard so agents skip `UP_PKG` and scrapling import preflights.
|
|
12
|
+
- **SearXNG search backend:** pluggable `HARNESS_WEB_SEARCH_ENGINE` (`ddg_html` | `searxng`) with Docker bootstrap via `harness-searxng-bootstrap.mjs`.
|
|
13
|
+
- **harness-web status:** JSON config subcommand for setup and diagnostics.
|
|
14
|
+
|
|
15
|
+
### 🔧 Chores
|
|
16
|
+
|
|
17
|
+
- Apply pre-commit format and refresh `graphify-out` after harness-web tools merge.
|
|
18
|
+
|
|
7
19
|
## [v0.4.1] — 2026-05-17
|
|
8
20
|
|
|
9
21
|
### ✨ Features
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultimate-pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Ultimate AI coding harness for pi.dev — extensible skills, Obsidian wiki knowledge layer, compressed context, deterministic output",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@mariozechner/pi-coding-agent": "*"
|
|
75
75
|
},
|
|
76
76
|
"scripts": {
|
|
77
|
-
"check:ts": "tsc --noEmit --target ES2023 --lib ES2023 --moduleResolution nodenext --module nodenext --skipLibCheck .pi/extensions/lib/harness-vcc-settings.ts .pi/extensions/dotenv-loader.ts .pi/extensions/lib/posthog-node.d.ts .pi/extensions/lib/harness-posthog.ts .pi/extensions/lib/harness-paths.ts .pi/extensions/pi-model-router-harness.ts .pi/extensions/provider-payload-sanitize.ts .pi/extensions/harness-telemetry.ts .pi/extensions/harness-ask-user.ts .pi/extensions/lib/ask-user/schema.ts .pi/extensions/lib/ask-user/types.ts .pi/extensions/lib/ask-user/validate.ts .pi/extensions/lib/ask-user/dialog.ts .pi/extensions/lib/ask-user/fallback.ts .pi/extensions/lib/ask-user/render.ts .pi/extensions/trace-recorder.ts .pi/extensions/observation-bus.ts .pi/extensions/drift-monitor.ts .pi/extensions/sentrux-rules-sync.ts .pi/extensions/custom-header.ts .pi/extensions/lib/harness-subagents/agent-loader.ts .pi/extensions/lib/harness-subagents/agent-parser.ts .pi/extensions/lib/harness-subagents/agent-manifest.ts .pi/extensions/lib/harness-subagents/blackboard.ts .pi/extensions/lib/harness-subagents/blackboard-tool.ts .pi/extensions/lib/harness-subagents/spawn-policy.ts .pi/extensions/lib/harness-subagents/types-blackboard.ts",
|
|
77
|
+
"check:ts": "tsc --noEmit --target ES2023 --lib ES2023 --moduleResolution nodenext --module nodenext --skipLibCheck .pi/extensions/lib/harness-vcc-settings.ts .pi/extensions/dotenv-loader.ts .pi/extensions/lib/posthog-node.d.ts .pi/extensions/lib/harness-posthog.ts .pi/extensions/lib/harness-paths.ts .pi/extensions/pi-model-router-harness.ts .pi/extensions/provider-payload-sanitize.ts .pi/extensions/harness-telemetry.ts .pi/extensions/harness-ask-user.ts .pi/extensions/lib/ask-user/schema.ts .pi/extensions/lib/ask-user/types.ts .pi/extensions/lib/ask-user/validate.ts .pi/extensions/lib/ask-user/dialog.ts .pi/extensions/lib/ask-user/fallback.ts .pi/extensions/lib/ask-user/render.ts .pi/extensions/trace-recorder.ts .pi/extensions/observation-bus.ts .pi/extensions/drift-monitor.ts .pi/extensions/sentrux-rules-sync.ts .pi/extensions/custom-header.ts .pi/extensions/lib/harness-subagents/agent-loader.ts .pi/extensions/lib/harness-subagents/agent-parser.ts .pi/extensions/lib/harness-subagents/agent-manifest.ts .pi/extensions/lib/harness-subagents/blackboard.ts .pi/extensions/lib/harness-subagents/blackboard-tool.ts .pi/extensions/lib/harness-subagents/spawn-policy.ts .pi/extensions/lib/harness-subagents/types-blackboard.ts .pi/extensions/harness-web-tools.ts .pi/extensions/harness-web-guard.ts .pi/extensions/lib/harness-web/run-cli.ts",
|
|
78
78
|
"vendor:sync-router": "bash .pi/scripts/vendor-sync-pi-model-router.sh",
|
|
79
79
|
"vendor:sync-vcc": "bash .pi/scripts/vendor-sync-pi-vcc.sh",
|
|
80
80
|
"release": "bash .pi/scripts/release.sh",
|