Commit Graph
21 Commits
Author SHA1 Message Date
Lucas WintherandClaude Opus 5.5 5c63f17cff feat(ai): structured tool calls on ChatMessage (contract request 3)
ChatMessage gains toolCalls and an opaque providerData; providers may
yield providerData once per turn. The assistant loop appends one
assistant message per model turn. Anthropic replays its own raw blocks
from providerData (no in-memory map) or maps text + tool_use blocks;
OpenAI maps toolCalls to tool_calls.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 20:36:38 +01:00
Lucas WintherandClaude Opus 5.5 ddc66f5be5 feat(ai): encrypt MCP env and headers at rest and mask them in the admin API
env/headers are sealed into secretCipher with the BYOK AES-GCM/HKDF box.
The admin GET returns masked values; a mask posted back for the same
server and key keeps the stored value, any other mask is a 400. The chat
and the test button use the stored values. upgradeAiData seals plaintext
v1 rows.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 20:33:56 +01:00
Lucas WintherandClaude Opus 5.5 a995900fba feat(ai): per-course mentor preferences table (contract request 4)
0002_ai_mentor_prefs.sql adds ai_mentor_prefs(user_id, course_id, off).
upgradeAiData copies v1 config_json.mentorOff toggles into it once
(marked ai_data_v11 in schema_migrations); the settings repo awaits the
upgrade before first use and aiFeature starts it at construction.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 20:30:59 +01:00
Lucas WintherandClaude Opus 5.5 d34a5c1f0c feat(ai): citations column on ai_messages (contract request 5)
New packages/feature-ai/migrations/0001_ai_message_citations.sql adds
ai_messages.citations_json and folds v1 'sources' rows into the assistant
row before them. The feature writes and reads the column directly.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 20:28:23 +01:00
Lucas WintherandClaude Opus 5.5 777ae2cc37 feat: resolve Phase 1 contract requests and compose every feature
Contracts and core:
- Feature gains auth and stop; FeatureFactory; core composeServer builds the
  context, runs the factories, then the job queue from the union of their jobs
  (R8/R14). startServer uses it; main.ts composes learner, import, studio, AI.
- AppConfig/loadConfig own the layout and settings: courseDirs include
  <dataDir>/courses and <dataDir>/worktrees, studioReposDir, cacheDir,
  importRoots, uploadMaxMb, aiAllowedBaseUrls, transcribeUrl, python.
  resolveConfig derives the same for tests; cachePaths shares the importer's
  cache layout.
- canView: the global author role views every course (R14); the learner,
  studio and AI packages all call it.
- migrate(db, packages): core first, then packages in name order.
- Media: nosniff on every response, a sandbox CSP on svg/html/js; a Range on
  an empty file is 416.
- courseUrl/lessonUrl and the lesson route patterns live in @stc/contracts.

Packages:
- import, studio and AI read AppConfig instead of process.env; the importer
  refuses ids used by studio/repos.
- learner migrations run through core migrate; library covers fall back to
  the importer's cached candidate behind a canView-checked route.
- studio preview renders through the learner LessonView (anchors honoured,
  draft URLs); AI drafts go to the studio draft branch for studio courses (as
  the requesting user) and to <dataDir>/drafts otherwise, and the generator
  page says which.

Web: tsconfig paths for @stc/<feature>/web browser entries; features.ts
imports them by package name; nav.roles hides links by role.

Tests: compose, config, canView, media headers, migrations order, covers,
preview, nav, SPA bundle without server code, and an end-to-end flow on
SQLite and Postgres.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 15:02:46 +01:00
Lucas WintherandClaude Opus 5.5 f3ce2e34bf fix(ai): lessonUrl builder in one place; authoring follows core canView
- Learner links go through lessonUrl/courseUrl (src/web/urls.ts).
- Generation, the studio course list and file listing require an authoring
  right and core canView, so a global author needs a grant for a restricted
  course. Contract requests 8 (global author in canView) and 9
  (STC_AI_ALLOWED_BASE_URLS in AppConfig).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 04:49:48 +01:00
