v0.3.0: Maslow + Awareness — self-learning bot with needs ladder, event-driven reflex, and TimeWeb fast advisor #27
+8
-12
@@ -29,24 +29,20 @@ GOOGLE_API_KEY=
|
|||||||
PI_DEFAULT_PROVIDER=openai
|
PI_DEFAULT_PROVIDER=openai
|
||||||
PI_DEFAULT_MODEL=gpt-5-mini
|
PI_DEFAULT_MODEL=gpt-5-mini
|
||||||
|
|
||||||
# --- Fast LLM tier (v0.3.0+) --------------------------------------------------
|
# --- Fast LLM tier (TimeWeb / OpenAI-compatible, v0.3.0+) --------------------
|
||||||
# Pi (CLI) handles slow deep analytics — post-mortem and 30-min reflection.
|
# Pi (CLI) handles slow deep analytics — post-mortem and 30-min reflection.
|
||||||
# A parallel "fast advisor" tier handles tactical "what to do RIGHT NOW"
|
# A parallel "fast advisor" tier handles tactical "what to do RIGHT NOW"
|
||||||
# decisions when the reflex is stuck / preempted. Any OpenAI-compatible
|
# decisions when the reflex is stuck / preempted. The default expectation
|
||||||
# endpoint works: TimeWeb, OpenAI direct, Groq, OpenRouter, local Ollama.
|
# is TimeWeb, but any OpenAI-compatible endpoint works (OpenAI direct,
|
||||||
|
# Groq, OpenRouter, local Ollama with the OpenAI shim).
|
||||||
#
|
#
|
||||||
# Leave blank to disable — the bot then runs without the fast tier
|
# Leave blank to disable — the bot then runs without the fast tier
|
||||||
# (rc.1 scaffold is a safe no-op when API_KEY is unset).
|
# (rc.1 scaffold is a safe no-op when API_KEY is unset).
|
||||||
#
|
TIMEWEB_BASE_URL=
|
||||||
# Example for TimeWeb (replace with your own endpoint + key + model):
|
TIMEWEB_API_KEY=
|
||||||
# PEPA_FAST_LLM_BASE_URL=https://api.gen-api.ru/api/v1
|
TIMEWEB_MODEL=
|
||||||
# PEPA_FAST_LLM_API_KEY=<paste your key here>
|
|
||||||
# PEPA_FAST_LLM_MODEL=gpt-5-mini
|
|
||||||
PEPA_FAST_LLM_BASE_URL=
|
|
||||||
PEPA_FAST_LLM_API_KEY=
|
|
||||||
PEPA_FAST_LLM_MODEL=
|
|
||||||
# Optional: request timeout in ms (default 8000)
|
# Optional: request timeout in ms (default 8000)
|
||||||
PEPA_FAST_LLM_TIMEOUT_MS=
|
TIMEWEB_TIMEOUT_MS=
|
||||||
|
|
||||||
# --- Bot behaviour ------------------------------------------------------------
|
# --- Bot behaviour ------------------------------------------------------------
|
||||||
# How often (seconds) the autonomous tick prompt fires. Set to 0 to disable.
|
# How often (seconds) the autonomous tick prompt fires. Set to 0 to disable.
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ L10 village_full глобальная цель (ферма + дом + сосе
|
|||||||
- `runtime/coach/advice.js`: `normalisePreferSkill` строго отбрасывает
|
- `runtime/coach/advice.js`: `normalisePreferSkill` строго отбрасывает
|
||||||
всё, что не в реестре (raise log, не дрейфит на fuzzy)
|
всё, что не в реестре (raise log, не дрейфит на fuzzy)
|
||||||
- `runtime/llm/provider.js` — OpenAI-совместимый клиент, конфигурируется
|
- `runtime/llm/provider.js` — OpenAI-совместимый клиент, конфигурируется
|
||||||
через env (`PEPA_FAST_LLM_BASE_URL`, `_API_KEY`, `_MODEL`); graceful
|
через env (`TIMEWEB_BASE_URL`, `TIMEWEB_API_KEY`, `TIMEWEB_MODEL`); graceful
|
||||||
fallback "no-op" если env не задан (бот не падает)
|
fallback "no-op" если env не задан (бот не падает)
|
||||||
- `runtime/coach/fast-advisor.js` — функция `advise({snapshot, reason})`
|
- `runtime/coach/fast-advisor.js` — функция `advise({snapshot, reason})`
|
||||||
с rate-limit (макс. 6 вызовов/час), таймаут 8с, JSON-парсинг ответа
|
с rate-limit (макс. 6 вызовов/час), таймаут 8с, JSON-парсинг ответа
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ fixed: (a) Pi now sees the real registry in its system prompt,
|
|||||||
namespace, with "USE ONLY THESE, never invent" instruction
|
namespace, with "USE ONLY THESE, never invent" instruction
|
||||||
- [`runtime/llm/provider.js`](../../runtime/llm/provider.js) —
|
- [`runtime/llm/provider.js`](../../runtime/llm/provider.js) —
|
||||||
OpenAI-compatible chat client, env-driven:
|
OpenAI-compatible chat client, env-driven:
|
||||||
- `PEPA_FAST_LLM_BASE_URL` (default `https://api.openai.com/v1`)
|
- `TIMEWEB_BASE_URL` (default `https://api.openai.com/v1`)
|
||||||
- `PEPA_FAST_LLM_API_KEY` (required to enable; safe no-op otherwise)
|
- `TIMEWEB_API_KEY` (required to enable; safe no-op otherwise)
|
||||||
- `PEPA_FAST_LLM_MODEL` (required)
|
- `TIMEWEB_MODEL` (required)
|
||||||
- `PEPA_FAST_LLM_TIMEOUT_MS` (default 8000)
|
- `TIMEWEB_TIMEOUT_MS` (default 8000)
|
||||||
- Supports JSON-mode via `response_format: { type: "json_object" }`
|
- Supports JSON-mode via `response_format: { type: "json_object" }`
|
||||||
- Surfaces `not_configured`, `no_model`, `http_<status>`,
|
- Surfaces `not_configured`, `no_model`, `http_<status>`,
|
||||||
`network_error`, `timeout`, `bad_json` codes
|
`network_error`, `timeout`, `bad_json` codes
|
||||||
@@ -167,9 +167,9 @@ Tests: 332 green (was 315 on rc.2, +17 new):
|
|||||||
start growing as the registry feedback closes the loop.
|
start growing as the registry feedback closes the loop.
|
||||||
3. **Set fast-advisor env when ready to test**:
|
3. **Set fast-advisor env when ready to test**:
|
||||||
```bash
|
```bash
|
||||||
export PEPA_FAST_LLM_BASE_URL="https://<timeweb-endpoint>/v1"
|
export TIMEWEB_BASE_URL="https://<timeweb-endpoint>/v1"
|
||||||
export PEPA_FAST_LLM_API_KEY="<key>"
|
export TIMEWEB_API_KEY="<key>"
|
||||||
export PEPA_FAST_LLM_MODEL="gpt-5-mini"
|
export TIMEWEB_MODEL="gpt-5-mini"
|
||||||
```
|
```
|
||||||
The advisor still isn't auto-triggered in rc.1 — it's wired in rc.3.
|
The advisor still isn't auto-triggered in rc.1 — it's wired in rc.3.
|
||||||
4. **Pick the next rc** from PLAN.md.
|
4. **Pick the next rc** from PLAN.md.
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export async function advise({
|
|||||||
force = false,
|
force = false,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
if (!isAvailable()) {
|
if (!isAvailable()) {
|
||||||
return { ok: false, code: "not_configured", detail: "set PEPA_FAST_LLM_API_KEY", latencyMs: 0 };
|
return { ok: false, code: "not_configured", detail: "set TIMEWEB_API_KEY", latencyMs: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import assert from "node:assert/strict";
|
|||||||
|
|
||||||
import { advise, isAvailable, _resetForTest, __testing } from "./fast-advisor.js";
|
import { advise, isAvailable, _resetForTest, __testing } from "./fast-advisor.js";
|
||||||
|
|
||||||
const API_KEY = "PEPA_FAST_LLM_API_KEY";
|
const API_KEY = "TIMEWEB_API_KEY";
|
||||||
const MODEL = "PEPA_FAST_LLM_MODEL";
|
const MODEL = "TIMEWEB_MODEL";
|
||||||
const BASE = "PEPA_FAST_LLM_BASE_URL";
|
const BASE = "TIMEWEB_BASE_URL";
|
||||||
|
|
||||||
function withEnv(env, fn) {
|
function withEnv(env, fn) {
|
||||||
const prev = {};
|
const prev = {};
|
||||||
@@ -43,6 +43,7 @@ test("advise: not_configured without API key", async () => {
|
|||||||
const res = await advise({ reason: "stuck" });
|
const res = await advise({ reason: "stuck" });
|
||||||
assert.equal(res.ok, false);
|
assert.equal(res.ok, false);
|
||||||
assert.equal(res.code, "not_configured");
|
assert.equal(res.code, "not_configured");
|
||||||
|
assert.match(res.detail, /TIMEWEB_API_KEY/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+10
-8
@@ -6,19 +6,21 @@
|
|||||||
// right now ("I'm wedged in a pit, what should I do?").
|
// right now ("I'm wedged in a pit, what should I do?").
|
||||||
//
|
//
|
||||||
// This provider opens a parallel path: any OpenAI-compatible HTTP endpoint
|
// This provider opens a parallel path: any OpenAI-compatible HTTP endpoint
|
||||||
// (TimeWeb, OpenAI direct, Groq, OpenRouter, local Ollama with the OpenAI
|
// (TimeWeb is the default — same env var convention as the user's other
|
||||||
// shim, …) producing a structured JSON answer in ≤8 seconds.
|
// projects — but OpenAI direct, Groq, OpenRouter, and local Ollama with
|
||||||
|
// the OpenAI shim all work with the same plumbing) producing a structured
|
||||||
|
// JSON answer in ≤8 seconds.
|
||||||
//
|
//
|
||||||
// Configuration is strictly env-driven. The provider is a NO-OP unless
|
// Configuration is strictly env-driven. The provider is a NO-OP unless
|
||||||
// PEPA_FAST_LLM_API_KEY is set, so it's safe to ship the code disabled.
|
// TIMEWEB_API_KEY is set, so it's safe to ship the code disabled.
|
||||||
|
|
||||||
import { info, warn } from "../log.js";
|
import { info, warn } from "../log.js";
|
||||||
|
|
||||||
const ENV = {
|
const ENV = {
|
||||||
BASE_URL: "PEPA_FAST_LLM_BASE_URL",
|
BASE_URL: "TIMEWEB_BASE_URL",
|
||||||
API_KEY: "PEPA_FAST_LLM_API_KEY",
|
API_KEY: "TIMEWEB_API_KEY",
|
||||||
MODEL: "PEPA_FAST_LLM_MODEL",
|
MODEL: "TIMEWEB_MODEL",
|
||||||
TIMEOUT_MS: "PEPA_FAST_LLM_TIMEOUT_MS",
|
TIMEOUT_MS: "TIMEWEB_TIMEOUT_MS",
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_BASE_URL = "https://api.openai.com/v1";
|
const DEFAULT_BASE_URL = "https://api.openai.com/v1";
|
||||||
@@ -58,7 +60,7 @@ export async function complete({
|
|||||||
}
|
}
|
||||||
const useModel = model || cfg.model;
|
const useModel = model || cfg.model;
|
||||||
if (!useModel) {
|
if (!useModel) {
|
||||||
return { ok: false, code: "no_model", detail: `set ${ENV.MODEL} or pass model arg`, latencyMs: 0 };
|
return { ok: false, code: "no_model", detail: `set ${ENV.MODEL} env or pass model arg`, latencyMs: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
|
|||||||
Reference in New Issue
Block a user