Skip to content

Commit 02ea881

Browse files
authored
refactor!: rework pipeline and runtime into component-based engine architecture (#1)
Reworks the project from the initial single-purpose script into a component-based engine: a framework-free core pipeline, descriptor-driven built-ins (source providers, LLM providers, steps, renderers), and HTTP adapters wired through bundles. Also documents the squash-merge strategy for the project. Breaking; pre-1.0, no compatibility with 0.1.x internals. Co-authored-by: David Soušek <15769039+sousekd@users.noreply.github.com>
1 parent 0fe597d commit 02ea881

233 files changed

Lines changed: 10981 additions & 4996 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Build artifacts and dependencies (rebuilt inside the image)
1+
# Build artifacts and dependencies rebuilt inside the image
22
node_modules
33
dist
44
coverage
@@ -10,11 +10,11 @@ coverage
1010
.gitattributes
1111
.github
1212

13-
# Local config / secrets
13+
# Environment files are supplied at runtime, never baked into the image
1414
.env
1515
.env.*
1616

17-
# Tests and dev tooling (not needed in runtime image)
17+
# Tests and dev tooling not needed in the runtime image
1818
tests
1919
vitest.config.ts
2020
tsconfig.test.json
@@ -27,7 +27,7 @@ npm-debug.log*
2727
.idea
2828
.DS_Store
2929

30-
# Repo docs (kept in the source tree, excluded from the image to keep it small)
30+
# Repository docs stay outside the runtime image
3131
README.md
3232
docs
3333
AGENTS.md

.env.example

Lines changed: 74 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,84 @@
1-
# --- Docker Compose ------------------------------------------------------
2-
# Local image name used by compose.yaml. Ignored by the Node app.
1+
# --- Compose images ------------------------------------------------------
2+
# Local image name used by compose.yaml. Ignored by the Node app. Default: llm-context-loader:local
33
LLMC_LOCAL_IMAGE=llm-context-loader:local
4-
# Published image tag used by compose.deploy.yaml. Ignored by the Node app.
4+
5+
# Published image tag used by compose.deploy.yaml. Pin a release tag for repeatable deployments. Default: latest
56
LLMC_IMAGE_TAG=latest
67

7-
# --- Server --------------------------------------------------------------
8-
# Bind address. 0.0.0.0 listens on every interface; use 127.0.0.1 for local only.
9-
SERVER_HOST=0.0.0.0
10-
# TCP port the HTTP server listens on.
11-
SERVER_PORT=3010
12-
# pino log level: trace, debug, info, warn, error, fatal, silent.
8+
# --- Bootstrap -----------------------------------------------------------
9+
# YAML configuration file loaded at startup. Default: config/llm-context-loader.yaml
10+
CONFIG_FILE=config/llm-context-loader.yaml
11+
12+
# Bind address. Use 127.0.0.1 for local-only development. Default: 0.0.0.0
13+
HOST=0.0.0.0
14+
15+
# HTTP server listen port. Default: 3010
16+
PORT=3010
17+
18+
# pino log level: trace, debug, info, warn, error, fatal, or silent. Default: info
1319
LOG_LEVEL=info
1420

15-
# --- Auth / Diagnostics --------------------------------------------------
16-
# Require Authorization: Bearer <API_KEY> on real client routes.
17-
AUTH_ENABLED=false
18-
# Shared bearer token for POST / and GET /r/* when AUTH_ENABLED=true.
19-
API_KEY=
20-
# Append <context_loader_info /> and return diagnostic document on fetch failures.
21-
# When false, fetch failures throw HTTP errors and no footer is appended.
22-
DIAGNOSTIC_FOOTER_ENABLED=true
23-
24-
# --- Clients -------------------------------------------------------------
25-
# Comma-separated client plugins to register. Empty means only /health is served.
26-
# Built-ins: openwebui, jina.
27-
CLIENTS=openwebui,jina
28-
29-
# --- Fetch ---------------------------------------------------------------
30-
# Fetch provider implementation. v1 supports only "firecrawl".
31-
FETCH_PROVIDER=firecrawl
32-
# Per-URL fetch timeout in seconds.
33-
FETCH_TIMEOUT_SECONDS=60
34-
# Max parallel in-flight fetches across all requests.
35-
FETCH_CONCURRENCY=4
36-
# Base URL of Firecrawl instance.
37-
FIRECRAWL_BASE_URL=http://firecrawl-api:3002
38-
# Optional Firecrawl bearer token.
21+
# Pretty logs: auto detects TTY, true forces pretty output, false writes JSON. Default: auto
22+
LOG_PRETTY=auto
23+
24+
# --- Pipeline ------------------------------------------------------------
25+
# Maximum concurrent source-loading groups. Default: 1
26+
SOURCE_CONCURRENCY=4
27+
28+
# Maximum concurrent LLM workflow groups. Default: 1
29+
LLM_CONCURRENCY=2
30+
31+
# Output renderer used by the default pipeline. Default: debug-xml
32+
DEFAULT_OUTPUT_RENDERER=debug-xml
33+
34+
# Include skipped steps in the debug-xml footer. Default: false
35+
DEBUG_XML_INCLUDE_SKIPPED=false
36+
37+
# Desired maximum output size used by summarize and truncate steps. Default: 25000
38+
OUTPUT_TARGET_CHARS=35000
39+
40+
# --- Source provider -----------------------------------------------------
41+
# Firecrawl base URL used by the default source provider. Required, no default.
42+
FIRECRAWL_BASE_URL=https://firecrawl.example
43+
44+
# Optional Firecrawl bearer token. Default: empty (no token)
3945
FIRECRAWL_API_KEY=
40-
# Ask Firecrawl to strip boilerplate before returning markdown.
41-
FIRECRAWL_ONLY_MAIN_CONTENT=true
42-
43-
# --- LLM (shared) --------------------------------------------------------
44-
# LLM provider implementation. v1 supports only "openai_chat".
45-
LLM_PROVIDER=openai_chat
46-
# OpenAI-compatible Chat Completions base URL.
47-
LLM_BASE_URL=http://localhost:8080/v1
48-
# Optional LLM bearer token.
46+
47+
# --- LLM provider --------------------------------------------------------
48+
# OpenAI-compatible Chat Completions /v1 base URL. Required, no default.
49+
LLM_BASE_URL=https://openai-compatible.example/v1
50+
51+
# Optional LLM bearer token. Default: empty (no token)
4952
LLM_API_KEY=
50-
# Model identifier sent in chat-completions requests.
51-
LLM_MODEL=local-model
52-
# Model context window in tokens for stage eligibility checks.
53+
54+
# Model identifier sent to the chat-completions endpoint. Required, no default.
55+
LLM_MODEL=model-name
56+
57+
# Model context window in tokens. Default: empty (disables the context-fit gate)
5358
LLM_CONTEXT_TOKENS=131072
54-
# Rough chars-per-token estimate.
55-
LLM_CHARS_PER_TOKEN=4
56-
# Max parallel per-URL LLM workflows (clean + summarize together).
57-
LLM_CONCURRENCY=1
58-
# Extra JSON object merged into every chat-completions request body.
59-
# Any key wins. Example: {"temperature":0.7, ...}
60-
LLM_EXTRA_BODY=
61-
62-
# --- Clean stage ---------------------------------------------------------
63-
# Run a clean pass over fetched markdown.
64-
CLEAN_ENABLED=true
65-
# Skip cleanup below this compacted char count.
59+
60+
# Conservative chars-per-token estimate used by the context-fit gate. Default: 3.5
61+
LLM_CHARS_PER_TOKEN=3.5
62+
63+
# Extra tokens reserved for chat-template framing and estimator drift. Default: 128
64+
LLM_SAFETY_MARGIN_TOKENS=128
65+
66+
# --- Step thresholds and timeouts ---------------------------------------
67+
# Timeout in seconds for the source-loading step. Default: 20
68+
LOAD_SOURCE_TIMEOUT_SECONDS=20
69+
70+
# Timeout in seconds for the clean LLM pass. Default: 60
71+
CLEAN_TIMEOUT_SECONDS=90
72+
73+
# Minimum body length before the clean LLM pass runs. Default: 1000
6674
CLEAN_MIN_INPUT_CHARS=500
67-
# Hard cap on clean input size. 0 means no cap.
68-
CLEAN_MAX_INPUT_CHARS=75000
69-
# Output token budget reserved as a fraction of input tokens for context-window eligibility.
70-
CLEAN_OUTPUT_RATIO=0.5
71-
# Per-call timeout in seconds.
72-
CLEAN_TIMEOUT_SECONDS=60
73-
# Reject output when output/source ratio drops below this threshold.
74-
CLEAN_QUALITY_MIN_RATIO=0.02
75-
# Reject clean output that introduces URLs absent from source.
76-
CLEAN_CHECK_URLS=true
77-
78-
# --- Summarize stage -----------------------------------------------------
79-
# Run a summarize pass over current best content.
80-
SUMMARIZE_ENABLED=false
81-
# Skip summarization below this compacted char count.
82-
SUMMARIZE_MIN_INPUT_CHARS=25000
83-
# Hard cap on summarize input size. 0 means no cap.
84-
SUMMARIZE_MAX_INPUT_CHARS=0
85-
# Output token budget reserved as a fraction of input tokens for context-window eligibility.
86-
SUMMARIZE_OUTPUT_RATIO=0.15
87-
# Per-call timeout in seconds.
75+
76+
# Timeout in seconds for the summarize LLM pass. Default: 60
8877
SUMMARIZE_TIMEOUT_SECONDS=60
89-
# Reject output when output/source ratio drops below this threshold.
90-
SUMMARIZE_QUALITY_MIN_RATIO=0.01
91-
# Reject summarize output that introduces URLs absent from source.
92-
SUMMARIZE_CHECK_URLS=false
93-
94-
# --- Truncate stage ------------------------------------------------------
95-
# Hard cap on final response body length in characters.
96-
TRUNCATE_TARGET_CHARS=25000
97-
98-
# --- Templates -----------------------------------------------------------
99-
# Directory containing the Mustache templates below.
100-
TEMPLATE_DIR=./templates
101-
# Clean stage prompts (relative to TEMPLATE_DIR).
102-
CLEAN_SYSTEM_TEMPLATE=clean.system.md
103-
CLEAN_USER_TEMPLATE=clean.user.md
104-
# Summarize stage prompts (relative to TEMPLATE_DIR).
105-
SUMMARIZE_SYSTEM_TEMPLATE=summarize.system.md
106-
SUMMARIZE_USER_TEMPLATE=summarize.user.md
107-
# XML diagnostic footer template (relative to TEMPLATE_DIR).
108-
FOOTER_TEMPLATE=footer.md
78+
79+
# --- Inbound auth --------------------------------------------------------
80+
# Open WebUI adapter bearer token. Default: empty (leaves POST / open)
81+
OWUI_AUTH_TOKEN=
82+
83+
# Jina-style adapter bearer token. Default: empty (leaves GET /r open)
84+
JINA_AUTH_TOKEN=

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
node_modules/
1+
# Dependencies and build output
2+
node_modules/
23
dist/
34
coverage/
45
*.tsbuildinfo
56

7+
# Local environment files. Keep .env.example tracked.
68
.env
79
.env.local
810
.env.*.local
11+
!.env.example
912

13+
# Logs and OS noise
1014
*.log
1115
.DS_Store
1216

.prettierrc.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"printWidth": 120,
3+
"tabWidth": 2,
4+
"useTabs": false,
5+
"semi": true,
6+
"singleQuote": false,
7+
"quoteProps": "as-needed",
8+
"trailingComma": "none",
9+
"bracketSpacing": true,
10+
"bracketSameLine": false,
11+
"arrowParens": "avoid",
12+
"endOfLine": "lf",
13+
"proseWrap": "preserve"
14+
}

.vscode/extensions.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"recommendations": [
33
"editorconfig.editorconfig",
4+
"esbenp.prettier-vscode",
45
"vitest.explorer",
56
"ms-azuretools.vscode-docker",
67
"github.vscode-github-actions",

.vscode/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"editor.formatOnSave": true,
3+
"editor.defaultFormatter": "esbenp.prettier-vscode",
34
"js/ts.tsdk.path": "node_modules/typescript/lib",
5+
"vitest.cliArguments": "--project unit",
46
"search.exclude": {
57
"**/node_modules": true,
68
"**/dist": true,
@@ -13,4 +15,4 @@
1315
"**/dist/**": true,
1416
"**/coverage/**": true
1517
}
16-
}
18+
}

0 commit comments

Comments
 (0)