Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
e362786
docs: design spec for the logged-in shell rebuild
vishr Sep 5, 2026
a578aca
docs: implementation plan for the logged-in shell rebuild
vishr Sep 5, 2026
c7addaf
fix(ui): let embedded views load their inlined fonts
vishr Sep 5, 2026
a17ea6a
refactor(ui): share format, contracts and chart helpers between host …
vishr Sep 5, 2026
3008fe7
refactor(ui): drop an unused import from the logs view
vishr Sep 5, 2026
3a87958
feat(ui): expose the signed-in account to the app
vishr Sep 5, 2026
10d3749
fix(ui): keep the session when the post-login account reload fails
vishr Sep 5, 2026
4147ef3
feat(ui): add the navigation rail and a shared API helper
vishr Sep 5, 2026
6e714f5
feat(ui): replace the header toggle and history drawer with a persist…
vishr Sep 5, 2026
f7fef06
fix(ui): forget a draft thread when its first run fails or stops
vishr Sep 5, 2026
32ab6d5
feat(ui): chat pane with sticky composer, activity line and block chrome
vishr Sep 5, 2026
60a5c85
fix(ui): report a failed clipboard copy instead of rejecting
vishr Sep 5, 2026
22acc0f
feat(ui): slimmer embedded views that size to their content
vishr Sep 5, 2026
4982c09
feat(ui): per-type widget sizes and free-slot placement
vishr Sep 5, 2026
694377d
docs: add the prompt fix and the UX walk to the shell rebuild plan
vishr Sep 5, 2026
0b5006e
feat(ui): echarts in the host and a shared widget data layer
vishr Sep 5, 2026
b0f2e1d
fix(ui): keep one chart instance per mount and apply options in place
vishr Sep 5, 2026
04db008
docs: add the Geist typeface task to the shell rebuild plan
vishr Sep 5, 2026
cecedce
feat(ui): set the app in Geist, with mono reserved for data
vishr Sep 5, 2026
01a2366
chore: refresh the notices for the Geist font packages
vishr Sep 5, 2026
dba32ae
feat(ui): native dashboard widgets with charts, hover actions and con…
vishr Sep 5, 2026
432c4ab
feat(ui): dashboard page with native widgets and a quieter header
vishr Sep 5, 2026
c259fb4
feat(ui): six-digit code entry with resend and change email
vishr Sep 5, 2026
0c655f4
fix(ui): stop the resend countdown once it is over or the sign-in suc…
vishr Sep 6, 2026
2223eae
docs: align the shell spec with the configure modal
vishr Sep 6, 2026
dbcfe25
fix(agent): stop the model drawing text diagrams beside an attached view
vishr Sep 6, 2026
08d4562
fix(ui): chat code blocks, two-line rail rows, drawer focus
vishr Sep 6, 2026
6c44e54
fix(ui): level widget tiles, stable service map, badge cells, placeme…
vishr Sep 6, 2026
a7c17cf
fix(ui): readable dimmed text in light mode
vishr Sep 6, 2026
7ad6d8c
fix(ui): unclipped tab counts in embedded views
vishr Sep 6, 2026
ea61d8a
feat(ui): verify button and clearer code-step copy
vishr Sep 6, 2026
c1b5f65
fix(dashboard): default layout sizes match the client and the prompt …
vishr Sep 6, 2026
e36e6e0
fix(ui): badge labels survive narrow cells, stable ring order, mobile…
vishr Sep 6, 2026
ad974d1
chore(ui): rebuild embedded assets for the shell rebuild
vishr Sep 6, 2026
09f965b
fix(ui): retry reloads a thread that failed to restore, session stops…
vishr Sep 6, 2026
75efda8
fix(ui): unknown widget types degrade to a message, trace and sparkli…
vishr Sep 6, 2026
82ca825
fix(ui): embedded views keep one chart instance and ship a named font…
vishr Sep 6, 2026
503f5ff
docs: record the message-timestamp scope and the moved contracts path
vishr Sep 6, 2026
971d21f
chore(ui): rebuild embedded assets after the final fix wave
vishr Sep 6, 2026
500a86a
Merge remote-tracking branch 'origin/main' into ui/shell-rebuild
vishr Sep 6, 2026
0d81142
fix(ui): copy buttons share one guarded clipboard helper
vishr Sep 6, 2026
e85c567
fix(ui): the rail groups chats in a fixed order
vishr Sep 6, 2026
a74f1c2
chore(ui): rebuild embedded assets after the copy and rail fixes
vishr Sep 6, 2026
328731a
chore(ui): spell out noopener on the external links
vishr Sep 6, 2026
11b7aae
chore(ui): rebuild embedded assets after the link attribute change
vishr Sep 6, 2026
7a06c69
fix(ui): the burger and the avatar describe their real state
vishr Sep 6, 2026
d0ef3de
refactor(ui): widget records carry the server's type without casts
vishr Sep 6, 2026
c00e630
chore(ui): rebuild embedded assets after the widget type and label fixes
vishr Sep 6, 2026
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
12 changes: 6 additions & 6 deletions THIRD_PARTY_NOTICES
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ COMPONENT INVENTORY
- npm: @floating-ui/react 0.27.20 (declared license: MIT)
- npm: @floating-ui/react-dom 2.1.9 (declared license: MIT)
- npm: @floating-ui/utils 0.2.12 (declared license: MIT)
- npm: @fontsource/ibm-plex-mono 5.3.0 (declared license: OFL-1.1)
- npm: @fontsource/ibm-plex-sans 5.3.0 (declared license: OFL-1.1)
- npm: @fontsource-variable/geist 5.3.0 (declared license: OFL-1.1)
- npm: @fontsource-variable/geist-mono 5.3.0 (declared license: OFL-1.1)
- npm: @hono/node-server 1.19.15 (declared license: MIT)
- npm: @mantine/core 9.5.2 (declared license: MIT)
- npm: @mantine/hooks 9.5.2 (declared license: MIT)
Expand Down Expand Up @@ -4295,10 +4295,10 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

