ultimate-pi 0.6.0 → 0.6.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.
|
@@ -1,30 +1,44 @@
|
|
|
1
1
|
# ultimate-pi harness — local secrets and paths (gitignored .env)
|
|
2
|
-
#
|
|
2
|
+
# Created by /harness-setup (harness-sync-env.mjs). Re-run setup to append newly introduced keys only.
|
|
3
3
|
|
|
4
|
-
# Telemetry
|
|
4
|
+
# --- Telemetry ---
|
|
5
|
+
# Harness domain events (harness-telemetry.ts); set false to disable harness_* only
|
|
5
6
|
HARNESS_TELEMETRY_ENABLED=true
|
|
6
7
|
|
|
7
|
-
# harness-web (Scrapling scrape + pluggable search)
|
|
8
|
+
# --- harness-web (Scrapling scrape + pluggable search) ---
|
|
8
9
|
HARNESS_WEB_FETCH_MODE=stealth
|
|
9
10
|
HARNESS_WEB_SEARCH_ENGINE=ddg_html
|
|
10
|
-
#
|
|
11
|
+
# When HARNESS_WEB_SEARCH_ENGINE=searxng (bootstrap via harness-searxng-bootstrap.mjs):
|
|
11
12
|
# HARNESS_WEB_SEARXNG_URL=http://127.0.0.1:8080
|
|
12
13
|
# HARNESS_WEB_PROXY=
|
|
13
14
|
# HARNESS_WEB_RATE_LIMIT_MS=2000
|
|
14
15
|
# HARNESS_WEB_TIMEOUT_MS=30000
|
|
15
16
|
|
|
16
|
-
#
|
|
17
|
+
# --- VCC compaction (env-only; no JSON config files) ---
|
|
18
|
+
# Default: VCC handles /compact and auto-compaction. Set false for Pi LLM compaction:
|
|
19
|
+
# HARNESS_VCC_COMPACTION=false
|
|
20
|
+
# HARNESS_VCC_DEBUG=true
|
|
21
|
+
|
|
22
|
+
# --- PostHog (optional) ---
|
|
23
|
+
# Project key — required for harness_* telemetry when HARNESS_TELEMETRY_ENABLED=true
|
|
17
24
|
# POSTHOG_API_KEY=
|
|
25
|
+
# POSTHOG_HOST=https://us.i.posthog.com
|
|
26
|
+
# POSTHOG_ENABLED=true
|
|
18
27
|
# POSTHOG_PROJECT_NAME=ultimate-pi
|
|
19
28
|
# POSTHOG_PRIVACY_MODE=false
|
|
29
|
+
# Personal API key — PostHog MCP / posthog-analyst skill only
|
|
30
|
+
# POSTHOG_PERSONAL_API_KEY=
|
|
31
|
+
# POSTHOG_MCP_FEATURES=llm_analytics
|
|
20
32
|
|
|
21
|
-
# Graphify semantic extract (optional; `graphify update .` needs no key)
|
|
33
|
+
# --- Graphify semantic extract (optional; `graphify update .` needs no key) ---
|
|
22
34
|
# GEMINI_API_KEY=
|
|
23
35
|
# GOOGLE_API_KEY=
|
|
24
36
|
# OPENAI_API_KEY=
|
|
37
|
+
# OPENAI_API_BASE=
|
|
25
38
|
|
|
26
|
-
#
|
|
27
|
-
|
|
39
|
+
# --- Wiki / Obsidian vault (optional) ---
|
|
40
|
+
VAULT_WIKI_PATH=vault/wiki
|
|
28
41
|
|
|
29
|
-
#
|
|
30
|
-
#
|
|
42
|
+
# --- Sentrux gate (optional) ---
|
|
43
|
+
# Require Sentrux stub for harness-verify (see .pi/scripts/harness-verify.mjs)
|
|
44
|
+
# HARNESS_SENTRUX_REQUIRED=true
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
readFile,
|
|
22
22
|
writeFile,
|
|
23
23
|
} from "node:fs/promises";
|
|
24
|
+
import { randomBytes } from "node:crypto";
|
|
24
25
|
import { constants } from "node:fs";
|
|
25
26
|
import { join, dirname } from "node:path";
|
|
26
27
|
import { fileURLToPath } from "node:url";
|
|
@@ -50,7 +51,10 @@ const SETTINGS_PATH = join(CORE_CONFIG, "settings.yml");
|
|
|
50
51
|
const COMPOSE_PATH = join(SEARXNG_DIR, "docker-compose.yml");
|
|
51
52
|
const ENV_COMPOSE = join(SEARXNG_DIR, ".env");
|
|
52
53
|
|
|
53
|
-
const
|
|
54
|
+
const DEFAULT_SECRET = "ultrasecretkey";
|
|
55
|
+
|
|
56
|
+
function buildHarnessSettings(secret) {
|
|
57
|
+
return `use_default_settings: true
|
|
54
58
|
|
|
55
59
|
search:
|
|
56
60
|
formats:
|
|
@@ -58,9 +62,11 @@ search:
|
|
|
58
62
|
- json
|
|
59
63
|
|
|
60
64
|
server:
|
|
65
|
+
secret_key: "${secret}"
|
|
61
66
|
limiter: false
|
|
62
67
|
public_instance: false
|
|
63
68
|
`;
|
|
69
|
+
}
|
|
64
70
|
|
|
65
71
|
async function exists(path) {
|
|
66
72
|
try {
|
|
@@ -138,6 +144,69 @@ async function readComposePort() {
|
|
|
138
144
|
return DEFAULT_PORT;
|
|
139
145
|
}
|
|
140
146
|
|
|
147
|
+
function parseEnvValue(raw) {
|
|
148
|
+
return raw.trim().replace(/^["']|["']$/g, "");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function readComposeSecret() {
|
|
152
|
+
if (!(await exists(ENV_COMPOSE))) return null;
|
|
153
|
+
const text = await readFile(ENV_COMPOSE, "utf8");
|
|
154
|
+
for (const line of text.split("\n")) {
|
|
155
|
+
const m = line.match(/^SEARXNG_SECRET=(.+)$/);
|
|
156
|
+
if (m) {
|
|
157
|
+
const val = parseEnvValue(m[1]);
|
|
158
|
+
if (val && val !== DEFAULT_SECRET) return val;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function readSettingsSecret() {
|
|
165
|
+
if (!(await exists(SETTINGS_PATH))) return null;
|
|
166
|
+
const text = await readFile(SETTINGS_PATH, "utf8");
|
|
167
|
+
const m = text.match(/^\s*secret_key:\s*["']?([^"'\n#]+)["']?\s*$/m);
|
|
168
|
+
if (!m) return null;
|
|
169
|
+
const val = m[1].trim();
|
|
170
|
+
return val && val !== DEFAULT_SECRET ? val : null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function generateSecret() {
|
|
174
|
+
return randomBytes(32).toString("hex");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function getOrCreateSecret() {
|
|
178
|
+
return (
|
|
179
|
+
(await readComposeSecret()) ||
|
|
180
|
+
(await readSettingsSecret()) ||
|
|
181
|
+
generateSecret()
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function upsertComposeSecret(secret) {
|
|
186
|
+
let content = "";
|
|
187
|
+
if (await exists(ENV_COMPOSE)) {
|
|
188
|
+
content = await readFile(ENV_COMPOSE, "utf8");
|
|
189
|
+
}
|
|
190
|
+
const line = `SEARXNG_SECRET=${secret}`;
|
|
191
|
+
const re = /^SEARXNG_SECRET=.*$/m;
|
|
192
|
+
if (re.test(content)) {
|
|
193
|
+
content = content.replace(re, line);
|
|
194
|
+
} else {
|
|
195
|
+
const sep = content.endsWith("\n") || content.length === 0 ? "" : "\n";
|
|
196
|
+
content = `${content}${sep}${line}\n`;
|
|
197
|
+
}
|
|
198
|
+
await writeFile(ENV_COMPOSE, content, "utf8");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function settingsNeedUpdate() {
|
|
202
|
+
if (!(await exists(SETTINGS_PATH))) return true;
|
|
203
|
+
const text = await readFile(SETTINGS_PATH, "utf8");
|
|
204
|
+
if (!text.includes("json")) return true;
|
|
205
|
+
if (text.includes(DEFAULT_SECRET)) return true;
|
|
206
|
+
if (!/^\s*secret_key:/m.test(text)) return true;
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
141
210
|
async function ensureSearxngLayout() {
|
|
142
211
|
await mkdir(CORE_CONFIG, { recursive: true });
|
|
143
212
|
if (!(await exists(COMPOSE_PATH))) {
|
|
@@ -152,12 +221,28 @@ async function ensureSearxngLayout() {
|
|
|
152
221
|
}
|
|
153
222
|
await copyFile(example, ENV_COMPOSE);
|
|
154
223
|
}
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
|
|
224
|
+
const secret = await getOrCreateSecret();
|
|
225
|
+
await upsertComposeSecret(secret);
|
|
226
|
+
console.log(`✓ Set SEARXNG_SECRET in ${ENV_COMPOSE}`);
|
|
227
|
+
if (await settingsNeedUpdate()) {
|
|
228
|
+
try {
|
|
229
|
+
await writeFile(SETTINGS_PATH, buildHarnessSettings(secret), "utf8");
|
|
230
|
+
console.log(
|
|
231
|
+
`✓ Wrote ${SETTINGS_PATH} (json format, limiter off, secret_key set)`,
|
|
232
|
+
);
|
|
233
|
+
} catch (err) {
|
|
234
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EACCES") {
|
|
235
|
+
console.warn(
|
|
236
|
+
`⚠ Could not write ${SETTINGS_PATH} (permission denied). ` +
|
|
237
|
+
"SEARXNG_SECRET in .env is set — restart containers. " +
|
|
238
|
+
`Fix ownership: chown -R $USER:$USER ${SEARXNG_DIR}`,
|
|
239
|
+
);
|
|
240
|
+
} else {
|
|
241
|
+
throw err;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
console.log(`✓ ${SETTINGS_PATH} already configured`);
|
|
161
246
|
}
|
|
162
247
|
}
|
|
163
248
|
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [v0.6.1] — 2026-05-17
|
|
8
|
+
|
|
9
|
+
### 🐛 Fixes
|
|
10
|
+
|
|
11
|
+
- **SearXNG bootstrap:** generate `SEARXNG_SECRET` and set `server.secret_key` so containers no longer crash on the default `ultrasecretkey` (SearXNG 2026.4+).
|
|
12
|
+
- **Harness env template:** remove obsolete `PI_VCC_CONFIG_PATH`; add env-only VCC, PostHog MCP, Sentrux, and default `VAULT_WIKI_PATH` keys aligned with `/harness-setup`.
|
|
13
|
+
|
|
7
14
|
## [v0.6.0] — 2026-05-17
|
|
8
15
|
|
|
9
16
|
### ✨ Features
|
package/package.json
CHANGED