Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
</td>
<td valign="top" width="50%">
<strong>Persistent admin and time travel</strong><br />
When something breaks, admin mode gives you a stable control plane, and Git-backed history lets you roll back user or group changes without taking everyone down with you.
Enter Space opens the native workspace shell. Admin mode gives you the stable control plane, and Git-backed history lets you roll back user or group changes without taking everyone down with you.
</td>
</tr>
</table>
Expand Down
2 changes: 1 addition & 1 deletion app/L0/_all/mod/_core/admin/views/agent/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Current behavior:
- the admin HuggingFace panel should let users either enter a compatible repo id directly or pick from the shared saved-model list, then load or unload that selection directly from the modal while reusing the same progress block and current-model status area as the routed sidebar
- the admin local-provider panel should show the selected model separately from the currently loaded model, so an unloaded but configured selection is visible immediately instead of looking stuck on `None loaded`
- when no Hugging Face model is selected and the shared saved-model list has entries, the admin local-provider panel should preselect the browser-wide last successfully loaded saved model from `_core/huggingface/manager.js`, falling back to the first saved entry if that last-used entry was discarded
- when no Hugging Face model is selected, no model is loaded, and the shared saved-model list is empty, the admin local-provider panel should prefill the model field with the same default used by the routed testing page: `onnx-community/gemma-4-E4B-it-ONNX`
- when no Hugging Face model is selected, no model is loaded, and the shared saved-model list is empty, the admin local-provider panel should prefill the model field with the same default used by the routed testing page: `onnx-community/Qwen3-0.6B-ONNX`
- admin-local provider inputs mounted through the shared sidebar components should write back through explicit `store.js` setter methods instead of depending on implicit nested `x-model` mutation across component boundaries
- discarding a HuggingFace repo from the routed testing harness removes it from the shared browser-side saved-model list too, so it disappears from the admin saved-model shortcut selector until it is loaded again
- admin should subscribe to `_core/huggingface/manager.js` directly, so the modal and send flow read the same live worker state, saved-model options, loading, and streaming behavior as the routed Hugging Face surface within the current browser context
Expand Down
53 changes: 32 additions & 21 deletions app/L0/_all/mod/_core/admin/views/agent/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -803,17 +803,6 @@ const model = {
return false;
}

const preferredSavedModel = huggingfaceManager.refreshPreferredSavedModelSelection();

if (preferredSavedModel?.modelId && preferredSavedModel?.dtype) {
this.settingsDraft = {
...this.settingsDraft,
huggingfaceDtype: preferredSavedModel.dtype,
huggingfaceModel: preferredSavedModel.modelId
};
return true;
}

const snapshot = huggingfaceManager.getSnapshot();
const hasSavedModels = Array.isArray(snapshot.savedModels) && snapshot.savedModels.length > 0;
const activeModelId = normalizeHuggingFaceModelInput(snapshot.activeModelId || "");
Expand Down Expand Up @@ -1633,21 +1622,31 @@ const model = {
},