--- Applies to -------------------------------------------------------------
- npm: @fontsource/ibm-plex-mono 5.3.0 / LICENSE
- npm: @fontsource-variable/geist 5.3.0 / LICENSE
----------------------------------------------------------------------------

Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-ThinItalic.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-ExtraLight.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-ExtraLightItalic.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-Light.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-LightItalic.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-Regular.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-Italic.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-Medium.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-MediumItalic.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-SemiBold.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-SemiBoldItalic.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-Bold.ttf: Copyright 2017 IBM Corp. All rights reserved. IBMPlexMono-BoldItalic.ttf: Copyright 2017 IBM Corp. All rights reserved.
Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font) Geist-Italic[wght].ttf: Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font)

This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
Expand Down Expand Up @@ -4393,10 +4393,10 @@ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

--- Applies to -------------------------------------------------------------
- npm: @fontsource/ibm-plex-sans 5.3.0 / LICENSE
- npm: @fontsource-variable/geist-mono 5.3.0 / LICENSE
----------------------------------------------------------------------------

Copyright 2019 IBM Corp. All rights reserved. IBMPlexSans-Italic[wdth,wght].ttf: Copyright 2019 IBM Corp. All rights reserved.
Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git) GeistMono-Italic[wght].ttf: Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git)

This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
Expand Down
3,669 changes: 3,669 additions & 0 deletions docs/superpowers/plans/2026-09-05-logged-in-ui-shell.md

Large diffs are not rendered by default.

154 changes: 154 additions & 0 deletions docs/superpowers/specs/2026-09-05-logged-in-ui-shell-design.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion internal/agent/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
appid "github.com/labstack/fanout/internal/id"
)