Lucas WintherandClaude Opus 5.5 ead7327bb1 fix(ai): solution and hidden-file guard runs on the canonical real path
read_file and read_lesson URL-decode, posix-normalise, reject .. and absolute
paths, resolve through CourseRepository.resolvePath (symlinks followed), then
guard the real course-relative path and compare real paths with every
manifest browser.solution. Hidden files are refused too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 04:48:56 +01:00
Lucas WintherandClaude Opus 5.5 cfc41c6a63 fix(ai): stdio MCP servers get PATH, HOME, LANG and their configured env only
STC_SECRET, database URLs and API keys are no longer inherited by MCP child
processes. Test: a fake server reports its environment.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 04:47:47 +01:00
Lucas WintherandClaude Opus 5.5 a13cc66ebb fix(ai): BYOK endpoints limited to official presets and admin-allowed origins (SSRF)
- A user's own key goes only to https://api.anthropic.com, https://api.openai.com/v1
  or an origin listed in STC_AI_ALLOWED_BASE_URLS / the server config's
  allowedBaseUrls; anything else is a 400, and a stored key whose origin was
  later removed stops being used.
- User-scope provider calls never follow redirects, and their errors reach the
  user only as the HTTP status plus a fixed message; the full text is logged.
- The admin's server-scope provider may still use any base URL.
- Admin UI: allowed origins field; MCP stdio env editable, HTTP headers kept.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 04:47:25 +01:00
Lucas WintherandClaude Opus 5.5 a47e6e0971 feat(ai): my_progress tool so the assistant sees the learner's progress
Spec 9.2 has the assistant retrieve from the learner's notes and progress;
progress was missing. Reads progressRepo(db).get for the signed-in user.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 04:37:25 +01:00
Lucas WintherandClaude Opus 5.5 6fb0019cd9 feat(ai): read the importer's deck and transcript cache; studio DraftWriter fits DraftSink as is
Retrieval now reads <dataDir>/cache/decks/<courseId>/<deckId>/text.json and
<dataDir>/cache/transcripts/<courseId>/<lessonId>.json (skipped when the lesson
has a transcript file). DraftSink returns { location?, branch?, commit? }, so
the studio's createDraftWriter(ctx) needs no adapter; generateDraft computes
paths itself and reports the draft branch.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 04:36:48 +01:00
Lucas WintherandClaude Opus 5.5 08d3e3f642 feat(ai): assistant panel, AI settings and studio generator UI
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:30:22 +01:00
Lucas WintherandClaude Opus 5.5 a57222ecc3 feat(ai): HTTP routes, chat streaming and generation job
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:25:10 +01:00
Lucas WintherandClaude Opus 5.5 3cec42bba5 feat(ai): house-style generator writing drafts through a DraftSink
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:22:38 +01:00
Lucas WintherandClaude Opus 5.5 49d1df0f13 feat(ai): assistant prompt, course tools and tool loop
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:20:31 +01:00
Lucas WintherandClaude Opus 5.5 24cd6329cb feat(ai): MCP client over stdio and streamable HTTP
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:19:13 +01:00
Lucas WintherandClaude Opus 5.5 50e1e49b6d feat(ai): BM25 course retrieval over lessons, transcripts, code, deck text and notes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:18:21 +01:00
Lucas WintherandClaude Opus 5.5 76ea0d5101 feat(ai): OpenAI-compatible provider (covers Ollama)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:16:06 +01:00
Lucas WintherandClaude Opus 5.5 3c2220145b feat(ai): Anthropic provider over fetch with streaming tool use
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:15:33 +01:00
Lucas WintherandClaude Opus 5.5 bccbc692e9 feat(ai): settings repository for server config, BYOK keys and mentor toggles
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:14:29 +01:00
Lucas WintherandClaude Opus 5.5 e1938b5be8 feat(ai): package scaffold and AES-GCM secret box
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:13:50 +01:00