openSettingsDialog() {
const provider = config.normalizeAdminChatLlmProvider(this.settings.provider);

this.settingsDraft = {
...this.settings,
promptBudgetRatios: clonePromptBudgetRatios(this.settings.promptBudgetRatios)
};
this.syncHuggingFaceFromManager();
this.prefillSettingsDraftDefaultHuggingFaceModel();

if (!String(this.settingsDraft.huggingfaceDtype || "").trim()) {
this.settingsDraft.huggingfaceDtype = DTYPE_OPTIONS[0]?.value || config.DEFAULT_ADMIN_CHAT_SETTINGS.huggingfaceDtype;
if (provider === config.ADMIN_CHAT_LLM_PROVIDER.LOCAL) {
this.prefillSettingsDraftDefaultHuggingFaceModel();

if (!String(this.settingsDraft.huggingfaceDtype || "").trim()) {
this.settingsDraft.huggingfaceDtype = DTYPE_OPTIONS[0]?.value || config.DEFAULT_ADMIN_CHAT_SETTINGS.huggingfaceDtype;
}
} else {
this.settingsDraft.huggingfaceModel = "";
this.settingsDraft.huggingfaceDtype = "";
}

void this.warmSettingsDraftLocalProvider()
.catch((error) => {
this.reportError("warming the local-provider settings draft", error);
});
if (provider === config.ADMIN_CHAT_LLM_PROVIDER.LOCAL) {
void this.warmSettingsDraftLocalProvider()
.catch((error) => {
this.reportError("warming the local-provider settings draft", error);
});
}
openDialog(this.refs.settingsDialog);
},

Expand All @@ -1656,9 +1655,17 @@ const model = {
},

setSettingsProvider(provider) {
const nextProvider = config.normalizeAdminChatLlmProvider(provider);

this.settingsDraft = {
...this.settingsDraft,
provider: config.normalizeAdminChatLlmProvider(provider)
huggingfaceDtype: nextProvider === config.ADMIN_CHAT_LLM_PROVIDER.LOCAL
? this.settingsDraft.huggingfaceDtype
: "",
huggingfaceModel: nextProvider === config.ADMIN_CHAT_LLM_PROVIDER.LOCAL
? this.settingsDraft.huggingfaceModel
: "",
provider: nextProvider
};

if (this.isSettingsDraftUsingLocalProvider) {
Expand Down Expand Up @@ -1877,8 +1884,12 @@ const model = {
this.settings = {
apiEndpoint: (this.settingsDraft.apiEndpoint || "").trim(),
apiKey: (this.settingsDraft.apiKey || "").trim(),
huggingfaceDtype: (this.settingsDraft.huggingfaceDtype || "").trim(),
huggingfaceModel: normalizeHuggingFaceModelInput(this.settingsDraft.huggingfaceModel || ""),
huggingfaceDtype: provider === config.ADMIN_CHAT_LLM_PROVIDER.LOCAL
? (this.settingsDraft.huggingfaceDtype || "").trim()
: "",
huggingfaceModel: provider === config.ADMIN_CHAT_LLM_PROVIDER.LOCAL
? normalizeHuggingFaceModelInput(this.settingsDraft.huggingfaceModel || "")
: "",
localProvider,
maxTokens,
model: (this.settingsDraft.model || "").trim(),
Expand Down
3 changes: 3 additions & 0 deletions app/L0/_all/mod/_core/agent-chat/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Documentation is top priority for this module. After any change under `_core/age
This module owns:

- `assistant-message-evaluation.js`: shared assistant-message normalization, exact-repeat detection, severity-based loop warning construction, and safe prepending of synthetic transcript logs ahead of real execution console output
- `visual-data.js`: shared image visual-data normalization, serialization, token estimation, and transport shaping for first-party agent surfaces; its framework dependency stays relative so pure consumers remain directly importable in browser and Node verification runtimes
- `ext/js/_core/onscreen_agent/store.js/evaluateOnscreenAssistantMessage/end/*.js`: hook implementations for overlay assistant-message evaluation
- `ext/js/_core/admin/views/agent/store.js/evaluateAdminAssistantMessage/end/*.js`: hook implementations for admin assistant-message evaluation

Expand All @@ -24,6 +25,7 @@ Current shared helper contract:

- assistant-message repeat matching should normalize line endings, trim trailing per-line whitespace, and trim outer whitespace before comparing exact assistant-message bodies
- synthetic transcript warnings should be emitted only when the same normalized assistant message has already appeared earlier in the settled assistant history for that same surface
- vision transport shaping must convert user visual data into provider-facing image content parts and must remove internal `visualData` and `tokenCount` metadata from outbound messages
- severity must escalate as `info` on the 2nd exact send, `warn` on the 3rd exact send, and `error` on the 4th exact send onward
- the warning text should stay short, direct, and framed as loop pressure visible through the normal execution transcript channel
- prepending synthetic transcript logs must not rewrite or trim the real execution console entries that already exist on the execution result
Expand All @@ -35,6 +37,7 @@ Current shared helper contract:

- keep framework-generic runtime helpers in `_core/framework/`; keep chat-feature policy here
- keep surface-specific store behavior in the owning chat modules and reuse this module only for logic that is intentionally shared across agent surfaces
- keep shared pure helper imports browser- and Node-resolvable; use relative module specifiers when the helper is covered by direct Node imports
- when repeat-detection thresholds, wording, or transcript insertion semantics change, update this file, the consuming chat docs, and the supplemental agent-runtime docs in the same session

## Verification
Expand Down
8 changes: 6 additions & 2 deletions app/L0/_all/mod/_core/agent-chat/visual-data.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { countTextTokens } from "/mod/_core/framework/js/token-count.js";
import { countTextTokens } from "../framework/js/token-count.js";

const DATA_URL_PATTERN = /^data:([^;,]+)?((?:;[^,]+)*),(.*)$/isu;
const DEFAULT_IMAGE_MEDIA_TYPE = "image/png";
Expand Down Expand Up @@ -677,8 +677,12 @@ export function prepareChatMessagesForVisionTransport(messages = [], options = {
return null;
}

const transportMessage = { ...message };
delete transportMessage.tokenCount;
delete transportMessage.visualData;

return {
...message,
...transportMessage,
content: buildVisionContentParts(message, options)
};
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The settings and prompt-history dialogs reuse the shared `_core/visual/forms/dia
Caught overlay runtime errors are logged through `console.error` and shown through the shared toast stack from `_core/visual/chrome/toast.js`. The composer placeholder still belongs to ready-state and lightweight status guidance, so raw exception text should not be pushed into the textarea placeholder.
Overlay execution transcripts now use the shared YAML-first formatter for both console logs and returned values, emitting block headers such as `log↓`, `warn↓`, `error↓`, and `result↓` so structured telemetry stays complete across the thread and execution cards. Queued follow-up submissions wait behind any just-finished assistant reply that contains `_____javascript`; the runtime must execute the block and append the `execution-output` turn before sending the queued draft, so the next model request sees the execution result in history. Immediately before those execution results are serialized back into the `execution-output` follow-up turn, the overlay also runs the shared assistant-message evaluation seam; the current first-party hook from `_core/agent-chat` prepends synthetic loop warnings when the exact same assistant message reappears, using `info` on the 2nd send, `warn` on the 3rd send, and `error` on the 4th send onward.

The settings dialog now has two provider tabs named `API` and `Local`. `API` keeps the OpenAI-compatible endpoint, model, and key fields. `Local` mounts the shared Hugging Face config sidebar in onscreen mode, so the overlay reads the same saved-model list and live WebGPU worker state as the routed Local LLM page and the admin chat. Opening the Local tab should refresh saved-model shortcuts without booting the worker; saving local settings persists the selected repo id and dtype, then starts background model preparation. When no local model is selected and saved models exist, the Local panel preselects the browser-wide last successfully loaded saved model from `_core/huggingface/manager.js`, falling back to the first saved entry if that last-used entry was discarded. When no local model is selected, no local model is loaded, and the shared saved-model list is empty, the Local panel prefills the Hugging Face model field with the same testing-page default: `onnx-community/gemma-4-E4B-it-ONNX`.
The settings dialog now has two provider tabs named `API` and `Local`. `API` keeps the OpenAI-compatible endpoint, model, and key fields. `Local` mounts the shared Hugging Face config sidebar in onscreen mode, so the overlay reads the same saved-model list and live WebGPU worker state as the routed Local LLM page and the admin chat. Opening the Local tab should refresh saved-model shortcuts without booting the worker; saving local settings persists the selected repo id and dtype, then starts background model preparation. When no local model is selected and saved models exist, the Local panel preselects the browser-wide last successfully loaded saved model from `_core/huggingface/manager.js`, falling back to the first saved entry if that last-used entry was discarded. When no local model is selected, no local model is loaded, and the shared saved-model list is empty, the Local panel prefills the Hugging Face model field with the same testing-page default: `onnx-community/Qwen3-0.6B-ONNX`.

The API-key composer blocker applies only to the default API-provider configuration with no API key, where the composer shows a centered `Set LLM API key` action over the disabled textarea. Local Hugging Face mode can send without an API key and falls back to loading the selected local model on the first message if background preparation has not finished.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ The admin settings modal now starts with a provider switch:

Below those provider-specific sections, the shared settings area also exposes `max_tokens`, prompt-budget ratios for `system`, `history`, and `transient`, plus the separate single-history-message ratio used by the shared trimming path. Those values are persisted in `prompt_budget_ratios` and feed the same prompt-budget builder used by the onscreen agent: prepared entries and prompt items reuse cached token counts, single live history messages are capped first, contributor-level trims must each be at least `250` tokens, and `system` or `transient` falls back to one combined section-body trim when smaller contributor cuts would otherwise be required.

When no local model is selected and saved models exist, the admin local panel preselects the browser-wide last successfully loaded saved model from `_core/huggingface/manager.js`, falling back to the first saved entry if that last-used entry was discarded. When no local model is selected, no local model is loaded, and the shared saved-model list is empty, the admin local panel prefills the Hugging Face model field with the same testing-page default: `onnx-community/gemma-4-E4B-it-ONNX`.
When no local model is selected and saved models exist, the admin local panel preselects the browser-wide last successfully loaded saved model from `_core/huggingface/manager.js`, falling back to the first saved entry if that last-used entry was discarded. When no local model is selected, no local model is loaded, and the shared saved-model list is empty, the admin local panel prefills the Hugging Face model field with the same testing-page default: `onnx-community/Qwen3-0.6B-ONNX`.

The stored config keeps both API settings and the selected local provider state:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The page owns:
- a simple testing chat with system prompt, user messages, streamed assistant replies, stop, and clear-chat
- compact response metrics inline under each assistant reply

When admin or onscreen chat local settings have no selected model and the browser has saved Hugging Face models, the shared sidebar preselects the browser-wide last successfully loaded saved model from local storage. If that entry was discarded, it falls back to the first saved model. When the browser has no saved local Hugging Face models and no persisted auto-reload target, the routed testing-page model input prefills `onnx-community/gemma-4-E4B-it-ONNX` as the empty-state suggestion; admin and onscreen chat local settings reuse that same default only when there is no preferred saved-model selection. The default generation cap is `16384` max new tokens unless the user changes it.
When admin or onscreen chat local settings have no selected model and the browser has saved Hugging Face models, the shared sidebar preselects the browser-wide last successfully loaded saved model from local storage. If that entry was discarded, it falls back to the first saved model. When the browser has no saved local Hugging Face models and no persisted auto-reload target, the routed testing-page model input prefills `onnx-community/Qwen3-0.6B-ONNX` as the empty-state suggestion; admin and onscreen chat local settings reuse that same default only when there is no preferred saved-model selection. The default generation cap is `16384` max new tokens unless the user changes it.

This is not a general agent surface. It does not expose tool execution, queueing, attachments, persisted conversations, or backend orchestration.

Expand Down
2 changes: 2 additions & 0 deletions app/L0/_all/mod/_core/framework/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ This module owns:
- Alpine directives and magic helpers registered during bootstrap, including delayed-target `x-inject`
- shared browser API helpers in `js/api-client.js`, `js/api.js`, `js/fetch-proxy.js`, `js/download.js`, and `js/proxy-url.js`
- small shared parsing and utility helpers such as markdown frontmatter, the browser YAML wrapper, and token counting
- `js/token-count.js`: shared token counting with relative vendor imports so direct Node tests and browser module loading execute the same implementation
- shared framework CSS and icon font assets under `css/`, including non-visual helper-tag defaults such as hidden `x-context` elements

## Local Contracts
Expand Down Expand Up @@ -141,6 +142,7 @@ Rules:
### Local Work Rules

- keep this module focused on platform concerns, not feature logic
- keep pure framework utilities that are directly imported by Node tests on relative internal imports; browser-absolute `/mod/...` specifiers remain appropriate for browser-only runtime entry points
- add shared runtime helpers here only when multiple modules genuinely need them
- prefer explicit small runtime namespaces over loose globals
- if a contract is used by only one module, keep it in that module instead of promoting it here too early
Expand Down
4 changes: 2 additions & 2 deletions app/L0/_all/mod/_core/framework/js/token-count.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Tiktoken } from "/mod/_core/framework/js/vendor/js-tiktoken-lite.js";
import o200kBase from "/mod/_core/framework/js/vendor/js-tiktoken-o200k_base.js";
import { Tiktoken } from "./vendor/js-tiktoken-lite.js";
import o200kBase from "./vendor/js-tiktoken-o200k_base.js";

let tokenizer = null;

Expand Down
Loading