const systemPrompt = `You are Fanout's observability assistant. Use observability_overview first for broad health questions, intelligence_snapshot for the latest precomputed anomalies and recurring log patterns, service_topology for dependencies, service_performance for activity/latency/endpoints/comparisons, trace_detail for trace or root-cause inspection, and search_logs for log questions. Treat structured outputs as authoritative. You can also list, inspect, create, and update the user's named dashboards. When asked to create a dashboard, compose a useful complete layout using overview, topology, activity, performance, trace, logs, and assistant widgets; use unique stable widget IDs, valid non-overlapping 12-column positions, and the requested time window. Creating is additive. Only update an existing dashboard after the user explicitly asks to change or replace it; inspect it first and preserve unrelated views. State the time window you used, distinguish missing data from healthy behavior, and never invent services, metrics, or causal claims. Keep answers concise because attached views provide interactive details. Never expose implementation details to the user: do not mention protocol names, tool names, schemas, query IDs, data-source names, storage engines, providers, or internal execution steps. Refer to attached interactive content simply as a view.`
const systemPrompt = `You are Fanout's observability assistant. When a view is attached to your reply it is the picture: never draw diagrams, trees, or charts in text, never use code fences to draw boxes, arrows, or trees, and never add a table or list that restates what an attached view already shows; your prose adds only what the view omits. Use observability_overview first for broad health questions, intelligence_snapshot for the latest precomputed anomalies and recurring log patterns, service_topology for dependencies, service_performance for activity/latency/endpoints/comparisons, trace_detail for trace or root-cause inspection, and search_logs for log questions. Treat structured outputs as authoritative. You can also list, inspect, create, and update the user's named dashboards. When asked to create a dashboard, compose a useful complete layout using overview, topology, activity, performance, trace, logs, and assistant widgets; use unique stable widget IDs, valid non-overlapping 12-column positions, and the requested time window. Creating is additive. Only update an existing dashboard after the user explicitly asks to change or replace it; inspect it first and preserve unrelated views. State the time window you used, distinguish missing data from healthy behavior, and never invent services, metrics, or causal claims. Keep answers concise because attached views provide interactive details. Never expose implementation details to the user: do not mention protocol names, tool names, schemas, query IDs, data-source names, storage engines, providers, or internal execution steps. Refer to attached interactive content simply as a view.`

// Error categories used to pick a client-safe RUN_ERROR message; the raw
// error (which can include provider response bodies) stays server-side.
Expand Down
11 changes: 11 additions & 0 deletions internal/agent/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,14 @@ func TestRuntimeSurfacesTokenLimitTruncation(t *testing.T) {
t.Fatalf("assistant message missing truncation notice: %#v", messages)
}
}

