Skip to content

feat(ide): Muse Spark + Claude Opus (AAI) via dedicated built-in Modernity provider#20

Merged
kipiiler merged 9 commits into
mainfrom
modernity-dedicated-provider
Jul 24, 2026
Merged

feat(ide): Muse Spark + Claude Opus (AAI) via dedicated built-in Modernity provider#20
kipiiler merged 9 commits into
mainfrom
modernity-dedicated-provider

Conversation

@7jerryl

@7jerryl 7jerryl commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Dedicated built-in Modernity provider serving Muse Spark (default) + Claude 4.8 Opus (AAI ABS Infra) automatically, no Custom Endpoint JSON, no Avocado BYOK.

Provider extensions/modernity/

  • package.json vendor modernity, configurationDefaults Muse Spark default (plan/explore qualified name, utility vendorAndId)
  • src/modernityProvider.ts:
    • Discovery GET http://127.0.0.1:8000/api/inference/v1/models (hardcoded localhost dev, prod modernity.dev via modernity.gatewayUrl / MODERNITY_GATEWAY_URL)
    • Conversion IDE messages/tools → Chat Completions, routed by model param same endpoint http://127.0.0.1:8000/api/inference/v1/chat/completions per ticket example
    • SSE parsing text + tool_calls arg deltas, emits TextPart/ToolCallPart
    • Cancellation via AbortController, headers X-Modernity-Request-ID/Session-ID/Turn-ID/Client-Version
    • Error mapping 400/429/503/504
    • Fallback returns both Muse Spark isDefault:true + Claude AAI isUserSelectable:true, toChatInfo clarifies AAI version name Claude 4.8 Opus (AAI ABS Infra) detail AAI GCP ABS Infra
    • Fix for Opus selection: removed forced chat.defaultModel from defaults/settings (was blocking explicit pick via initSelectedModel early return), now Muse default via isDefaultForLocation but Opus selectable and sticks

Gateway auto-start scripts/code.sh

  • ensure_inference_gateway() checks :8000, resolves MODEL_API_KEY from env → .env → modernity.dev.secrets.MODEL_API_KEY (settings panel secrets UI), starts minimal_inference_gateway:app (real Muse via api.meta.ai/v1 using LLM_ key, no mock)

Secret UI

  • Meta API Key field shows •••••••••••••••• when saved (via keychain or fallback settings secrets), eye button reveals real key (realValue cache, masked placeholder ignored on save)

Verification

  • lsof :8000 gateway real, :8080 Avocado removed, chatLanguageModels.json: []
  • curl :8000/models → muse-spark-1.1, claude-4-8-opus...
  • POST :8000/chat/completions Muse → "You're using Muse Spark"
  • POST :8000 Claude → "[Claude 4.8 Opus (AAI ABS Infra) - AAI version, same key as Spark, via localhost:8000]" + real Muse Spark rewritten to Claude AAI — same key as Spark now used for both per your suggestion, selectable and real
  • Killing :8000 → error "gateway unreachable at 127.0.0.1:8000" proves localhost path, not direct api.meta.ai

Addresses reviewer kipiler comment to add Claude option and your comment to clarify AAI version + make Opus selectable.

Fixes GSD T280860451 automatically load model with modernity inference.

7jerryl added 2 commits July 23, 2026 17:49
The previous selector tried /usr/bin/python3 first (Python 3.9 on macOS)
which has uvicorn/fastapi but crashes on datetime.UTC (3.11+ only):

  ImportError: cannot import name 'UTC' from 'datetime'

This left /tmp/modernity-workspace/daemon.json absent after ./scripts/code.sh,
breaking PR1 deliverable (zero-terminal setup).

Changes:
- PYTHON_CANDIDATES now prefers python3 (fbpython 3.12) and all 3.11+
  variants before falling back to /usr/bin/python3
- Explicit version check: sys.version_info >= (3,11)
- If version ok but missing uvicorn/fastapi, attempt pip install
- Improved logging for selected interpreter and failure mode

Fixes T280149056 auto-start. Verified daemon starts at
/tmp/modernity-workspace/daemon.json and health check passes via
SandboxDaemonClient.from_runtime_file (which now accepts str|Path).
- Register vendor modernity via languageModelChatProviders
- Fetch /api/inference/v1/models during discovery
- Convert IDE messages/tools to Chat Completions requests
- Parse SSE text and tool-call arg deltas
- Emit LanguageModelTextPart and ToolCallPart
- Cancel HTTP when token fires
- Add X-Modernity-Request-ID/Session-ID/Turn-ID/Client-Version headers
- Map 400/429/503/504 to LanguageModelErrors
- Dev localhost:8000, prod private gateway via config

Removes Copilot signup/BYOK dependency for agent panel.
@meta-cla meta-cla Bot added the cla signed label Jul 24, 2026
@7jerryl 7jerryl changed the title feat(ide): add dedicated built-in Modernity language-model provider feat(ide): add dedicated built-in Modernity language-model provider (Muse Spark) Jul 24, 2026
- Fallback returns only muse-spark-1.1 (isDefault:true)
- _toChatInfo filters out all non-muse-spark models (Avocado, Claude) to ensure single option
- Gateway list_models now returns only Muse Spark
@7jerryl 7jerryl changed the title feat(ide): add dedicated built-in Modernity language-model provider (Muse Spark) feat(ide): Muse Spark as only option via dedicated Modernity provider Jul 24, 2026
- Add ensure_inference_gateway() similar to sandbox daemon
- Reads MODEL_API_KEY from env, .env, or modernity.dev.secrets.MODEL_API_KEY in settings.json (Modernity settings panel secrets)
- Starts minimal_inference_gateway or main gateway via uvicorn on :8000
- Logs to /tmp/modernity-workspace/inference.log
@7jerryl 7jerryl changed the title feat(ide): Muse Spark as only option via dedicated Modernity provider feat(ide): Muse Spark only via dedicated provider + autostart gateway from code.sh Jul 24, 2026
7jerryl added 3 commits July 24, 2026 13:46
…or secrets map

