Skip to content
Merged
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
6 changes: 3 additions & 3 deletions apps/web/e2e/data/admin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ export function buildAdmin(now, base, resources) {
vaults: resources.vaults.filter(of("vault", projectId)),
});

const keyRef = (project, k) => ({ id: k.id, name: k.name, prefix: k.prefix, kind: "issued", revoked_at: k.revoked_at ? iso(k.revoked_at) : null });
const keyRef = (k) => ({ id: k.id, name: k.name, prefix: k.prefix, kind: "issued", revoked_at: k.revoked_at ? iso(k.revoked_at) : null });
// Deterministic creator per resource: rotate through the project's keys; one in seven is unknown.
const creators = new Map();
let turn = 0;
const creatorFor = (project, type, id) => {
const cacheKey = `${type}:${id}`;
if (!creators.has(cacheKey)) {
turn += 1;
creators.set(cacheKey, turn % 7 === 0 ? null : keyRef(project, project.keys[turn % project.keys.length]));
creators.set(cacheKey, turn % 7 === 0 ? null : keyRef(project.keys[turn % project.keys.length]));
}
return creators.get(cacheKey);
};
Expand All @@ -61,7 +61,7 @@ export function buildAdmin(now, base, resources) {
const own = collections(project.id);
const list = [];
const push = (at, action, type, id, parent = "", creatorType = type) => {
const creator = action === "create" ? creatorFor(project, creatorType, id) : keyRef(project, project.keys[list.length % project.keys.length]);
const creator = action === "create" ? creatorFor(project, creatorType, id) : keyRef(project.keys[list.length % project.keys.length]);
list.push({ id: `op_${project.id.slice(5)}_${list.length}`, created_at: iso(at), api_key: creator, action, resource_type: type, resource_id: id, parent_id: parent, request_id: `req_${list.length}`, trace_id: `${list.length}`.padStart(32, "0") });
};
for (const agent of own.agents) { push(agent.created_at, "create", "agent", agent.id); if (agent.updated_at > agent.created_at) push(agent.updated_at, "update", "agent", agent.id); }
Expand Down
1 change: 0 additions & 1 deletion apps/web/e2e/data/routes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ function daemonUrl(publicUrl) {

export function buildDemo(now = Math.floor(Date.now() / 1000), publicUrl = "https://core.example.com") {
seed = 42;
const models = ["gpt-5.1-codex", "claude-sonnet-5", "MiniMax-M2", "gpt-5.1-mini"];
const agents = agentDefinitions.map((definition, index) => ({
id: `agent_${index + 1}${uuid().slice(0, 6)}`, object: "agent", model: definition.model, name: definition.name, instructions: definition.instructions,
metadata: definition.metadata, multi_agent: { enabled: false, max_concurrent_subagents: null }, reasoning: definition.reasoning, service_tier: "auto",
Expand Down
4 changes: 2 additions & 2 deletions apps/web/e2e/fixture-console.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ const tokenLimit = (value) => value === undefined || (Number.isInteger(value) &&
const jsonKind = (value) => Array.isArray(value) ? "an array" : typeof value === "string" ? "a string" : typeof value === "boolean" ? "a boolean" : Number.isInteger(value) ? "an integer" : "a number";

/** The first rule a provider body breaks, in Core's order and words; null when valid. */
function providerProblem(harness, input) {
function providerProblem(input) {
if (Object.keys(input).some((key) => !PROVIDER_FIELDS.has(key)) || ["protocol", "base_url", "api_key"].some((key) => typeof input[key] !== "string") ||
!tokenLimit(input.context_window) || !tokenLimit(input.max_output_tokens)) return PROVIDER_SHAPE;
if (!httpsBase(input.base_url)) return "model provider requires an HTTPS base_url without credentials, query or fragment";
Expand Down Expand Up @@ -581,7 +581,7 @@ async function harnessRoute(request, response, path) {
if (typeof input.model !== "string" || !input.model.trim()) return error(response, 400, "A model ID is required.", "model_configuration_model_invalid");
if (input.harness_config !== undefined && (!input.harness_config || typeof input.harness_config !== "object" || Array.isArray(input.harness_config))) return error(response, 400, "Harness configuration must be an object.", "harness_config_invalid");
if (!support(harness).protocols.includes(input.model_provider?.protocol)) return error(response, 400, "This harness does not support this protocol.", "model_provider_protocol_unsupported");
const problem = providerProblem(harness, input.model_provider ?? {});
const problem = providerProblem(input.model_provider ?? {});
if (problem) return error(response, 400, problem, "invalid_request_error");
entry.provider = {
object: "core.model_configuration", harness, model: input.model, harness_config: input.harness_config ?? {},
Expand Down
1 change: 0 additions & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"@number-flow/react": "^0.6.2",
"@oac/agents-client": "workspace:*",
"@tanstack/react-query": "^5.103.2",
"@tanstack/react-table": "^8.21.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"i18next": "^26.4.2",
Expand Down
22 changes: 0 additions & 22 deletions apps/web/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/web/src/ConsoleApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { SessionPage } from "./features/sessions/SessionPage";
import { SkillsPage } from "./features/skills/SkillsPage";
import { SettingsPage } from "./features/settings/SettingsPage";
import { VaultsPage } from "./features/vaults/VaultsPage";
import { consoleDepth, ConsoleNavigationContext, useConsoleNavigation, hashWithParams, routeParamsFromHash, type ConsoleIntent, type RouteParams } from "./lib/console-navigation";
import { consoleDepth, ConsoleNavigationContext, hashWithParams, routeParamsFromHash, type ConsoleIntent, type RouteParams } from "./lib/console-navigation";
import { consoleHashForView, consoleNavParent, consoleViewFromHash, type ConsoleView } from "./lib/console-routes";
import { ProjectsProvider, useProjects } from "./lib/projects";
import { collectionQuery, collections, filesCollection, queryClient, type CollectionSpec } from "./lib/queries";
Expand Down
243 changes: 0 additions & 243 deletions apps/web/src/app/beautifui/foundation.css
Original file line number Diff line number Diff line change
Expand Up @@ -211,30 +211,6 @@ a {
text-decoration-skip-ink: auto;
}

/* theme switches swap every token at once — freeze transitions so the flip
* is one clean repaint instead of hundreds of mismatched color fades */
.theme-switching *,
.theme-switching *::before,
.theme-switching *::after {
transition: none !important;
}

/* touch: :hover sticks after a tap, so neutralize row/header hovers there */
@media (hover: none) {
.records-row:hover > .records-cell {
background: transparent;
}

.records-row:hover > td.is-colsel {
background: color-mix(in srgb, var(--accent) 4%, var(--surface));
}

.records-header-button:hover {
background: transparent;
color: var(--ink-2);
}
}

/* Tailwind v4 resets buttons to cursor:default — anything
* clickable must invite the click */
button:not(:disabled),
Expand All @@ -258,73 +234,6 @@ select:focus-visible,
outline: none;
}

.animated-underline {
position: relative;
display: inline-block;
}

.animated-underline::after {
position: absolute;
right: 0;
bottom: -1px;
left: 0;
height: 1px;
content: "";
background: currentColor;
transform: scaleX(0);
transform-origin: left center;
transition: transform 280ms var(--ease-link);
}

a:hover .animated-underline::after,
a:focus-visible .animated-underline::after {
transform: scaleX(1);
}

/* ══════════════════════════════════════════════════════════
* COMPONENT-SPECIFIC — StreamingText / ContextCards
* Favicon source avatars.
* Copy this block only alongside StreamingText / ContextCards; it is not part of the
* generic foundation above.
* ══════════════════════════════════════════════════════════ */
.source-avatar {
box-shadow: 0 0 0 1px oklch(0.21 0.034 263.436 / 0.1);
}

.dark .source-avatar {
box-shadow: 0 0 0 1px oklch(1 0 0 / 0.08);
}

/* ── primitive spacing system ─────────────────────────────
* Shared optical offsets for small demo cards. Use these
* instead of hand-tuning 10/12/14px per component.
*/

.primitive-card-pad {
padding: 12px;
}

.primitive-card-bar {
padding: 10px 12px;
}

.primitive-card-footer {
padding: 10px;
}

.primitive-table-cell {
padding: 10px 12px;
}

.primitive-icon-button {
display: inline-flex;
width: 28px;
height: 28px;
align-items: center;
justify-content: center;
border-radius: var(--radius-control);
}

/* ── shared keyframes ─────────────────────────────────── */

@keyframes shimmer-text {
Expand All @@ -347,114 +256,6 @@ a:focus-visible .animated-underline::after {
}
}

.home-reveal {
will-change: opacity, transform, filter;
}


/* ── filter table electric status colors ─────────────────── */

/* ══════════════════════════════════════════════════════════
* COMPONENT-SPECIFIC — FilterTable
* Electric status-pill colors.
* Copy this block only alongside FilterTable; it is not part of the
* generic foundation above.
* ══════════════════════════════════════════════════════════ */
.filter-status-todo,
.filter-status-progress,
.filter-status-done {
border: 1px solid transparent;
}

/* ══════════════════════════════════════════════════════════
* COMPONENT-SPECIFIC — InsightCards
* Liveline chart tooltip + cursor.
* Copy this block only alongside InsightCards; it is not part of the
* generic foundation above.
* ══════════════════════════════════════════════════════════ */
.insight-chart-stage {
overflow: hidden;
}

.insight-chart-cursor {
position: absolute;
z-index: 4;
top: 0;
bottom: 0;
width: 1px;
background: var(--ink);
opacity: 0.26;
pointer-events: none;
}

.insight-chart-tooltip-anchor {
position: absolute;
z-index: 5;
top: 8px;
transform: translateX(-50%);
pointer-events: none;
}

.insight-chart-tooltip {
display: flex;
align-items: center;
gap: 12px;
padding: 5px 9px;
border: 1px solid var(--line-strong);
border-radius: 8px;
color: var(--tooltip-fg);
background: var(--tooltip-bg);
box-shadow: var(--shadow-overlay);
font-size: 11.5px;
font-variant-numeric: tabular-nums;
white-space: nowrap;
}

.insight-chart-tooltip-item {
display: inline-flex;
align-items: center;
gap: 6px;
}

.insight-chart-tooltip-dot {
width: 8px;
height: 8px;
flex: 0 0 8px;
border-radius: 50%;
}

/* Status pills share the same base-hue → color-mix derivation as .records-tag,
* so both components stay consistent across light and dark. */
.filter-status-todo {
--tag-base: oklch(0.757 0.153 66.401);
}
.filter-status-progress {
--tag-base: oklch(0.671 0.118 219.351);
}
.filter-status-done {
--tag-base: oklch(0.652 0.131 162.865);
}

.filter-status-todo,
.filter-status-progress,
.filter-status-done {
color: color-mix(in srgb, var(--tag-base) 92%, var(--ink));
background: color-mix(in srgb, var(--tag-base) 20%, var(--surface));
border-color: color-mix(in srgb, var(--tag-base) 34%, var(--surface));
}

/* Dark mode — a richer, saturated same-hue fill
* with bright same-hue text and no visible border (light mode keeps the soft
* tinted pastels above). Applies to both the records grid and status pills. */
.dark .records-tag,
.dark .filter-status-todo,
.dark .filter-status-progress,
.dark .filter-status-done {
color: color-mix(in srgb, var(--tag-base) 86%, white);
background: color-mix(in srgb, var(--tag-base) 34%, var(--surface));
border-color: color-mix(in srgb, var(--tag-base) 34%, var(--surface));
}

@keyframes fade-in {
from {
opacity: 0;
Expand All @@ -474,39 +275,6 @@ a:focus-visible .animated-underline::after {
}
}

/* ── StreamText primitive ─────────────────────────────────
* Fast character reveal: the newest few characters carry a
* soft, masked blur so the leading edge resolves smoothly as
* text flows in. The caret holds solid while streaming, then
* blinks once the string settles. */
/* ══════════════════════════════════════════════════════════
* COMPONENT-SPECIFIC — StreamText
* The streaming caret + tail.
* Copy this block only alongside StreamText; it is not part of the
* generic foundation above.
* ══════════════════════════════════════════════════════════ */
.stream-tail {
filter: blur(1.6px);
-webkit-mask-image: linear-gradient(to right, oklch(0 0 0) 20%, oklch(0 0 0 / 0.2));
mask-image: linear-gradient(to right, oklch(0 0 0) 20%, oklch(0 0 0 / 0.2));
}

.stream-caret {
display: inline-block;
width: 2px;
height: 1.05em;
margin-left: 1.5px;
translate: 0 -0.5px;
border-radius: 1px;
background: var(--ink);
vertical-align: text-bottom;
animation: caret-blink 1s step-end infinite;
}

.stream-caret.is-streaming {
animation: none;
}

@keyframes caret-blink {
0%,
100% {
Expand All @@ -517,17 +285,6 @@ a:focus-visible .animated-underline::after {
}
}

@media (prefers-reduced-motion: reduce) {
.stream-caret {
animation: none;
}
.stream-tail {
filter: none;
-webkit-mask-image: none;
mask-image: none;
}
}

@keyframes pop-in {
from {
opacity: 0;
Expand Down
Loading
Loading