func TestSystemPromptForbidsTextDiagrams(t *testing.T) {
for _, want := range []string{
"never draw diagrams, trees, or charts in text",
"never add a table or list that restates what an attached view already shows",
} {
if !strings.Contains(systemPrompt, want) {
t.Fatalf("system prompt is missing %q", want)
}
}
}
12 changes: 8 additions & 4 deletions internal/dashboard/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,15 @@ func DefaultState() State {
{ID: "activity", Type: "activity", Title: "Recent activity", Enabled: true},
{ID: "assistant", Type: "assistant", Title: "Ask Fanout", Enabled: true},
},
// Sizes mirror widgetDefaults in ui/host/src/dashboard-layout.ts: a card
// gets the shape its content fills. The old default gave Ask Fanout the
// full twelve columns for three chips and left the health card with a
// blank band under it.
Layout: []Layout{
{I: "health", X: 0, Y: 0, W: 4, H: 3, MinW: 3, MinH: 2},
{I: "topology", X: 4, Y: 0, W: 8, H: 6, MinW: 4, MinH: 4},
{I: "activity", X: 0, Y: 3, W: 4, H: 3, MinW: 3, MinH: 2},
{I: "assistant", X: 0, Y: 6, W: 12, H: 3, MinW: 4, MinH: 2},
{I: "health", X: 0, Y: 0, W: 4, H: 3, MinW: 3, MinH: 3},
{I: "topology", X: 4, Y: 0, W: 8, H: 5, MinW: 4, MinH: 4},
{I: "activity", X: 0, Y: 3, W: 4, H: 5, MinW: 3, MinH: 4},
{I: "assistant", X: 4, Y: 5, W: 4, H: 3, MinW: 3, MinH: 3},
},
Filters: Filters{Window: "1h"},
}
Expand Down
33 changes: 33 additions & 0 deletions internal/dashboard/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dashboard
import (
"context"
"errors"
"reflect"
"testing"

appid "github.com/labstack/fanout/internal/id"
Expand Down Expand Up @@ -150,6 +151,38 @@ func TestServiceMigratesLegacyCanvasOnFirstRead(t *testing.T) {
assertDashboardUUIDv7s(t, item)
}

func TestDefaultStateMatchesTheClientWidgetSizes(t *testing.T) {
state := DefaultState()
want := []Layout{
{I: "health", X: 0, Y: 0, W: 4, H: 3, MinW: 3, MinH: 3},
{I: "topology", X: 4, Y: 0, W: 8, H: 5, MinW: 4, MinH: 4},
{I: "activity", X: 0, Y: 3, W: 4, H: 5, MinW: 3, MinH: 4},
{I: "assistant", X: 4, Y: 5, W: 4, H: 3, MinW: 3, MinH: 3},
}
if !reflect.DeepEqual(state.Layout, want) {
t.Fatalf("default layout = %#v, want %#v", state.Layout, want)
}
overlaps := func(a, b Layout) bool {
return a.X < b.X+b.W && b.X < a.X+a.W && a.Y < b.Y+b.H && b.Y < a.Y+a.H
}
for i := range state.Layout {
for j := i + 1; j < len(state.Layout); j++ {
if overlaps(state.Layout[i], state.Layout[j]) {
t.Errorf("%q overlaps %q", state.Layout[i].I, state.Layout[j].I)
}
}
}
// Validate wants UUIDv7 widget ids, which the default state is given when
// it is created for an owner; everything else it checks holds as written.
normalized, err := normalizeStateIDs(state)
if err != nil {
t.Fatal(err)
}
if err := Validate("System overview", "", normalized); err != nil {
t.Fatalf("default state does not validate: %v", err)
}
}

func TestValidateRejectsInvalidStates(t *testing.T) {
newID := func() string {
t.Helper()
Expand Down
34 changes: 17 additions & 17 deletions internal/mcp/apps/logs.html

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions internal/mcp/apps/overview.html

Large diffs are not rendered by default.

68 changes: 34 additions & 34 deletions internal/mcp/apps/performance.html

Large diffs are not rendered by default.

68 changes: 34 additions & 34 deletions internal/mcp/apps/topology.html

Large diffs are not rendered by default.

36 changes: 18 additions & 18 deletions internal/mcp/apps/trace.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion internal/observability/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ type HeatmapPoint struct {
P95MS float64 `json:"p95_ms"`
}

// Direction mirrors the closed union in ui/apps/src/contracts.ts
// Direction mirrors the closed union in ui/contracts.ts
// ("improvement" | "regression" | "stable"); keep the two in sync.
type Direction string

Expand Down
1 change: 0 additions & 1 deletion internal/ui/dist/assets/auth-DhIxmh_D.js

This file was deleted.

1 change: 1 addition & 0 deletions internal/ui/dist/assets/brand-CCB4_HD8.js

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions internal/ui/dist/assets/chat-BWEtId3_.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion internal/ui/dist/assets/chat._threadId-CzfhQ5YC.js

This file was deleted.

1 change: 1 addition & 0 deletions internal/ui/dist/assets/chat._threadId-DC_eOz23.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import{t as e}from"./chat-BWEtId3_.js";var t=e;export{t as component};
1 change: 0 additions & 1 deletion internal/ui/dist/assets/chat.index-BCfx7LKm.js

This file was deleted.

1 change: 1 addition & 0 deletions internal/ui/dist/assets/chat.index-DC_eOz23.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import{t as e}from"./chat-BWEtId3_.js";var t=e;export{t as component};
1 change: 1 addition & 0 deletions internal/ui/dist/assets/copy-BcWHRdqc.js

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

24 changes: 24 additions & 0 deletions internal/ui/dist/assets/dashboard-DFF2_SFC.js

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions internal/ui/dist/assets/dashboard-yVYEftTd.js

This file was deleted.

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

This file was deleted.

1 change: 1 addition & 0 deletions internal/ui/dist/assets/dashboards.index-DY3GETbb.js

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

1 change: 0 additions & 1 deletion internal/ui/dist/assets/dashboards.index-DzfpVEyI.js

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Loading