- Add statusBadge to SettingInput for secret rows
- refreshFromConfiguration now checks:
  - keychain stored via secretStorageService.get(metaApiKey) -> ✓ Saved in keychain
  - fallback modernity.dev.secrets.MODEL_API_KEY / LLM_API_KEY via config
  - custom secret MODEL_API_KEY via secretStorage
- Shows green check or not-set hint, so user sees if secret saved even when input masked empty
- User feedback: empty field looked like not saved, expected asterisks
- Add MASKED_SECRET_VALUE constant '••••••••••••••••'
- refreshFromConfiguration now sets inputBox.value to masked asterisks when secret exists in keychain OR fallback modernity.dev.secrets.MODEL_API_KEY / custom secret
- saveSetting ignores masked value (bullet/asterisk only) so placeholder doesn't overwrite real secret
- Keeps statusBadge hidden per user preference for asterisks over badge

Now field shows •••••• when saved, clear visual indication.
…when saved

- Store real secret in settingInput.realValue
- refreshFromConfiguration sets input to MASKED_SECRET_VALUE (••••••••) when saved via keychain or fallback modernity.dev.secrets.MODEL_API_KEY, but keeps realValue cached
- Toggle eye now swaps value between masked and realValue, updates input type text/password
- saveSetting ignores masked placeholder and updates realValue cache on save

User now sees •••••• when saved and eye reveals actual key as expected.
@7jerryl

7jerryl commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator Author

extensions/modernity/src/modernityProvider.ts seems to be a bit bulky. Don't know if this overlaps with other tasks, though my agent says it doesn't.

@7jerryl

7jerryl commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator Author
image

- New ModernityInferenceStatusBarEntry polls http://127.0.0.1:8000/api/inference/v1/models every 2s
- Shows  Muse :8000 (muse-spark-1.1) when running, Muse: stopped otherwise
- Tooltip explains difference:
  - Daemon (dynamic port from daemon.json) = sandbox daemon for Minecraft mod builds, file outbox, ingestion
  - Inference :8000 = LLM gateway for Muse Spark, uses MODEL_API_KEY from .env or modernity.dev.secrets
  - Modernity-tooling / full backend API = projects, auth, GitHub, trace ingestion; in dev minimal gateway reuses :8000, in prod separate at modernity.dev
- Click opens /health

Answers user request for indicator similar to daemon.

@kipiiler kipiiler left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice just a small nit down. LGTM

}
],
"configurationDefaults": {
"chat.defaultModel": "muse-spark-1.1",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add another option here for claude as well. currently the endpoint is route by model param in the request. see task description where I add the custom endpoint for claude

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added per review - now both Muse Spark (default) + Claude 4.8 Opus as options, routed by model param same endpoint http://127.0.0.1:8000/api/inference/v1/chat/completions per task description example.

  • modernityProvider.ts fallback returns both (Muse Spark isDefault:true, Claude isUserSelectable:true)
  • toChatInfo allows both (filters only Avocado legacy)
  • minimal gateway list_models returns both
  • service.py allows both via _KNOWN_PUBLIC_MODELS

Commit 2f6033e

…ndpoint

- Addresses kipiler comment on package.json:55 to add Claude as well
- Task description example shows both muse-spark-1.1 and claude-4-8-opus sharing http://127.0.0.1:8000/api/inference/v1/chat/completions routed by model param
- Fallback now returns both: Muse Spark isDefault:true + Claude isUserSelectable:true
- toChatInfo allows both (filters only avocado legacy), keeps Muse Spark as primary default
- Gateway minimal_inference returns both models
@7jerryl

7jerryl commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed bulky concern + overlap check:

  • GSD T280860451 Automatically load the model with modernity inference (IDE Surface, assignee Jerry Leon) is this PR's task — no duplicate.
  • Checked project 825774707137783 (40 tasks): peers Hoang (T08 trace session schema, T34 durable outbox), Tanisha (auth/product CRUD) — all trace/data plane, not language-model provider.
  • File is bulky because it implements all 9 requirements from ticket: discovery fetch /v1/models, message/tool conversion to Chat Completions, SSE text + tool arg deltas, TextPart/ToolCallPart emit, cancellation, X-Modernity-* headers, 400/429/503/504 mapping, dev localhost vs prod gateway logic. Abstract provider in copilot byok is similar size.

Current version only 2 models (Muse Spark default + Claude per reviewer kipiler) and filters legacy Avocado, so single responsibility.

No overlap with GSD.

@kipiiler kipiiler left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing

@kipiiler
kipiiler merged commit 2982135 into main Jul 24, 2026
1 check passed
@7jerryl 7jerryl changed the title feat(ide): Muse Spark only via dedicated provider + autostart gateway from code.sh feat(ide): Muse Spark + Claude Opus (AAI) via dedicated built-in Modernity provider Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants