Commit Graph
12 Commits
Author SHA1 Message Date
Kaede AkinoandClaude Opus 5 9bd2401a5c Add Open at Login
Settings › App › Startup gains an Open at Login switch backed by
SMAppService.mainApp, and an Open Hidden at Login switch that keeps the
login launch from taking the screen. Both are off by default.

The registration is not mirrored into preferences. SMAppService is the
store for whether Termind opens at login: the user can revoke it in
System Settings without telling the app, so the switch re-reads the
system status on appear and on every window activation. requiresApproval
counts as on, with a row saying what is outstanding and a button into
Login Items, rather than a switch that quietly refuses to hold.

Hidden means NSApp.hide(nil) rather than a suppressed window, because
Termind terminates with its last window. LoginLaunch latches the launch
Apple Event during applicationWillFinishLaunching, the only moment
currentAppleEvent can still be read; the hide is armed a second time for
the window SwiftUI orders front just afterwards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 19:07:54 +08:00
Kaede AkinoandClaude Opus 5 b13c87cbe8 Move splits and Workspace navigation off keys macOS already owns
Split Right held ⌥⌘D, which macOS reserves system-wide for Turn Dock
Hiding On/Off as symbolic hotkey 52. The system consumed the event
before the menu saw it, so the command was unreachable from the
keyboard and pressing it only hid the Dock. It and Split Down move to
⌥⌘→ and ⌥⌘↓, the directions they name. ⌥ still marks the pair that only
rearranges the window, against Duplicate's ⌘D, which opens a
connection.

Next Workspace and Previous Workspace held ⌃⇥ and ⌃⇧⇥. The app never
sets `allowsAutomaticWindowTabbing` to false, so AppKit installs its own
Show Next Tab ⌃⇥ and Show Previous Tab ⌃⇧⇥ into the same Window menu
and shadows both.

Those two were also exact duplicates. `Show Next Workspace` invoked the
same `selectNext()` as `Next Workspace`, and the Previous pair likewise
— four buttons for two actions, where the shadowed pair held the better
titles. The Window menu keeps one pair on ⇧⌘] / ⇧⌘[, which is what
Safari, Terminal and Finder use, under the names Next Workspace and
Previous Workspace. Both already carried finished zh-Hans, so no new
translation was needed and the two orphaned catalog entries are gone.

`AppShortcutKey` gains `.rightArrow` and `.downArrow`. They match on key
code rather than character, as `.tab` and `.escape` do, because that is
what lets `AppShortcutRegistry.routesToApplication` recognise ⌥⌘→ inside
the terminal's `performKeyEquivalent` and decline it — otherwise Ghostty
encodes the arrow and writes an escape sequence to the shell.
`registeredApplicationShortcutsFallThroughTheTerminal` now covers both.

Verification: build succeeds, 975 of 975 tests pass, and
`swift-format lint --strict` and check-zh-localization.sh are clean. The
menu bar itself was not driven: osascript has no assistive access here,
so rendering of ⌥⌘→ and a live keypress inside a focused terminal remain
unchecked by hand.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 18:34:43 +08:00
Kaede Akino cdd8fe0668 Extract the agent runtime as AgentKit
The loop, the approval gate, the provider adapters, the MCP client, and the
tools with no opinion about transports now live in a package and are consumed
from it. Termind keeps everything that reaches a machine or a person: the SSH
and SFTP tools, the connection pool, the Vault resolver, scratch_pull and
scratch_push, the SwiftData store, and every view.

They meet at four seams. TermindAgentTools registers our tools alongside the
built-in groups; AgentToolServices carries the SSH credential prompt to them
without that prompt appearing in a runtime protocol; TermindAgentPolicy owns the
system prompt, the plan contract, and the ssh_exec plan-mode rule the runtime
cannot write for us; TermindAgentPresentation extends the card vocabulary with
our own semantics.

ChatPermissionMode becomes AgentPermissionMode and moves out of the conversation
model — who authorizes an action is a property of the run, not of a view.
AgentRunRequest takes the session context as rendered text rather than our
SessionContext, because the runtime does nothing with it but insert it in front
of the turn it describes.

Termind's system prompt and plan contract are byte-identical to what shipped.
Every provider cache is a prefix cache, so editing a word there would miss the
cache on every replayed conversation at once.
2026-09-02 13:58:35 +08:00
Kaede Akino f159082299 Add Agent Skill 2026-09-02 11:08:38 +08:00
Kaede Akino 9e1264455e refactor 2026-09-02 09:57:52 +08:00
Kaede Akino 9309a425d3 Reduce redundant production and copy test logic 2026-09-02 09:34:35 +08:00
Kaede Akino dc4bd34414 Add review mode and remove developer pro 2026-09-01 23:27:58 +08:00
Kaede Akino 2f96b5a75a Fix Shell Integration 2026-09-01 10:47:13 +08:00
Kaede Akino f125f72070 Refine Shell Integration 2026-08-31 21:57:54 +08:00
Kaede Akino 0dc80b76e0 refactor settings 2026-08-30 15:46:42 +08:00
Kaede Akino d8d20a3548 refactor: reduce duplicated Swift code 2026-08-30 11:54:48 +08:00
Kaede Akino aff71e4585 refactor 2026-08-30 02:55:48 +08:00