pr/8dd0619a7 featcoc read only native copilot cli ses#327
Merged
plusplusoneplusplus merged 37 commits intoJun 14, 2026
Merged
Conversation
plusplusoneplusplus
commented
Jun 14, 2026
Owner
- feat(coc): read-only native Copilot CLI sessions dashboard view
- Improve Copilot Sessions panel UI
- Make Copilot Sessions panel more compact
- Dedup native Copilot sessions against CoC process store
- Deep-link Copilot Sessions and hide background-job sessions
- feat(coc): add compact LLM tool parameter summarization util + contract types
- feat(coc): wire compact LLM tool param metadata into workspace config API
- feat(coc): compact expandable param summaries in LLM Tools settings
- feat(coc): parse native Copilot session-state events.jsonl into rich turns
- feat(coc): reconstruct native Copilot session detail conversation (AC-02)
- feat(coc): render native Copilot session detail as a rich chat transcript (AC-03)
- feat(coc): add Dreams tab to Knowledge nav group (AC-01)
- feat(coc): relocate Dreams provider activity into the Dreams tab (AC-05)
- feat(coc): move dreams.enabled toggle into the Dreams tab (AC-03)
- Add Dreams idle interval admin setting
- Add Dreams run defaults to admin tab
- Fix Dreams admin defaults dirty tracking
- test(coc): cover LLM tools param affordance keyboard a11y + narrow-screen layout
- docs(coc-knowledge): refresh Copilot Sessions tab for rich-transcript reconstruction
- test(coc): render real ConversationTurnBubble for native reconstructed turns
- test(coc): cover panel→mapper→real-bubble native transcript render path
- fix(coc): make embedded Dreams admin panel scrollable
- Hide summary-only Copilot title sessions
- Add native CLI session parsers
- Add native CLI session providers
- Wire native CLI session routes
- Add CLI sessions dashboard tab
- Harden Codex native session image parsing
- Deduplicate native CLI session list rows
- Consolidate native CLI sessions flag
- Tighten Claude native session workspace scoping
- Default CLI sessions to Copilot
- Test native CLI session HTML escaping
- Move CLI Sessions sub-tab between Activity and Git
- Capture Codex sub-agent tool calls
- Capture Claude sub-agent tool calls
Add a disabled-by-default features.nativeCopilotSessions flag that exposes a
workspace-scoped, read-only "Copilot Sessions" repo tab over the server
user's native GitHub Copilot CLI session store (~/.copilot/session-store.db).
Server:
- New native-copilot-sessions query service: short-lived read-only SQLite
connections, workspace scoping by native cwd (normalized prefix) or
repository (origin-remote owner/repo, case-insensitive), parameterized
metadata filters, literal-quoted FTS text search with snippets, newest
updated_at sorting, pagination, turn counts, and typed
db-missing/db-invalid unavailable states that never crash the dashboard.
- GET /api/workspaces/:id/native-copilot-sessions (+ /:sessionId detail with
ordered turns, char counts, and search-index diagnostics), live
feature-guarded; disabled flag returns 200 {enabled:false}.
Client/SPA:
- coc-client nativeCopilotSessions domain with typed contracts.
- Copilot Sessions tab gated by the runtime flag; two-pane read-only panel
with search/sessionId/branch/date filters, disabled/unavailable/loading/
empty/error states, "Native Copilot CLI session" labels, read-only badge
with helper copy, "No assistant response stored" labeling, plain
pre-wrapped text rendering (stored HTML/scripts never execute), and no CoC
chat actions.
Tests:
- Server route + service tests using synthetic temp SQLite fixtures only:
disabled flag, missing/invalid DB, two-repo workspace filtering, sorting,
pagination, turn counts, FTS hits/snippets, combined filters, no-result
state, hostile filter input parameterization, detail ordering/diagnostics,
and workspace-scoped 404s.
- SPA panel tests for all UX states, read-only labeling, inert script text,
filter wiring, and absence of CoC chat action controls.
Docs: coc-knowledge references (rest-api, server-architecture,
dashboard-spa) and packages/coc/AGENTS.md read-only invariant.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fix the broken master-detail width (nested flex-1 + max-w-[46%] collapsed the list to ~23% leaving a large empty gap) by giving the list a clamped ~42% column and letting the detail fill the rest. Remove the redundant per-row 'Native Copilot CLI session' badge that caused horizontal column clipping, and replace the cramped 4-column table with a single-column list of session cards (ID chip, timestamp, summary, repo, turn/branch pills, selected-row accent bar). Polish the filter bar (full-width search with icon, focus rings) and the empty detail state (icon + centered copy). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tighten the panel density: reduce header/filter/row/detail padding and gaps, shrink control heights (h-8 -> h-7), drop font sizes to 10-13px, and shrink badges/labels and pre block max-heights so more sessions and turns fit on screen without horizontal or vertical waste. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Copilot SDK/CLI writes one session id per conversation that equals the native session-store id (~/.copilot/session-store.db sessions.id) and the value CoC persists as processes.sdk_session_id. The read-only Copilot Sessions tab previously listed native sessions independently, so sessions already tracked in the Activity tab appeared in both places. Add ProcessStore.getSdkSessionIds(workspaceId) (SQLite-backed, one indexed query over processes.workspace_id) returning the distinct set of recorded sdk_session_ids. The native session list route passes that set as excludeSessionIds; the service hides matching sessions during its existing in-memory workspace filter (O(1) per row) and returns deduplicatedCount. The panel shows a 'N sessions hidden — already tracked in CoC Activity' hint. Tests: forge getSdkSessionIds unit tests; service-level exclusion and count; route-level dedup via SqliteProcessStore; SPA hint presence/absence. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Deep-link support: the selected native session is reflected in the URL
hash (#repos/{wsId}/copilot-sessions/{sessionId}) via new Router helpers
parseNativeCopilotSessionDeepLink/buildNativeCopilotSessionHash. The panel
syncs selection to the hash on select/clear and restores it on mount and
hashchange, so selections survive refresh/back-forward and are shareable.
Background-job filtering: the native session list now hides automated
background sessions whose first turn matches BACKGROUND_JOB_PROMPT_PREFIXES
(e.g. 'Summarise the following conversation as a short title') — these are
Copilot CLI title-generation jobs, not user conversations (603 of them in
a real store). Detection is a chunked indexed query over turns.turn_index=0;
the hidden count is returned as backgroundJobCount and surfaced as a panel
hint. Opt out via the includeBackgroundJobs service option.
Also fix a stale Router test count guard (REPO_SUB_TAB_VALUES is 17 since
copilot-sessions was added; the assertion still expected 16).
Tests: Router deep-link parse/build, panel select/restore/cross-workspace
deep-link sync, panel background-hidden hint, service + route background-job
exclusion and includeBackgroundJobs passthrough.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ct types
Foundation for the LLM Tools settings page showing each tool's input
parameters compactly (AC-01/AC-02 format).
- Add additive `LlmToolParam` type and optional `params?` field to
`LlmToolMeta` in both the server registry and the coc-client contract.
Existing clients reading only name/label/description/enabledByDefault are
unaffected.
- Add pure `summarizeToolParameters()` / `compactParamType()` helpers that
compress a tool's JSON-schema `parameters` into `{name,type,required}`
entries: primitives keep their type, nested objects -> `{...}`, arrays ->
`[...]`, typeless enums -> `enum`. Returns `[]` for a no-parameter schema
and `undefined` when no JSON schema is available, so callers can render
"No parameters" vs "Parameters unavailable".
- Unit tests covering type compaction, required/optional flags, ordering,
empty-schema, and unavailable-schema cases.
No tool behavior, routing, or persisted preference changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… API Source each toggleable tool's input-schema structure via a display-only mirror (`LLM_TOOL_PARAMETER_SCHEMAS`) and attach the additive `params` summary to GET/PUT `/api/workspaces/:id/llm-tools-config` responses through `withToolParameterMetadata`. The mirror avoids instantiating tool factories at route time (some build heavyweight deps like FileWorkItemStore) and is display-only — it never affects tool execution, validation, provider routing, or persisted prefs. Tools without a locally-declared schema (e.g. the built-in `memory` tool) omit `params` so clients can render "parameters unavailable". Existing `name`/`label`/`description`/`enabledByDefault` fields are unchanged. A drift-guard test compares the mirror's summary against each live tool schema for every cheaply-constructible factory, plus a completeness check that every registry tool is either mirrored or explicitly excluded. Completes AC-01. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Render each tool's input parameters in the workspace LLM Tools panel as a
compact, scannable affordance. Collapsed rows show only a "N parameters"
button (keyboard-accessible, aria-expanded/aria-controls); expanding inline
shows `name: type*` for required and `name?: type` for optional params, with
nested `{...}`/`[...]` shapes left collapsed. Tools with `params: []` show
"No parameters" and tools without a schema show "Parameters unavailable".
The params button lives outside the toggle <label> so activating it never
flips the enable/disable checkbox; toggle save behavior is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…turns AC-01 of the native Copilot session chat reconstruction: add a read-only parser for the per-session log at ~/.copilot/session-state/<id>/events.jsonl, which is the rich source for messages, tool calls + results, model reasoning, images, and errors (the on-disk session-state is a directory, not a file; the sibling session.db holds only todos/inbox, and forge_trajectory_events in the main store is empty). - session-state-parser.ts: parseNativeSessionState() resolves the cross-platform path, reads events.jsonl, and reconstructs ordered ReconstructedConversationTurn[] — coalescing assistant messages by turnId, correlating tool start/complete by toolCallId, capturing reasoningText (thinking), model, base64 image attachments, skills, and tool errors. Returns null (never throws) on missing/malformed/empty input so callers fall back to the flat session-store.db turns. Rejects unsafe session ids (path traversal). - types.ts: add ReconstructedConversationTurn / ReconstructedToolCall / ReconstructedTimelineItem mirroring the SPA ClientConversationTurn subset. - test: 11 cases over a faithful synthetic events.jsonl (rich path with a tool call carrying name+args+result, failed-tool error capture, image data URLs, malformed/empty/missing → null, partial-line resilience, traversal guard, mid-stream tool, turnId coalescing). Validated manually against real sessions (52/87 turns, 46/217 tool calls) and confirmed c3a97a05 (empty SDK job) → null. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-02) Backend mapping + DB fallback for the native Copilot session detail view. - NativeCopilotSessionDetail gains an always-present `conversation` (ReconstructedConversationTurn[]). getSession prefers the rich session-state/<id>/events.jsonl parser output; when it returns null (missing/malformed/empty log) it maps the flat session-store.db turns into text-only user/assistant turns via buildFallbackConversation. - Service accepts sessionStateDir/parseSessionState overrides; plumb a nativeCopilotSessionStateDir option through server + route options for hermetic tests. Strictly read-only — no writes to ~/.copilot. - Mirror ReconstructedToolCall/TimelineItem/ConversationTurn + the conversation field into coc-client contracts. - Tests: rich-path (parser output preferred over DB), DB-fallback mapping (role/content/turnIndex sequencing, empty-message skipping, timeline shape), empty-session, real events.jsonl wiring via sessionStateDir, and an HTTP assertion that conversation flows through the detail endpoint. - Update packages/coc/AGENTS.md and coc-knowledge rest-api.md reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ript (AC-03) Reuse the existing read-only chat ConversationTurnBubble to render the reconstructed native-session conversation instead of the flat <pre> dump. A new SPA-local nativeConversationTurns mapper converts the backend ReconstructedConversationTurn[] into ClientConversationTurn[], folding assistant `thinking` into the content timeline as a markdown blockquote (the chat turn shape has no reasoning field — no component fork). The metadata header is preserved; no input box, streaming, resume, or per-turn (pin/archive/delete) actions are wired. Empty conversations show the existing no-turns state. Tests: pure mapper unit test (field passthrough, thinking fold into timeline+content, fallback) + panel test rewritten to assert the transcript renders one bubble per turn with tool calls/images/model/provider, stored HTML stays inert, and no chat-action controls exist. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Register a new 'dreams-admin' DashboardTab and wire it through the existing tool-nav pattern: ALL_TOOL_NAV_ITEMS entry, TOOL_TAB_GROUP_LABELS -> 'Knowledge', toolNavItem in the Knowledge group, hash route in tabFromHash + Router switch, and a lazy-rendered DreamsView shell. This is the foundational scaffold for the Dreams admin tab; subsequent slices relocate the enable toggle, running-interval, provider/model/timeout defaults, and the provider-activity section into it. Tests: nav-item + group-label assertions, tabFromHash route, sidebar group/data-tab rendering. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the "Dreams provider activity" queue + history out of the AI Provider page and into the admin Dreams tab, reused rather than duplicated. - Extract shared provider brand visuals (PROVIDER_LABELS, ProviderAvatar, brand SVG icons) into shared/providerVisuals.tsx so both the AI Provider page and the activity section share one source of truth. - Move ProviderActivitySection into its own features/dreams component and render it from DreamsView (new optional providerActivity/error/onRefresh props). Refresh control preserved. - Remove the section, its three props, and the now-dead providerActivity imports from AIProviderPage; AdminPanel passes the existing dream activity state/refresh to DreamsView instead, and the auto-refresh effect now loads dream activity when the Dreams tab is the active route (quota still loads on the AI Provider sub-tab). - Tests: new DreamsView.test.tsx (attribution, empty, error, Refresh-preserved, no-handler) and a regression test that the section is gone from the AI Provider page. Update dashboard-spa knowledge reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Render the global `dreams.enabled` toggle in the admin Dreams tab and remove it from the general Settings → Features grid. The runtime flag (`dreamsEnabled`) and PUT /api/admin/config validation are unchanged. - admin-setting-definitions: drop the `ui` block from `dreams.enabled` so it no longer renders on the Features card (key/runtime untouched). - Extract the shared admin row primitives (SourceBadge, AdminRow, AdminToggle, AdminSeg, AdminInputSuffix) into admin/adminControls.tsx so the Dreams tab can reuse them instead of duplicating markup. - AdminPanel owns the Dreams config form (loaded with the rest of the admin config) and a Save handler that persists to global config, invalidates display settings, and applies the runtime patch — same flow the Features card used. Passed into DreamsView as props. - DreamsView renders the toggle inside a dirty-tracked SettingsCard. - Tests: DreamsView toggle reflects/drives config + Save/Cancel wiring; contract test guards dreams.enabled stays admin-editable but off the Features card. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…reen layout Adds the final AC-03 verification tests for the LlmToolsPanel parameter affordance: an explicit keyboard-activation assertion (native button is focusable, Enter expands and Space collapses, with accessible label/state) and a narrow-screen layout assertion (single-column grid by default, wrapping param tokens, fit-width affordance). Verified the production SPA build compiles the Tailwind arbitrary values (pl-[46px] -> padding-left:46px). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… reconstruction
The dashboard-spa.md "Copilot Sessions Tab" section still described the old
plain <pre> text dump ("renders all stored text as plain pre-wrapped text",
per-turn "No assistant response stored" / "Indexed (N chars)" diagnostics),
all of which were removed when the detail view was reconstructed as a rich CoC
chat transcript. Update it to document the backend `conversation:
ReconstructedConversationTurn[]` (rich session-state/<id>/events.jsonl via
parseNativeSessionState, DB fallback via buildFallbackConversation), the SPA
toClientConversationTurns thinking-fold, one read-only ConversationTurnBubble
per turn under the native-session-conversation card, and the strictly
read-only guarantee.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d turns The NativeCopilotSessionsPanel suite stubs ConversationTurnBubble, so no test proved the real chat bubble renders a native-reconstructed transcript. Add a hermetic render integration test that feeds a reconstructed conversation (tool-call timeline items, model reasoning fold, a user image, a failed tool call, and a turn-level error) through the real toClientConversationTurns mapper into the real ConversationTurnBubble, and asserts tool-call cards (name + result), assistant markdown, the reasoning fold, the image gallery, the failed-tool error text, and the turn-level error strip all reach the DOM — closing the AC-03 "tool-call cards/markdown/ images render" DoD gap with permanent regression coverage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The native Copilot session detail render had a tested seam gap: the panel suite stubs ConversationTurnBubble (proving fetch→prop wiring only) while the bubble suite feeds toClientConversationTurns directly (bypassing the panel). Neither exercises the production path AC-03's "demo shows a rich transcript" relies on: panel → cocClient.get() → SessionDetailView → toClientConversationTurns(detail.conversation) → real ConversationTurnBubble. Add an end-to-end render integration test that drives the REAL panel with the REAL bubble (no component stub) and a mocked detail fetch returning a rich reconstructed conversation (modeled on real session 09c6d69e), asserting genuine tool-call cards, the tool result + error text, assistant markdown, the folded reasoning blockquote, and the user image gallery all reach the DOM — the deterministic equivalent of the live screenshot. Read-only is re-asserted (no chat-action controls). Uses the real `ui` barrel; only cocClient, MarkdownView, and useDisplaySettings are mocked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Dreams admin tab reuses the AI-provider `.aip-page` shell, but unlike that page (which scrolls via `.ar-main`), it renders inside `.ar-tool-embed` where `.ar-main--embed` suppresses the outer scroller. The Skills/Memory embeds own an inner scroll region; the `.aip-page` grid has none, so its content — notably the provider-activity queue — overflowed unreachably and the panel could not scroll. Give the embedded `.aip-page` its own scroll region (`overflow-y: auto`) plus page padding mirroring `.ar-page`, scoped to `.ar-tool-embed > .aip-page` so the non-embedded AI-provider page that shares the class is untouched. Add a matching narrow-screen padding override. Extend the admin fit-to-viewport CSS-contract test to lock in that the embedded `.aip-page` owns its scroll region and that Dreams renders inside `.ar-tool-embed` using that shell, so the regression can't silently return. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse duplicate filesystem-backed native CLI transcript records with the same provider session ID to the newest metadata record so list rows and detail deep links remain stable. Add regression coverage for duplicate Claude transcript files and keep documentation current. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Gate legacy Copilot session compatibility routes with features.nativeCliSessions and remove the old nativeCopilotSessions runtime/admin flag so CLI Sessions has one operational switch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Require Claude native session records with cwd metadata to all remain under the active workspace root before listing or serving detail, preventing mixed-cwd transcripts from leaking across workspaces. Add regression coverage for mixed-cwd Claude transcripts and document the stricter native CLI session scoping rule. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the unified CLI Sessions tab and bare cli-sessions deep links aligned with the legacy Copilot Sessions behavior and the REST provider default. Add regression coverage for Copilot-default routing plus provider switching. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reorder the repo sub-tab strip so CLI Sessions sits immediately after the Activity/Chats tab and before Git in both the classic and dev-workflow layouts. CLI Sessions also moves into the Activity/Git/Terminal divider group so it renders without divider-flanked isolation. Update RepoDetail SUB_TABS unit tests to assert the new ordering and group placement, and add a regression block covering CLI Sessions placement in SUB_TABS, VISIBLE_SUB_TABS, the divider group, and the dev-workflow order. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The merged native-CLI-sessions, Dreams admin, and LLM-tool-param features left several deterministic test failures uncovered by the sharded suite: - llm-tool-parameter-schemas: mirror the three canvas tools (write_canvas, read_canvas, extension_canvas) so the registry-completeness guard passes. - shared barrel: re-export providerVisuals so barrel-completeness passes. - config "all fields overridden": set the new dreams.provider, dreams.model, and features.nativeCliSessions keys in the fixture; refresh the inline resolved-config/source snapshot for features.nativeCliSessions. - terminal-tab-integration: update the visibleSubTabs dependency-array assertion for the added nativeCliSessionsEnabled dep. - admin e2e: expect Dreams in the Knowledge nav group. Also fix a Windows-only regression: dashEncodeWorkspaceRoot kept the drive-letter colon (C:\... -> C:-...), an invalid Windows path segment that broke ClaudeNativeSessionProvider directory reads. Encode colons to dashes (C--...), export the helper, and add cross-platform regression tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.