479 Commits
Author SHA1 Message Date
David Kaya 0eac1da70c chore: release v0.0.30 v0.0.30 2026-04-20 09:04:25 +02:00
David Kaya b8553c6593 Merge branch 'agents/approval-mapping-issue-analysis' into main 2026-04-17 20:47:23 +02:00
David KayaandCopilot 26847cf00d fix: consume canonical approvalToolKey from sidecar
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 14:21:53 +02:00
David KayaandCopilot fce0430091 fix: align backend approval tool keys
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 14:05:00 +02:00
David Kaya fa355197cb chore: release v0.0.29 v0.0.29 2026-04-16 14:48:09 +02:00
David KayaandCopilot 5f263002f0 fix: pass mainWindow argument to showAndFocusWindow in second-instance handler
The showAndFocusWindow function signature was updated to require a
mainWindow parameter, but the call site in the second-instance handler
was not updated, causing a TypeScript compilation error that broke CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 14:43:41 +02:00
David Kaya 1376de4148 chore: release v0.0.28 v0.0.28 2026-04-16 14:17:21 +02:00
David Kaya 5ce6bb4b0a Merge branch 'agents/tray-icon-main-window-fix' 2026-04-16 14:16:33 +02:00
David KayaandCopilot 47d3fb0a29 fix: tray icon click opens main window reliably after quick prompt use
showAndFocusWindow() used BrowserWindow.getAllWindows()[0] to find the
main window, which breaks once the quick prompt window is created —
the array order is not guaranteed and windows[0] may resolve to the
quick prompt instead, causing the show/focus calls to target a hidden,
frameless window.

Accept the main window reference as an explicit parameter and guard
against destroyed windows with isDestroyed().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 14:00:30 +02:00
David Kaya 4da31cbdd6 Merge branch 'agents/single-instance-app-launch' 2026-04-16 13:56:19 +02:00
David KayaandCopilot f15323e37e feat: enforce single-instance app launch
Use Electron's requestSingleInstanceLock() to prevent opening
multiple instances. When a second instance is attempted, the
existing window is restored and focused instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 13:54:22 +02:00
David KayaandCopilot f8fe9d866e fix: use platform-native paths in release tests for cross-OS compatibility
The release workflow tests hardcoded Windows-style backslash paths
(C:\workspace\...) which caused path.relative() to produce incorrect
results on Linux and macOS, where backslashes are not path separators.

Replace hardcoded paths with resolve()/join() calls that produce
platform-native paths, fixing CI failures on Linux and macOS.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 13:53:49 +02:00
David Kaya 6c24754749 chore: release v0.0.27 v0.0.27 2026-04-16 12:57:19 +02:00
David Kaya 2a7c627008 Merge branch 'agents/dotnet-aspire-opentelemetry-explorer' 2026-04-16 11:57:06 +02:00
David KayaandCopilot 3a3e1d5eab fix: correct OTEL instrumentation wiring for agent traces
- Fix ActivitySource name from 'Microsoft.Agents.AI' to
  'Experimental.Microsoft.Agents.AI' matching the Agent Framework default
- Wrap agents with UseOpenTelemetry() via AIAgentBuilder so agent
  invocation spans are emitted to the configured OTLP collector
- Add proper disposal of OpenTelemetryAgent wrappers via
  SyncDisposableAdapter bridging IDisposable to IAsyncDisposable
- Enable workflow-level telemetry on WorkflowRunner custom graph builds
  via WithOpenTelemetry() (HandoffWorkflowBuilder and
  GroupChatWorkflowBuilder do not expose this API — framework limitation)
