-
Notifications
You must be signed in to change notification settings - Fork 0
Archive: post-init work (19 commits) #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
eb5a904
ce3bce3
6559bdf
0ad374c
7177a64
23d8ae0
ba1f218
c07e4ef
f6a363f
874a38e
4c136e4
531d0a2
c8bca84
219dc23
d4163e9
0a6b034
dfce124
ecd7c5d
c34dc03
22aa874
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| node_modules | ||
| packages | ||
| dist | ||
| .git | ||
| .env |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,16 +1,28 @@ | ||||||
| .PHONY: build clean lint docker-build docker-build-simple-email docker-build-send-email-link docker-push docker-push-simple-email docker-push-send-email-link | ||||||
| .PHONY: build clean lint test test-all build-test-runner docker-build docker-build-simple-email docker-build-send-email-link docker-push docker-push-simple-email docker-push-send-email-link | ||||||
|
|
||||||
| REGISTRY := ghcr.io/constructive-io/constructive-functions | ||||||
| # Detect kind binary (search PATH, fallback to Homebrew) | ||||||
| KIND_BIN := $(shell which kind) | ||||||
| ifeq ($(KIND_BIN),) | ||||||
| KIND_BIN := /opt/homebrew/bin/kind | ||||||
| endif | ||||||
| KIND_CLUSTER_NAME ?= interweb-local | ||||||
|
|
||||||
| SUBDIRS := functions/hello-world functions/simple-email functions/send-email-link functions/runtime-script | ||||||
|
|
||||||
| build: | ||||||
| pnpm run build | ||||||
| pnpm -r build | ||||||
|
|
||||||
| clean: | ||||||
| pnpm run clean | ||||||
| pnpm -r clean | ||||||
|
|
||||||
| lint: | ||||||
| pnpm run lint | ||||||
| pnpm -r lint | ||||||
|
|
||||||
| test: | ||||||
| pnpm -r test | ||||||
|
||||||
| pnpm -r test | |
| pnpm -r --workspace-concurrency=1 test |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| # Python runtime for LLM API inference (OpenAI & Claude) | ||
| # This module makes API calls to OpenAI and Anthropic for LLM inference | ||
| # For the full fat container with Ollama & local models, see Dockerfile.ollama | ||
| # Based on: /Users/0xj0/Documents/projects/LQL/CONSTRUCTIVE/agentic-foundation | ||
|
|
||
| ##################### heres what is had inside of (/Users/0xj0/Documents/projects/LQL/CONSTRUCTIVE/agentic-foundation) -- GO VERIFY YOURSELF | ||
|
|
||
| # Builder Stage | ||
| FROM rust:latest as builder | ||
| WORKDIR /app | ||
| COPY . . | ||
| # Build agent_core | ||
| RUN cargo build --release --bin agent_core | ||
|
|
||
| # Runtime Stage - "Fat Container" | ||
| FROM ubuntu:22.04 | ||
| WORKDIR /app | ||
|
|
||
| # Set non-interactive install | ||
| ENV DEBIAN_FRONTEND=noninteractive | ||
|
|
||
| # 1. Install Basic Tools & Runtimes (Python, Node, System Utils) | ||
| RUN apt-get update && apt-get install -y \ | ||
| curl wget git build-essential \ | ||
| python3 python3-pip python3-venv \ | ||
| nodejs npm \ | ||
| postgresql-14 postgresql-client-14 \ | ||
| sudo \ | ||
| libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 \ | ||
| libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 \ | ||
| chromium-browser \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # 2. Install Rust in Runtime (for the agent to use `cargo`) | ||
| RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y | ||
| ENV PATH="/root/.cargo/bin:${PATH}" | ||
|
|
||
| # 3. Install PostGraphile | ||
| # 3. Install PostGraphile | ||
| RUN npm install -g pnpm && pnpm add -g postgraphile @graphile-contrib/pg-simplify-inflector | ||
|
|
||
| # 4. Install Ollama & Bake Models | ||
| # We install Ollama, then start it in the background to pull models into the image layers. | ||
| RUN curl -fsSL https://ollama.com/install.sh | sh | ||
|
|
||
| # Pre-pull Models (Using available equivalents for the '2025' spec models) | ||
| # GPT-OSS -> llama3.2 (Small, open, robust) | ||
| # Qwen3-VL -> llava (Vision model standard in Ollama) | ||
| # Devstral -> qwen2.5-coder (Excellent coding model) | ||
| # Nemotron -> mistral (Strong reasoning) | ||
| RUN nohup bash -c "ollama serve" & \ | ||
| sleep 10 && \ | ||
| ollama pull llama3.2 && \ | ||
| ollama pull llava && \ | ||
| ollama pull qwen2.5-coder && \ | ||
| ollama pull mistral && \ | ||
| pkill ollama | ||
|
|
||
| # 5. Setup Data & Permissions | ||
| RUN mkdir -p /var/lib/postgresql/data && chown -R postgres:postgres /var/lib/postgresql/data | ||
|
|
||
| # 6. Copy Binaries & Scripts | ||
| COPY --from=builder /app/target/release/agent_core /app/agent_core | ||
| COPY scripts/entrypoint.sh /app/entrypoint.sh | ||
| RUN chmod +x /app/entrypoint.sh | ||
|
|
||
| # 7. Config | ||
| ENV DATABASE_URL=postgres://agent:agent@localhost:5432/agentic | ||
| ENV OLLAMA_HOST=0.0.0.0:11434 | ||
|
|
||
| EXPOSE 3000 5432 11434 5000 | ||
|
|
||
| ENTRYPOINT ["/app/entrypoint.sh"] | ||
| CMD ["./agent_core"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| FROM node:22-alpine | ||
|
|
||
| WORKDIR /usr/src/app | ||
|
|
||
| COPY package.json ./ | ||
|
|
||
| RUN npm install -g pnpm@10.12.2 && pnpm install --prod | ||
|
|
||
| COPY dist ./dist | ||
| COPY runner.js ./runner.js | ||
|
|
||
| ENV NODE_ENV=production | ||
| ENV PORT=8080 | ||
|
|
||
| USER node | ||
|
|
||
| CMD ["node", "runner.js", "dist/index.js"] | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| FROM node:20-alpine | ||
|
|
||
| # Install Postgres Client and Build Tools | ||
| RUN apk add --no-cache postgresql-client bash make g++ python3 kubectl | ||
|
|
||
| COPY . /app | ||
| WORKDIR /app | ||
|
|
||
| # Ensure clean slate | ||
| RUN rm -rf node_modules | ||
|
|
||
| # 3. Configure PNPM Home | ||
| ENV PNPM_HOME="/root/.local/share/pnpm" | ||
| ENV PATH="$PNPM_HOME:$PATH" | ||
| ENV SHELL="/bin/bash" | ||
|
|
||
| # 4. Install Dependencies from NPM | ||
| RUN npm install -g pnpm@9 && \ | ||
| pnpm setup && \ | ||
| pnpm install --no-frozen-lockfile | ||
|
|
||
| # 5. Connect to global (not needed for pnpm v9+) | ||
| # RUN pnpm route-global | ||
|
|
||
| # 6. Install PGPM from NPM | ||
| RUN pnpm add -g pgpm | ||
|
|
||
| # Run as postgres user to avoid 'role root does not exist' in pgsql-test | ||
| # handle existing user/group if created by apk | ||
| RUN (getent group postgres || addgroup -S postgres) && (getent passwd postgres || adduser -S postgres -G postgres) | ||
| RUN chown -R postgres:postgres /app | ||
| USER postgres | ||
| ENV USER=postgres | ||
| ENV PGUSER=postgres | ||
|
|
||
| # 6. Setup Entrypoint (Inlined for Minimalism) | ||
| ENV NODE_ENV=test | ||
| CMD ["/bin/bash", "-c", "set -e; \ | ||
| echo \"Waiting for Postgres at $PGHOST:$PGPORT...\"; \ | ||
| until pg_isready -h \"$PGHOST\" -p \"$PGPORT\" -U \"$PGUSER\"; do echo \"Waiting...\"; sleep 2; done; \ | ||
| echo \"Deploying Schema...\"; \ | ||
| pgpm deploy --package pgpm-database-jobs --database template1 --yes 2>/dev/null || echo \"Deploy continued...\"; \ | ||
| unset PGDATABASE; \ | ||
| pnpm test"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| const path = require('path'); | ||
| const fs = require('fs'); | ||
|
|
||
| const run = async () => { | ||
| // 1. Resolve Dependencies from CWD (User's Function Context) | ||
| // This logic ensures we find express/graphql-request in the function's node_modules, | ||
| // regardless of where runner.js is located (Local Dev vs Docker). | ||
| const resolveDep = (name) => { | ||
| try { | ||
| return require(require.resolve(name, { paths: [process.cwd()] })); | ||
| } catch (e) { | ||
| console.error(`[runner] Failed to resolve dependency '${name}' from ${process.cwd()}`); | ||
| console.error(e.message); | ||
| process.exit(1); | ||
| } | ||
| }; | ||
|
|
||
| const express = resolveDep('express'); | ||
| const bodyParser = resolveDep('body-parser'); | ||
| const { GraphQLClient } = resolveDep('graphql-request'); | ||
|
Comment on lines
+18
to
+20
|
||
| const http = require('http'); | ||
| const https = require('https'); | ||
| const { URL } = require('url'); | ||
|
|
||
| // 2. Resolve User Handler | ||
| const relativePath = process.argv[2] || 'dist/index.js'; | ||
| const absolutePath = path.resolve(process.cwd(), relativePath); | ||
|
|
||
| let userModule; | ||
| try { | ||
| userModule = require(absolutePath); | ||
| } catch (e) { | ||
| console.error(`[runner] Failed to load function at ${absolutePath}`); | ||
| console.error(e.message); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| const handler = userModule.default || userModule; | ||
|
|
||
| if (typeof handler !== 'function') { | ||
| console.error(`[runner] Export at ${absolutePath} is not a function.`); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| // 3. Setup App & Helper Functions (Ported from knative-job-fn/src/index.ts) | ||
| // We implement a simplified version of the logic to avoid needing deep imports. | ||
| // However, since we are replacing the shim which used `express` directly usually, | ||
| // or `knative-job-fn` library... | ||
| // Correct approach: The shim used `app` from `@constructive-io/knative-job-fn`. | ||
| // We should try to use THAT if available, to preserve exact behavior (headers, logging). | ||
|
|
||
| let app; | ||
| try { | ||
| // Try to load the standard wrapper if present | ||
| const jobFn = resolveDep('@constructive-io/knative-job-fn'); | ||
| // The library usually exports { default: { post: ..., listen: ... } } or similar? | ||
| // Let's check how functions imported it: "import app from '@constructive-io/knative-job-fn';" | ||
| // It exports 'default'. | ||
| const lib = jobFn.default || jobFn; | ||
|
|
||
| // The library exposes an 'app' like object but 'listen' is the main entry. | ||
| // But we want to inject our handler into a route. | ||
| // Library usage in shim: `app.post('/', ...)` | ||
| // Library implementation: `app` IS express() basically, but wrapped. | ||
|
|
||
| // Actually the library exports an object: { post: ..., listen: ... } | ||
| // We can use it directly. | ||
| app = lib; | ||
| } catch (e) { | ||
| // Fallback to raw express if wrapper missing (unlikely given package.json) | ||
| console.warn('[runner] @constructive-io/knative-job-fn not found, falling back to raw express'); | ||
| app = express(); | ||
| app.use(bodyParser.json()); | ||
| } | ||
|
|
||
| // 4. Setup GraphQL Client | ||
| const graphqlEndpoint = process.env.GRAPHQL_ENDPOINT || 'http://constructive-server:3000/graphql'; | ||
| if (!process.env.GRAPHQL_ENDPOINT) { | ||
| // Warn if falling back, to aid debugging | ||
| console.warn(`[runner] GRAPHQL_ENDPOINT not set, defaulting to internal k8s service: ${graphqlEndpoint}`); | ||
| } | ||
| const client = new GraphQLClient(graphqlEndpoint); | ||
|
|
||
| // 5. Setup Route | ||
| app.post('/', async (req, res) => { | ||
| try { | ||
| const result = await handler(req.body, { client, headers: req.headers }); | ||
|
|
||
| // Standard Shim Error Handling Heuristics | ||
| if (result && result.error) { | ||
| // Heuristics for 400 vs 500 | ||
| if (['Missing prompt', 'Unsupported provider', 'Missing "query" in payload', | ||
| 'Missing repoName or githubToken', 'Missing X-Database-Id header or DEFAULT_DATABASE_ID', | ||
| 'Missing required field', "Either 'html' or 'text' must be provided", | ||
| "Missing address, message, or signature"].some(s => result.error.includes(s) || s === result.error)) { | ||
| return res.status(400).json(result); | ||
| } | ||
| return res.status(500).json(result); | ||
| } | ||
|
|
||
| res.status(200).json(result); | ||
| } catch (e) { | ||
| console.error(e); | ||
| res.status(500).json({ error: e.message }); | ||
| } | ||
| }); | ||
|
|
||
| // 6. Start Server | ||
| const port = Number(process.env.PORT ?? 8080); | ||
| app.listen(port, () => { | ||
| console.log(`[runner] Function '${relativePath}' listening on port ${port}`); | ||
| }); | ||
| }; | ||
|
|
||
| run().catch(e => { | ||
| console.error('[runner] Fatal:', e); | ||
| process.exit(1); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CI matrix includes functions whose tests reference images that are set to
imagePullPolicy: "Never"(e.g.,pytorch-gpu,rust-hello-world). In GitHub Actions, these images won’t exist in the kind node unless you explicitly build andkind loadthem during the workflow, so those matrix jobs should fail deterministically. Either (1) build/load those specific images in CI before running tests, or (2) change the tests/manifests to use pullable images (and setIfNotPresent/Alwaysas appropriate).