Commit graph

693 commits

Author SHA1 Message Date
Mike Sawka
4969ee19b8
tsunami / builder updates (jsfuncs, devtools, gpt-5.4, etc) (#3226)
Some checks are pending
CodeQL / Analyze (push) Waiting to run
Docsite CI/CD / Build Docsite (push) Waiting to run
Docsite CI/CD / Deploy to GitHub Pages (push) Blocked by required conditions
TestDriver.ai Build / Build for TestDriver.ai (push) Waiting to run
lots of updates for tsunami and builder window:
* jsfuncs
* devtools windows
* devtools proper cleanup (fixes crashes)
* scrollbar fixes
* lock AI models -- gpt-5.4, builder prompts, etc
2026-04-17 12:30:39 -07:00
Mike Sawka
158e404d80
Lots of fixes, big and small for processviewer (frontend and backend) (#3224)
The big fix is not spawning a goroutine per process. other fixes are
more minor, but improve the quality and clean up some edge cases.
2026-04-15 22:36:28 -07:00
Mike Sawka
5e3673c338
batch wsh:run tevents by hour (#3181) 2026-04-15 11:06:26 -07:00
Drew Goddyn
1fe0fa236c
fix: trim trailing whitespace from terminal clipboard copies (#3167)
Fixes #2778.

## Problem

`xterm.js`'s `getSelection()` returns lines padded to the full terminal
column width. Every copy path passed this directly to
`navigator.clipboard.writeText()`, so pasting into Slack, editors, etc.
included hundreds of trailing spaces.

## Solution

Adds a `term:trimtrailingwhitespace` setting (default `true`) that
strips trailing whitespace from each line before writing to the
clipboard. Applied to all three copy paths:

- copy-on-select (`termwrap.ts`)
- `Ctrl+Shift+C` (`term-model.ts`)
- right-click Copy context menu (`term-model.ts`)

OSC 52 is intentionally excluded — that path copies program-provided
text, not grid content.

The trim itself uses the same per-line `trimEnd()` approach already
present in `bufferLinesToText` via `translateToString(true)`.

Setting to `false` restores the previous behaviour.

## Files changed

- `pkg/wconfig/settingsconfig.go` — new `TermTrimTrailingWhitespace
*bool` field
- `pkg/wconfig/defaultconfig/settings.json` — default `true`
- `frontend/app/view/term/termutil.ts` — `trimTerminalSelection` helper
- `frontend/app/view/term/termwrap.ts` — copy-on-select path
- `frontend/app/view/term/term-model.ts` — Ctrl+Shift+C and right-click
paths
- Generated: `pkg/wconfig/metaconsts.go`, `frontend/types/gotypes.d.ts`,
`schema/settings.json`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:24:39 -07:00
Mike Sawka
ffd0b669a5
fix notfound error in settings (#3212) 2026-04-15 10:22:45 -07:00
Mike Sawka
a08c2d7431
remove old waveai backend code (#3195)
frontend was removed in the last release. cleaning up the backend code.
remove wsapi host (cloud service is also getting removed)
2026-04-15 10:22:25 -07:00
Mike Sawka
9f41b5761c
remove electron deps from about.tsx (#3194) 2026-04-07 10:04:02 -07:00
Lucy Farnik
57e4e27a29
feat: add opt-in split buttons to block headers (#3159)
Add two icon buttons (horizontal/vertical split) to every block's header
bar, gated behind a new `app:showsplitbuttons` setting (default false).
When enabled, the buttons appear before the settings cog.

Motivation: for users who split panes frequently, having the buttons
always visible speeds up the workflow vs. right-click > context menu.
The split functionality already exists — this just surfaces it more
conveniently.

- New setting `app:showsplitbuttons` (Go + TS + default config)
- Split buttons in `blockframe-header.tsx`, using existing
`createBlockSplitHorizontally`/`createBlockSplitVertically`
- New pane clones the current block's meta so terminals inherit
shell/connection config

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 17:07:34 -07:00
Mateusz Świszcz
bda8421377
feat: add widgets sidebar toggle button to view menu (#3140)
Add ability to toggle the Widgets sidebar visibility via a button in the
tabbar. State persists across sessions and workspaces through workspace
metadata (layout:widgetsvisible).

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: sawka <mike@commandline.dev>
2026-03-31 16:06:13 -07:00
Mateusz Świszcz
984b4e5eb1
fix: Mouse Back/Forward support in webviews + few bugfixes (#3141)
- Add Mouse-3/Mouse-4 (back/forward) navigation support in webviews
- Add COLORTERM=truecolor env variable for terminal sessions
- Fix AI button width calculation when button is hidden
- Fix setSizeAndPosition animation on tab layout updates
- Increase DevInitTimeout for slower startup scenarios
- Update .gitignore and package-lock.json

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 15:11:15 -07:00
Mike Sawka
0ade6ee997
updates to make processviewer more robust (#3144) 2026-03-30 11:18:58 -07:00
Mike Sawka
96c2526f2a
First Cut at a new ProcessViewer Widget (#3137) 2026-03-27 13:59:25 -07:00
Mike Sawka
b436aaecc4
fix #3011 (missing blockfile) when splitting durable sessions (#3125) 2026-03-26 15:35:55 -07:00
lif
b26eb69df6
fix: set XDG_CONFIG_DIRS and XDG_DATA_DIRS defaults in tryGetPamEnvVars (#3121)
## Summary

- Fixes #2970: WaveTerm does not inherit `XDG_CONFIG_DIRS` (and
`XDG_DATA_DIRS`) when snap or other environments strip these variables
and PAM env files do not define them
- In `tryGetPamEnvVars()`, after the existing `XDG_RUNTIME_DIR`
fallback, adds identical fallback logic for `XDG_CONFIG_DIRS` (default:
`/etc/xdg`) and `XDG_DATA_DIRS` (default: `/usr/local/share:/usr/share`)
per the XDG Base Directory Specification
- No behavior change when these vars are already set by PAM env files

## Root Cause

Snap confinement strips several XDG environment variables.
`tryGetPamEnvVars()` already handles `XDG_RUNTIME_DIR` with a sensible
default, but `XDG_CONFIG_DIRS` and `XDG_DATA_DIRS` were left unhandled,
causing child shells to receive empty/unset values.

## Test plan

- [ ] `gofmt -l ./pkg/shellexec/` — no output (clean)
- [ ] `go build ./...` — succeeds
- [ ] On Linux with snap, verify that child shells receive
`XDG_CONFIG_DIRS=/etc/xdg` and
`XDG_DATA_DIRS=/usr/local/share:/usr/share` when the variables are not
set by the desktop environment

Signed-off-by: majiayu000 <1835304752@qq.com>
2026-03-26 10:45:10 -07:00
Copilot
24de0c1bcd
Deprecate the legacy waveai block UI and add a preview for its replacement state (#3122)
- [x] Inspect the current legacy Wave AI block UI and widget config
references
- [x] Restyle the deprecated `waveai` block message to remove the inner
card/icon and position it slightly above center
- [x] Remove `defwidget@ai` from default widgets and delete the related
frontend special-case filtering
- [x] Update the widgets preview mock data and scenarios to reflect the
removed AI default widget
- [x] Re-run targeted validation, review, and security scan

<!-- START COPILOT CODING AGENT TIPS -->
---

📍 Connect Copilot coding agent with [Jira](https://gh.io/cca-jira-docs),
[Azure Boards](https://gh.io/cca-azure-boards-docs) or
[Linear](https://gh.io/cca-linear-docs) to delegate work to Copilot in
one click without leaving your project management tool.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
2026-03-26 10:39:05 -07:00
lif
0b29c49076
fix: use fspath.Base to strip Windows paths on SSH remote drag-drop (#3118)
Fixes #3079

## Summary

When dragging a local file from Windows to an SSH remote connection, the
full Windows path (e.g. `D:\package\AA.tar`) was being passed to
`filepath.Base` on the remote (Linux) side. Since `filepath.Base` on
Linux does not recognize backslashes as separators, the full path was
used as the destination filename.

- In `RemoteFileCopyCommand` (`wshremote_file.go:159`), replace
`filepath.Base(srcConn.Path)` with `fspath.Base(srcConn.Path)`
- `fspath.Base` calls `ToSlash` before `path.Base`, converting
backslashes to forward slashes first, so `D:\package\AA.tar` correctly
yields `AA.tar` on any OS
- Same-host copies at line 86 use `filepath.Base(srcPathCleaned)` and
are unaffected — those run on the same OS where `filepath.Base` is
correct

## Test Plan

- Added `pkg/remote/fileshare/fspath/fspath_test.go` with table-driven
tests for `fspath.Base`:
  - Windows path with backslashes: `D:\package\AA.tar` → `AA.tar`
  - Windows path with forward slashes: `D:/package/AA.tar` → `AA.tar`
  - Unix path: `/home/user/file.txt` → `file.txt`
  - Filename only: `file.txt` → `file.txt`
- `go test ./pkg/remote/fileshare/fspath/...` passes

Signed-off-by: majiayu000 <1835304752@qq.com>
2026-03-25 13:31:01 -07:00
Mike Sawka
101d09b842
fix for terrible background color for default "ls" output on pwsh (#3119) 2026-03-25 13:06:57 -07:00
Mike Sawka
176657db79
increase buffer size for stream to lines to accomodate oversize packets (#3112) 2026-03-24 12:18:14 -07:00
Mike Sawka
6a287e4b84
migrate old file streaming to new modern interface (w/ flow control) (#3096) 2026-03-24 09:59:14 -07:00
Mike Sawka
645424a8be
Change presets/bg.json => backgrounds.json, migrate, change tab background to tab:background key (#3108)
also fixes aipanel's border colors
2026-03-24 09:00:45 -07:00
Mike Sawka
3028c2abf1
switch /wave/stream-file to use new modern streams (w/ flow control) and fix big ttfb streaming bug (#3084) 2026-03-19 15:17:04 -07:00
Mike Sawka
c126306da1
fallback to canvas renderer if webgl is not available, debug toggle for testing (#3081) 2026-03-18 15:57:42 -07:00
Mike Sawka
ac6b2f3520
New Vertical Tab Bar Option (#3059)
Lots of work on the vtabbar UI / UX to make it work and integrate into
the Wave UI
Lots of work on the workspace-layout-model to handle *two* resizable
panels.
2026-03-13 18:38:10 -07:00
Mike Sawka
cdb300ad97
fix issue with an undefined this in service code (#3048) 2026-03-12 16:20:11 -07:00
Mike Sawka
52dd0a2637
Add Claude Code Integration Guide + Fix Badge Priority Bug (#3040) 2026-03-11 22:16:02 -07:00
Mike Sawka
9ee654dd6e
Preview Directory Updates (modtime format, zebra, default sort, yml, context-menu) (#3038)
Lots of small updates:
* Fix modtime format to show time not just "today". Make fixed font.
* Zebra stripe rows
* Fix .yml files to be detected as yaml
* Add a new config option for changing the default sort (Name vs Mod
Time)
* Add ability to change the defaults using the context menu
* Make Size column fixed font
* Add vertical bars between header columns (more visual resize handles)
2026-03-11 16:20:05 -07:00
Copilot
ecccad6ea1
TabBar full preview + much more FE mocking via WaveEnv to enable it (#3028)
Large PR that extends WaveEnv mocking to fully cover the (complicated) TabBar implementation.  Also includes a full preview of the tab bar in the preview server with lots of controls to simulate different scenarios.

As a result of this mocking, also fixed a bunch of dependencies, and layout errors, random bugs, and visual UX bugs in the tab bar, making it more robust.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
Co-authored-by: sawka <mike@commandline.dev>
2026-03-11 13:54:12 -07:00
Mike Sawka
7119970794
flip bell-indicator to true by default (#3023) 2026-03-09 20:35:22 -07:00
Mike Sawka
e6e559c1e0
New WaveEnv, for preview server + mocking (#3015) 2026-03-09 13:21:31 -07:00
Mike Sawka
e41aabf758
Block Level Indicators/Badges, Update TabBar Styling, Add Badges/Flags to Tabs (#3009) 2026-03-09 13:13:32 -07:00
Mike Sawka
71f7e98175
create a FE rpc mock (#3014) 2026-03-07 14:09:40 -08:00
Copilot
68719988ea
Fix connparse handling for scheme-less //... WSH shorthand URIs (#3006)
`pkg/remote/connparse` was failing on shorthand WSH inputs that omit the
`wsh://` scheme, including remote hosts, WSL targets, and Windows local
paths. The parser was splitting on `://` too early and misclassifying
leading `//` inputs before WSH shorthand handling ran.

- **What changed**
- Detect scheme-less WSH shorthand up front with `strings.HasPrefix(uri,
"//")`
- Route those inputs through the existing WSH path parsing flow instead
of the generic `://` split path
- Reuse the same shorthand flag when deciding whether to parse as
remote/local WSH vs current-path shorthand

- **Behavioral impact**
- `//conn/path/to/file` now parses as host `conn` with path
`path/to/file`
- `//wsl://Ubuntu/path/to/file` now preserves the WSL host and absolute
path shape
- `//local/C:\path\to\file` now parses as local Windows shorthand
instead of being treated as a current-path string

- **Scope**
  - Keeps the existing test expectations intact
  - Limits the change to `pkg/remote/connparse/connparse.go`

```go
isWshShorthand := strings.HasPrefix(uri, "//")

if isWshShorthand {
    rest = strings.TrimPrefix(uri, "//")
} else if len(split) > 1 {
    scheme = split[0]
    rest = strings.TrimPrefix(split[1], "//")
}
```

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
Co-authored-by: sawka <mike@commandline.dev>
2026-03-06 17:55:55 -08:00
Copilot
56c18291e6
Update aiusechat read_dir tests for typed entry output (#3007)
`pkg/aiusechat/tools_readdir_test.go` was still asserting the old
`entries` payload shape after `read_dir` moved to returning typed
directory entries. This caused the `pkg/aiusechat` test failures even
though the tool behavior itself was already correct.

- **Align test expectations with current callback output**
- Update `TestReadDirCallback` to treat `entries` as
`[]fileutil.DirEntryOut`
- Assert directory/file classification via the `Dir` field instead of
map lookups

- **Fix truncation/sorting coverage**
- Update `TestReadDirSortBeforeTruncate` to validate the typed slice
returned by `readDirCallback`
- Preserve the existing intent of the test: directories should still be
sorted ahead of files before truncation

- **Keep scope limited to stale tests**
  - No changes to `read_dir` implementation or output contract
  - Only the broken test assumptions were corrected

```go
entries, ok := resultMap["entries"].([]fileutil.DirEntryOut)
if !ok {
    t.Fatalf("entries is not a slice of DirEntryOut")
}

for _, entry := range entries {
    if entry.Dir {
        // directory assertions
    }
}
```

<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/wavetermdev/waveterm/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
2026-03-06 17:51:40 -08:00
Copilot
3f4484a9e2
Remove dead “move block to new window” path and dependent unused APIs (#3002)
`WindowService.MoveBlockToNewWindow` appears to be unreferenced, and its
supporting path had become isolated. This change removes that dead RPC
surface and the backend/eventbus helpers that existed only for that
flow.

- **Window service cleanup (backend RPC)**
- Removed `MoveBlockToNewWindow_Meta` and `MoveBlockToNewWindow` from
`pkg/service/windowservice/windowservice.go`.
  - Dropped now-unused imports tied to that method (`log`, `eventbus`).

- **Store cleanup**
  - Removed `MoveBlockToTab` from `pkg/wstore/wstore.go`.
  - Removed now-unused `utilfn` import from the same file.

- **Eventbus cleanup**
  - Removed unused event constant `WSEvent_ElectronNewWindow`.
- Removed `getWindowWatchesForWindowId` and `BusyWaitForWindowId`, which
were only used by the deleted move-to-new-window path.
  - Removed now-unused `time` import.

- **Generated frontend service surface**
- Regenerated service bindings and removed
`WindowServiceType.MoveBlockToNewWindow(...)` from
`frontend/app/store/services.ts`.

Example of removed RPC surface:
```ts
// removed from frontend/app/store/services.ts
MoveBlockToNewWindow(currentTabId: string, blockId: string): Promise<void> {
    return WOS.callBackendService("window", "MoveBlockToNewWindow", Array.from(arguments))
}
```

<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/wavetermdev/waveterm/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
2026-03-06 16:47:12 -08:00
Copilot
7f5487d9ac
Remove mock-heavy OSC52 Vitest coverage (#2975)
The issue called out that the OSC52 unit tests were mostly validating
mock setup rather than meaningful behavior. This PR trims that
low-signal coverage by removing the Vitest suite for OSC52.

- **Scope**
  - Deleted `frontend/app/view/term/osc-handlers.test.ts`.
  - No production/runtime code changes.

- **Rationale reflected in changes**
- Removes brittle, mock-dominant tests for logic considered too simple
for this unit-test shape.
  - Keeps the codebase focused on higher-value test coverage.

```diff
- frontend/app/view/term/osc-handlers.test.ts
```

<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/wavetermdev/waveterm/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
2026-03-04 16:24:42 -08:00
Copilot
edc20f7ec0
Bring Anthropic usechat backend to OpenAI-level tool-use parity and stream robustness (#2971)
This updates `pkg/aiusechat/anthropic` from partial implementation to
full backend parity for core tool-use orchestration and stream behavior.
The main gaps were unimplemented tool lifecycle methods, missing
persisted tool-use UI state, and weaker disconnect/error handling versus
the OpenAI backend.

- **Tool-use lifecycle parity (critical path)**
  - Implemented Anthropic backend support for:
    - `UpdateToolUseData`
    - `RemoveToolUseCall`
    - `GetFunctionCallInputByToolCallId`
- Wired `pkg/aiusechat/usechat-backend.go` to call Anthropic
implementations instead of stubs.
- Added Anthropic run-step nil-message guard so `nil` responses are not
wrapped into `[]GenAIMessage{nil}`.

- **Persisted tool-use state in Anthropic native messages**
  - Added internal `ToolUseData` storage on Anthropic `tool_use` blocks.
- Ensured internal-only fields are stripped before API requests via
`Clean()`.

- **UI conversion parity for reloaded history**
- Extended `ConvertToUIMessage()` to emit `data-tooluse` parts when
tool-use metadata exists, in addition to `tool-{name}` parts.

- **Streaming UX parity for tool argument deltas**
  - Added `aiutil.SendToolProgress(...)` calls during:
    - `input_json_delta` (incremental updates)
    - `content_block_stop` for `tool_use` (final update)

- **Disconnect/stream robustness**
  - Added `sse.Err()` checks in event handling and decode-error path.
- Added partial-text extraction on client disconnect and deterministic
ordering of partial blocks.
- Cleans up completed blocks from in-flight state to avoid duplicate
partial extraction.

- **Correctness + hygiene alignment**
- Continuation model checks now use `AreModelsCompatible(...)` (instead
of strict string equality).
- Added hostname sanitization in Anthropic error paths (HTTP error
parsing and `httpClient.Do` failures).
- Replaced unconditional Anthropic debug `log.Printf` calls with
`logutil.DevPrintf`.

- **Targeted coverage additions**
  - Added Anthropic tests for:
    - function-call lookup by tool call id
    - tool-use data update + removal
    - `data-tooluse` UI conversion behavior

```go
// usechat-backend.go
func (b *anthropicBackend) RunChatStep(...) (..., []uctypes.GenAIMessage, ...) {
    stopReason, msg, rateLimitInfo, err := anthropic.RunAnthropicChatStep(ctx, sseHandler, chatOpts, cont)
    if msg == nil {
        return stopReason, nil, rateLimitInfo, err
    }
    return stopReason, []uctypes.GenAIMessage{msg}, rateLimitInfo, err
}
```

<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/wavetermdev/waveterm/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
Co-authored-by: sawka <mike@commandline.dev>
2026-03-04 16:20:50 -08:00
Mike Sawka
98c374b8cd
quick updates to get apptype (#2969) 2026-03-03 15:19:23 -08:00
Mike Sawka
b5d23e544e
v0.14.1 Release Notes and Onboarding (#2966) 2026-03-03 08:58:31 -08:00
Copilot
df24959e23
Add native 2+ arg RPC support and wire a concrete TestMultiArgCommand through server, generated clients, and CLI (#2963)
This PR extends WSH RPC command signatures to support `ctx + 2+ typed
args` while preserving existing `ctx` and `ctx + 1 arg` behavior. It
also adds a concrete `TestMultiArgCommand` end-to-end so the generated
Go/TS client surfaces can be inspected and exercised from CLI.

- **RPC wire + dispatch model**
- Added `wshrpc.MultiArg` (`args []any`) as the over-the-wire envelope
for 2+ arg commands.
- Extended RPC metadata to track all command arg types
(`CommandDataTypes`) and exposed a helper for normalized access.
  - Updated server adapter unmarshalling to:
    - decode `MultiArg` for 2+ arg commands,
    - validate arg count,
- re-unmarshal each arg into its declared type before invoking typed
handlers.
  - Kept single-arg commands on the existing non-`MultiArg` path.

- **Code generation (Go + TS)**
- Go codegen now emits multi-parameter wrappers for 2+ arg methods and
packs payload as `wshrpc.MultiArg`.
- TS codegen now emits multi-parameter API methods and packs payload as
`{ args: [...] }`.
  - 0/1-arg generation remains unchanged to avoid wire/API churn.

- **Concrete command added for validation**
  - Added to `WshRpcInterface`:
- `TestMultiArgCommand(ctx context.Context, arg1 string, arg2 int, arg3
bool) (string, error)`
- Implemented in `wshserver` with deterministic formatted return output
including source + all args.
- Updated `wsh test` command to call `TestMultiArgCommand` and print the
returned string.

- **Focused coverage**
- Added/updated targeted tests around RPC metadata and Go/TS multi-arg
codegen behavior, including command declaration for `testmultiarg`.

Example generated call shape:

```go
func TestMultiArgCommand(w *wshutil.WshRpc, arg1 string, arg2 int, arg3 bool, opts *wshrpc.RpcOpts) (string, error) {
    return sendRpcRequestCallHelper[string](
        w,
        "testmultiarg",
        wshrpc.MultiArg{Args: []any{arg1, arg2, arg3}},
        opts,
    )
}
```

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
Co-authored-by: sawka <mike@commandline.dev>
2026-03-02 12:29:04 -08:00
Copilot
4ec09cb611
Centralize proxy HTTP client creation in aiutil and remove redundant backend tests (#2961)
`makeHTTPClient(proxyURL)` had been duplicated across AI backends with
equivalent behavior. This change consolidates the logic into a single
helper in `aiutil` and updates backends to consume it, then removes
backend-local tests that only re-verified that shared utility behavior.

- **Shared client construction**
- Added `aiutil.MakeHTTPClient(proxyURL string) (*http.Client, error)`
in `pkg/aiusechat/aiutil/aiutil.go`.
- Standardizes proxy parsing and `http.Transport.Proxy` setup in one
place.
- Keeps streaming-safe client semantics (`Timeout: 0`) and existing
invalid proxy URL error behavior.

- **Backend refactor**
  - Removed duplicated client/proxy setup blocks from:
    - `pkg/aiusechat/openaichat/openaichat-backend.go`
    - `pkg/aiusechat/gemini/gemini-backend.go`
    - `pkg/aiusechat/openai/openai-backend.go`
    - `pkg/aiusechat/anthropic/anthropic-backend.go`
  - Replaced with direct calls to the shared helper.

- **Test cleanup**
- Deleted backend tests that only covered basic proxy client creation
and no backend-specific behavior:
    - `pkg/aiusechat/openaichat/openaichat-backend_test.go`
    - `pkg/aiusechat/gemini/gemini-backend_test.go`

```go
httpClient, err := aiutil.MakeHTTPClient(chatOpts.Config.ProxyURL)
if err != nil {
    return nil, nil, nil, err
}
resp, err := httpClient.Do(req)
```

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
2026-03-02 11:16:50 -08:00
Mike Sawka
cff84773a6
minor changes (#2962) 2026-02-28 15:48:52 -08:00
Copilot
4956c92c55
Make Wave home config writes atomic and serialized to avoid watcher partial reads (#2945)
`WriteWaveHomeConfigFile()` previously used direct `os.WriteFile`, which
can expose truncation/partial-write states to the JSON file watcher.
This change switches config persistence to temp-file + rename semantics
and serializes writes through a single process-wide lock for config file
writes.

- **Atomic file write helper**
  - Added `AtomicWriteFile()` in `pkg/util/fileutil/fileutil.go`.
- Writes to `<filename>.tmp` in the same directory, then renames to the
target path.
  - Performs temp-file cleanup on error paths.
- Introduced a shared suffix constant (`TempFileSuffix`) used by
implementation/tests.

- **Config write path update**
- Updated `WriteWaveHomeConfigFile()` in `pkg/wconfig/settingsconfig.go`
to:
- Use a package-level mutex (`configWriteLock`) so only one config write
runs at a time (across all config files).
- Call `fileutil.AtomicWriteFile(...)` instead of direct
`os.WriteFile(...)`.

- **Focused coverage for atomic behavior**
  - Added `pkg/util/fileutil/fileutil_test.go` with tests for:
- Successful atomic write (target file contains expected payload and no
leftover `.tmp` file).
    - Rename-failure path cleanup (temp file is removed).

```go
func WriteWaveHomeConfigFile(fileName string, m waveobj.MetaMapType) error {
    configWriteLock.Lock()
    defer configWriteLock.Unlock()

    fullFileName := filepath.Join(wavebase.GetWaveConfigDir(), fileName)
    barr, err := jsonMarshalConfigInOrder(m)
    if err != nil {
        return err
    }
    return fileutil.AtomicWriteFile(fullFileName, barr, 0644)
}
```

<!-- START COPILOT CODING AGENT TIPS -->
---

🔒 GitHub Advanced Security automatically protects Copilot coding agent
pull requests. You can protect all pull requests by enabling Advanced
Security for your repositories. [Learn more about Advanced
Security.](https://gh.io/cca-advanced-security)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
2026-02-27 15:43:37 -08:00
Mike Sawka
e8ebe88651
Fix for Claude Code Scroll to Top Bug (#2956)
There may be more cases here that I don't know about, but this fixes a
good chunk of them. This catches the CC "repaint" transaction and forces
a scrollToBottom. That should handle context repaints and resize
repaints.

Also adds a new (hidden) terminal escape sequence debugger, and (in dev
mode) adds a last 50 writes cache that can be used to look at and debug
output.
2026-02-27 15:34:35 -08:00
Mike Sawka
1ab58ea98a
Fix bugs with connection switching (#2957)
* Add per blockId mutex to block controller resync
* Pass initial termsize through to startJob
2026-02-27 15:23:55 -08:00
Copilot
b2f3129aa0
Add wsh debugterm (#2947)
`wsh debugterm` currently decodes terminal bytes sourced from backend
block files. This extends it with a stdin-driven path so FE-emitted
payloads like `["...", "..."]` can be decoded directly without requiring
block lookup/RPC in that mode.

- **CLI surface**
  - Added new mode: `--mode stdin`
  - Updated mode help text to: `hex`, `decode`, `stdin`
  - Centralized mode validation via `getDebugTermMode()`

- **Execution path split**
  - Added mode-aware pre-run (`debugTermPreRun`):
    - `stdin` mode: skips RPC setup
    - `hex`/`decode`: keeps existing RPC setup behavior
  - `stdin` mode now:
    - reads all stdin
    - parses JSON as `[]string`
    - concatenates entries and runs existing decode formatter

- **Parsing support**
  - Added `parseDebugTermStdinData([]byte) ([]byte, error)`
  - Error messaging explicitly requires a JSON array of strings

- **Tests**
  - Added focused coverage for:
    - valid stdin JSON array parsing + decoded output
    - invalid stdin JSON input

```go
stdinData, _ := io.ReadAll(WrappedStdin)
termData, err := parseDebugTermStdinData(stdinData) // expects []string JSON
if err != nil { return err }
WriteStdout("%s", formatDebugTermDecode(termData))
```

<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/wavetermdev/waveterm/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
Co-authored-by: sawka <mike@commandline.dev>
2026-02-27 10:24:26 -08:00
Copilot
f1e06c7ef9
Add groq AI mode provider defaults and docs (#2942)
This change adds first-class `groq` provider support to Wave AI mode
resolution and documents it in the Wave AI modes guide. Users can now
configure Groq modes via `ai:provider` with provider defaults applied
automatically.

- **Provider support in backend config resolution**
  - Added `groq` as a recognized AI provider constant.
  - Added Groq provider defaults in mode resolution:
    - `ai:apitype`: `openai-chat`
    - `ai:endpoint`: `https://api.groq.com/openai/v1/chat/completions`
    - `ai:apitokensecretname`: `GROQ_KEY`

- **Schema/config surface update**
- Extended `AIModeConfigType` provider enum to include `groq`, so
`ai:provider: "groq"` is valid in Wave AI config.

- **Documentation updates (`waveai-modes.mdx`)**
  - Added `groq` to supported providers.
- Added a Groq-specific configuration example and default behavior
notes.
  - Updated provider reference and capability guidance to include Groq.

- **Focused coverage**
- Added a targeted unit test for Groq provider default application in
`applyProviderDefaults`.

```json
{
  "groq-kimi-k2": {
    "display:name": "Groq - Kimi K2",
    "ai:provider": "groq",
    "ai:model": "moonshotai/kimi-k2-instruct"
  }
}
```

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
2026-02-26 09:50:05 -08:00
Copilot
ed7fa40300
Refine RemoteFileMultiInfoCommand semantics: dedup inputs, per-path stat errors, and cancellation (#2935)
This follow-up tightens the new multi-file remote stat RPC behavior to
match expected usage: duplicate input paths are skipped, per-path stat
failures no longer fail the entire call, and cancellation is respected
during iteration.

- **RPC response model**
  - Added `staterror` to `FileInfo`:
    - `StatError string \`json:"staterror,omitempty"\``
  - Generated TS type now exposes `staterror?: string` on `FileInfo`.

- **`RemoteFileMultiInfoCommand` behavior updates**
- **Dedup:** if an input path key is already present in the result map,
the loop continues.
- **Non-fatal stat failures:** on `fileInfoInternal` error, the command
now emits a `FileInfo` entry for that input with:
    - resolved `path`, `dir`, `name`
    - `staterror` populated with `err.Error()`
    - continues processing remaining paths.
- **Cancellation:** checks `ctx.Err()` at the top of each iteration and
returns immediately if canceled.

- **PR scope cleanup**
  - Removed the previously added test file from this PR per request.

```go
if _, found := rtn[path]; found {
    continue
}
if ctx.Err() != nil {
    return nil, ctx.Err()
}
fileInfo, err := impl.fileInfoInternal(cleanedPath, false)
if err != nil {
    rtn[path] = wshrpc.FileInfo{
        Path:      wavebase.ReplaceHomeDir(cleanedPath),
        Dir:       computeDirPart(cleanedPath),
        Name:      filepath.Base(cleanedPath),
        StatError: err.Error(),
    }
    continue
}
```

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
2026-02-25 12:52:50 -08:00
Copilot
624476fa33
Add terminal cursor style/blink config with block-level overrides (#2933)
Adds support for configuring terminal cursor style and blink behavior in
terminal blocks, with hierarchical resolution (block metadata →
connection overrides → global settings). New keys are `term:cursor`
(`block`/`underline`/`bar`, default `block`) and `term:cursorblink`
(`bool`, default `false`).

- **Config surface: new terminal keys**
  - Added to global settings schema/types:
    - `pkg/wconfig/settingsconfig.go`
  - Added to block metadata typing:
    - `pkg/waveobj/wtypemeta.go`
  - Added default values:
    - `pkg/wconfig/defaultconfig/settings.json`
      - `"term:cursor": "block"`
      - `"term:cursorblink": false`

- **Frontend terminal behavior (xterm options)**
  - `frontend/app/view/term/termwrap.ts`
- Added `setCursorStyle()` with value normalization (`underline`/`bar`
else fallback `block`)
    - Added `setCursorBlink()`
- Applies both options on terminal construction via
`getOverrideConfigAtom(...)`
  - `frontend/app/view/term/term-model.ts`
    - Subscribes to `term:cursor` and `term:cursorblink` override atoms
- Propagates live updates to `term.options.cursorStyle` /
`term.options.cursorBlink`
    - Cleans up subscriptions in `dispose()`

- **Generated artifacts**
  - Regenerated config/type outputs after Go type additions:
    - `schema/settings.json`
    - `pkg/wconfig/metaconsts.go`
    - `pkg/waveobj/metaconsts.go`
    - `frontend/types/gotypes.d.ts`

- **Docs**
  - Updated config reference and default config example:
    - `docs/docs/config.mdx`

```ts
// termwrap.ts
this.setCursorStyle(globalStore.get(getOverrideConfigAtom(this.blockId, "term:cursor")));
this.setCursorBlink(globalStore.get(getOverrideConfigAtom(this.blockId, "term:cursorblink")) ?? false);

// term-model.ts (live updates)
const termCursorAtom = getOverrideConfigAtom(blockId, "term:cursor");
this.termCursorUnsubFn = globalStore.sub(termCursorAtom, () => {
    this.termRef.current?.setCursorStyle(globalStore.get(termCursorAtom));
});
```

<!-- START COPILOT CODING AGENT TIPS -->
---

🔒 GitHub Advanced Security automatically protects Copilot coding agent
pull requests. You can protect all pull requests by enabling Advanced
Security for your repositories. [Learn more about Advanced
Security.](https://gh.io/cca-advanced-security)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sawka <2722291+sawka@users.noreply.github.com>
Co-authored-by: sawka <mike@commandline.dev>
2026-02-25 12:40:20 -08:00
Mike Sawka
752265fed7
add a preview component for tabs, update contextmenu model w/ getInstance method (#2927) 2026-02-25 12:39:07 -08:00
Mike Sawka
110e2b90a1
update eslint to v9 (and fix all eslint errors) (#2923) 2026-02-23 18:42:17 -08:00