- Fix settings panel help text to be user-facing instead of dev jargon
- Update test assertion for corrected ActivitySource name

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 11:52:13 +02:00
David Kaya 9a9332369b Merge branch 'agents/dotnet-aspire-opentelemetry-explorer' 2026-04-16 11:25:51 +02:00
David KayaandCopilot 67fb950e61 feat: add OpenTelemetry settings UI and sidecar environment wiring
Add a global Telemetry section in the settings panel with:
- Toggle to enable/disable OTLP export
- Text input for the OTLP endpoint URL (default: http://localhost:4317)
- Guidance note about using \un run aspire\ for local testing

Wire the setting through the full stack:
- OpenTelemetrySettings type in shared domain with normalization
- IPC channel, preload binding, and handler for persistence
- SidecarClient forwards settings to createSidecarEnvironment
- Sidecar environment injects OTEL_EXPORTER_OTLP_ENDPOINT when enabled
- Settings loaded from workspace.json on startup and on change

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 11:10:23 +02:00
David KayaandCopilot f7d376fc41 feat: add Aspire dashboard OTEL workflow
Add OTLP export wiring for the sidecar and dev scripts to launch the standalone Aspire Dashboard during development.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 10:39:36 +02:00
David KayaandCopilot 59ea028a24 feat: add release helper
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 09:30:17 +02:00
David KayaandCopilot c7910e6e4b fix: remove streaming text boundary heuristics that injected spurious spaces
The StreamingTextMerger (C#) and mergeStreamingText (TypeScript) contained
custom word-boundary heuristics that inserted spaces between streaming deltas
based on incorrect assumptions. Two bugs caused mid-word spaces:

1. Unconditional space insertion when incoming delta started with uppercase or
   digit characters, breaking acronyms (MDA -> M DA, UAG -> UA G)
2. LooksLikeWordBoundary using global token counts that fired on nearly every
   mid-word token split (writable -> wr itable, fragile -> frag ile)

Both upstream projects (Copilot SDK and Agent Framework) use simple string
concatenation for delta accumulation. LLM streaming tokens natively include
whitespace when needed, so no boundary detection is required.

Removed all boundary heuristic methods and replaced with plain concatenation.
Kept overlap detection and snapshot handling for event redelivery scenarios.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 18:55:34 +02:00
David Kaya 418946b854 chore: bump version to 0.0.26 v0.0.26 2026-04-15 11:15:20 +02:00
David KayaandCopilot 10fcaf2b92 fix: use theme-aware background for chat code blocks
Replace hard-coded dark hex color (bg-[#0d0d10]) with the theme-aware
bg-surface-1 token so the code block background correctly adapts to
light mode. The other zinc-based utility classes already respond to
the light mode CSS variable overrides.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 10:57:04 +02:00
David KayaandCopilot 34fb5420a4 fix: show activity panels for all turns, not just the last one
The displayItems logic only injected orphan run panels for the most
recent user message's run. Previous turns whose thinking messages
were not produced or were lost during reclassification silently
dropped their activity panels.

Now iterate all unconsumed runs and splice a turn-activity panel
after each trigger user message, ensuring every turn with a run
gets a visible activity panel in the chat transcript.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 10:29:19 +02:00
David KayaandCopilot 05b3771544 fix: accurate elapsed timing and UX polish for activity panel
- Fix useElapsedTimer to use completedAt instead of Date.now() for
  finished runs, preventing wildly inaccurate durations (e.g. 9802m)
  when reopening old sessions
- Extract formatElapsedMs as a shared pure formatter; reuse in
  SubagentActivityCard
- Standardize icon column alignment across all activity row types
  using consistent w-4 + h-[18px] icon containers
- Redesign collapsed header: status dot with pulse animation, bolder
  status label, tabular-nums on elapsed time, cleaner hierarchy
- Polish expanded stream: timeline spine connecting activity items,
  more prominent intent dividers with pill-style background,
  tightened vertical rhythm
- Add unit tests for formatElapsedMs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 09:11:38 +02:00
David Kaya 9243ec10a2 Merge branch 'agents/prepared-parrot' 2026-04-15 08:42:58 +02:00
David KayaandCopilot 1f49436d8a fix: serialize sidecar cleanup in batch delete to avoid requestId collision
Multiple concurrent sidecar.deleteSession() calls used
requestId: delete-session-\ which collides when two
fire in the same millisecond. The second overwrites the first in
the pending map, causing the first promise to never resolve and
Promise.allSettled to hang indefinitely — producing Electron's
'reply was never sent' error.

Run cleanup sequentially instead. Also add .catch() to rm() calls
for robustness.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 08:42:55 +02:00
David Kaya 61b5788e78 Merge branch 'agents/confidential-tyrannosaurus' 2026-04-15 08:35:31 +02:00
David KayaandCopilot 875c6a3706 chore: upgrade copilot preview package
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 08:34:46 +02:00
David KayaandCopilot b4aaf62179 chore: upgrade agent-framework to 1.1.0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 08:31:54 +02:00
David Kaya 4ffd6ad8d4 Merge branch 'agents/prepared-parrot' 2026-04-15 08:27:52 +02:00
David KayaandCopilot c22bd32f97 fix: wire modifier key detection into SessionItem click handler
Ctrl+Click (⌘+Click on Mac) and Shift+Click were not triggering
multi-select mode because modifier key detection in handleSessionClick
was never called from the actual click chain.

Root cause:
- SessionItem.handleClick only checked isSelecting state, never
  inspected modifier keys on the mouse event
- ProjectGroup passed onSessionSelect directly (plain navigation),
  bypassing handleSessionClick entirely
- Search results called handleSessionClick with a hardcoded fake event
  where all modifier keys were false

Fix:
- Move modifier key detection into SessionItem.handleClick, which
  receives the real React.MouseEvent with accurate modifier state
- Add onEnterSelectionMode and onShiftSelect props to SessionItem
- Thread new callbacks through ProjectGroup
- Remove dead handleSessionClick function from Sidebar
- Fix search results to use the new callback-based approach

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 08:27:44 +02:00
David Kaya dad9769fa1 Merge branch 'agents/prepared-parrot' 2026-04-15 08:15:01 +02:00
David Kaya 56e2f8669c Merge branch 'agents/abundant-squirrel'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2026-04-15 08:14:58 +02:00
David Kaya d6008da0af Merge branch 'main' into agents/prepared-parrot 2026-04-15 08:14:33 +02:00
David KayaandCopilot 575aca360a feat: batch session archive and delete with multi-select UI
Add multi-select mode to the sidebar session list, enabling users to
archive, restore, or delete multiple sessions at once.

UX:
- Ctrl+Click (Cmd+Click on Mac) any session to enter multi-select mode
- Animated checkboxes stagger-reveal across all visible sessions
- Click to toggle, Shift+Click for range selection
- Running sessions are excluded from selection (safety guard)
- Floating action bar slides up with count pill, Archive, Delete, Cancel
- Batch delete shows a confirmation dialog with hold-to-confirm for 3+
  sessions and a scrollable list of session titles
- Batch archive shows an undo toast with 5-second auto-dismiss
- Escape key or Cancel button exits multi-select mode

Backend:
- batchSetSessionsArchived IPC: single load/mutate/persist cycle for N
  sessions instead of N sequential calls
- batchDeleteSessions IPC: parallel cleanup of scratchpad dirs and SDK
  sessions, then single workspace persist

Accessibility:
- Action bar: role=toolbar, aria-label
- Checkboxes: role=checkbox, aria-checked, keyboard-activatable
- Selection count: aria-live=polite
- Delete dialog: role=alertdialog, aria-modal, focus trap

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 07:12:45 +02:00
David KayaandCopilot 649eeddff3 feat: add configurable hotkey for Quick Prompt in settings
Add a HotkeyRecorder UI component that lets users click to enter
recording mode, press a modifier+key combination, and immediately
save it as the new Quick Prompt global shortcut.

- New HotkeyRecorder component in ui/ with live modifier preview,
  animated recording indicator, click-outside/Escape to cancel,
  platform-aware key symbol display, and disabled state support
- Integrate into QuickPromptSettingsSection with separate enable
  toggle and recorder rows
- Recorder is disabled when the global hotkey toggle is off
- Existing GlobalHotkeyService.update() re-registers automatically

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 07:02:27 +02:00
David Kaya 521be0de3c Merge branch 'agents/embarrassing-trout' 2026-04-15 06:59:00 +02:00
David KayaandCopilot fdfa6f3046 fix: remove shadow causing gradient rectangle and add keyboard navigation to quick prompt model picker
Remove shadow-2xl shadow-black/50 from the ModelSelector dropdown. On
transparent Electron windows (Windows), box-shadows paint onto the
transparent canvas and create a visible rectangle behind the UI — the
panel itself already avoided this with a comment explaining why.

Add full arrow-key navigation to the model picker listbox: ArrowUp/Down
cycle through options, Enter/Space selects, Home/End jump to extremes,
Escape closes. The container auto-focuses on mount so keyboard input
works immediately after opening via Tab+Enter. Mouse hover also syncs
the focused index for consistent visual feedback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 06:57:10 +02:00
David KayaandCopilot 0e9d77c745 feat: allow saved workspace agents in the workflow editor
Add the ability to select from saved workspace agents when configuring
agent nodes in the workflow editor. Previously, adding an agent node
always created a new inline agent with empty fields.

Changes:
- Thread workspaceAgents prop through SettingsPanel → WorkflowEditor →
  WorkflowGraphInspector → AgentNodeInspector
- Add Inline/Saved Agent source toggle in the agent node inspector
- Add workspace agent picker dropdown with stale-agent detection
- Add override-aware fields that show inherited values from the saved
  agent with per-field reset buttons and visual indicators
- Support clean bidirectional switching between inline and linked modes
- Show saved workspace agents as directly-addable items in the node
  palette with link icon, separated from the generic New Agent button
- Add handleAddWorkspaceAgentNode to create pre-linked agent nodes

The underlying data model (AgentNodeConfig.workspaceAgentId, overrides)
and resolution logic (resolveWorkflowAgentNode) already existed but were
never exposed in the UI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-14 16:29:07 +02:00
David KayaandCopilot bed6427dfc fix: eliminate quick prompt panel flash on show
Add animation-fill-mode 'both' to .qp-panel-enter so the from-keyframe
(opacity: 0) applies immediately on mount, preventing the single-frame
flash of the opaque surface background before the entrance animation
begins.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-14 11:17:23 +02:00
David Kaya 6068ee42e1 chore: bump to version 0.0.25 v0.0.25 2026-04-13 21:08:30 +02:00
David KayaandCopilot 41d19e007d docs: update ARCHITECTURE.md for streaming ownership and provider adapter layer
- Document StreamingTranscriptBuffer as the single owner of text assembly
- Note provider adapter layer (IProviderEventAdapter.TryAdapt) for event
  normalization and how to add new providers
- Add capability metadata to protocol boundary description
- Update assistant-intent events as provider-neutral (not Copilot-specific)
- Add provider event normalization to sidecar runtime boundary

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 16:24:07 +02:00
David KayaandCopilot cc626a3152 test: add streaming regression tests for turn lifecycle and transitions
Add 5 regression tests covering:
- Thinking-to-response transition (reclassify → new message, no flash)
- Concurrent multi-message streaming independence
- Run-updated replacement semantics (no duplicates)
- Full turn lifecycle (intent → deltas → complete → idle clears intent)
- Message-complete content override of streamed content

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 16:21:44 +02:00
David KayaandCopilot 8d08a1df1a refactor: wire normalized intent into activity UI
- ChatPane header now prefers session.currentIntent over the activity-
  derived label from summarizeSessionActivity for the busy status display
- TurnActivityPanel receives currentIntent via props and prefers it over
  extractLatestIntent (report_intent tool-call scanning) when the panel
  is active; falls back to tool-call scan for completed/inactive runs
- This replaces the report_intent-as-status inference pattern with the
  normalized assistant-intent event data from the backend

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 16:20:04 +02:00
David KayaandCopilot 08886f9078 refactor: consolidate streaming text ownership and forward intent events
- Main process now always emits resolved content in message-delta events,
  making it the single authoritative text assembly point
- Renderer no longer imports or runs mergeStreamingText; uses main-process
  resolved content directly with simple append as defensive fallback
- Forward assistant-intent events through the session event pipeline; track
  currentIntent on SessionRecord, cleared on turn completion/cancellation
- Forward reasoning-delta events through the session event pipeline so
  renderers can consume incremental reasoning text
- Add SessionEventKind entries: assistant-intent, reasoning-delta
- Add SessionEventRecord fields: intent, reasoningId, reasoningDelta
- Remove dead applyTurnDelta, applyMessageReclassified, applyAgentActivity
  methods from AryxAppService (superseded by SessionTurnExecutor)
- Remove stale mergeStreamingText and appendRunActivityEvent imports from
  AryxAppService
- Add 5 regression tests: resolved content path, simple append fallback,
  intent set/clear lifecycle, duplicate suppression, intent preservation
  during status transitions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 16:12:41 +02:00
David KayaandCopilot 1fdb1c27d5 refactor: finalize backend streaming ownership
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 15:47:39 +02:00
David KayaandCopilot 4e34d2abfc refactor: unify tool call stream tracking
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 15:33:27 +02:00
David KayaandCopilot 7b9c4d140c refactor: enrich provider turn stream model
Add turn-stream capability metadata and richer normalized provider events for reasoning blocks, tool lifecycle, and turn boundaries. Track those signals in turn execution state and cover the new Copilot adapter/state behavior with tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 15:23:47 +02:00
David KayaandCopilot fde82bef4d fix: rewrite Quick Prompt event handling with message-by-ID tracking
The sidecar's fire-and-forget event handler pattern
(invokeRunTurnHandler) causes events to arrive out of order:
message-complete and status:idle can arrive before all
message-delta events have been emitted. Additionally, deltas
from multiple messages (thinking, response, sub-agent) were
naively concatenated into a single string, producing garbled
output.

Replace the single-string accumulation with a proper message
tracking model (Map<messageId, TrackedMessage>) that mirrors the
main app's SessionRecord.messages approach:

- Track each message independently by messageId
- Use message-complete event's content field as the authoritative
  final text, replacing any garbled intermediate streaming state
- Mark messages as finalized on message-complete to skip late
  arriving deltas that would corrupt the final content
- Derive display from the last non-thinking message's content
- Only transition to 'complete' when all tracked messages are
  not-pending AND at least one non-thinking message has content,
  preventing premature completion from setup/init events

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 14:39:41 +02:00
David KayaandCopilot 6ef44c6689 fix: prevent premature Quick Prompt completion from setup events
The session emits completion signals (agent-activity:completed,
message-complete, status:idle) during initialization before any
response content arrives. These early events were incorrectly
transitioning the popup to 'complete' phase, causing the
Nothing → In Progress → Nothing cycling pattern.

Track whether response content has been received via a ref and
only transition to 'complete' when hasContentRef is true. This
ensures setup/init completion events are ignored and the popup
stays in streaming until actual content has arrived and a
terminal event follows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-13 14:14:25 +02:00