Commit Graph
31 Commits
Author SHA1 Message Date
Kaede Akino 7bbfeb79e2 Bulk iOS 2026-09-11 21:07:44 +08:00
Kaede Akino 1b835a5df4 Continue iOS port with shared settings and Metrics 2026-09-11 15:12:37 +08:00
Kaede Akino c2958a05b3 Add iOS workspaces and shared feature services
Share Vault, persistence, SSH/SFTP, forwarding, and SwiftUI components across platforms. Add mobile editors, terminal input, standalone Assistant, Metrics navigation, transfers, and a unified Live Activity with host system icons.

Validation: 35 iOS tests and 100 focused macOS tests pass; formatting and zh-Hans checks pass. The full macOS run reports 14 issues in the documented timing, Keychain, and popover suites. Remaining Assistant tool and CloudKit work is tracked in Memory/MOBILE_ROLLOUT.md.
2026-09-11 13:47:16 +08:00
Kaede Akino 66890792b8 Split macOS and iOS targets into shared frameworks 2026-09-11 10:59:38 +08:00
Kaede Akino 6b3be99f48 Fix screenshot 2026-09-11 02:02:04 +08:00
Kaede Akino 656b0f20d0 Add App Store review link and automatic invitations 2026-09-11 00:46:59 +08:00
Kaede Akino cea1020bff Remove low-value test assertions 2026-09-11 00:25:32 +08:00
Kaede Akino afa77ae16a Add Known Hosts manager and SSH folder import 2026-09-11 00:00:38 +08:00
Kaede Akino f0fdcf4ddb Sync Vault and settings across devices 2026-09-10 23:15:25 +08:00
Kaede Akino 526f8bdf07 Add get_metrics tool for Agent and MCP 2026-09-10 22:20:57 +08:00
Kaede Akino 3e0479f573 Refresh focused screenshots and showcase server metrics 2026-09-10 22:03:09 +08:00
Kaede Akino 7caf70f5eb Add server metrics and menu bar monitoring 2026-09-10 20:47:35 +08:00
Kaede Akino e2490285c9 Remove unused Show Recents setting 2026-09-09 20:46:57 +08:00
Kaede Akino 2afc70a285 Normalize fetched model types with AgentKit 0.6.0 2026-09-09 17:14:19 +08:00
Kaede Akino d8b12d98af Add theme selector 2026-09-09 11:47:18 +08:00
Kaede Akino 6a912cc5d0 Fix App Icon 2026-09-09 11:34:51 +08:00
Kaede Akino 3511bf963a Refactor free trial 2026-09-09 01:20:42 +08:00
Kaede Akino dd30b19391 Fix apple speech crash 2026-09-06 19:31:45 +08:00
Kaede AkinoandClaude Opus 5 ea3aae9b52 Address a provider by one URL and one API type
The API Type picker named three vendors — OpenAI, Anthropic, Google — for
four wire protocols, so `.openAI` carried a Responses toggle to express the
fourth. Each kind also carried a default base URL, which the editor printed
as the Base URL placeholder, so `api.openai.com` was on screen for anyone
who had added a provider and typed nothing, and a provider with a key but no
address quietly resolved to a vendor endpoint nobody had named.

The picker now names the protocol: Automatic, Chat Completions, Responses,
Messages, generateContent. Automatic reads the protocol off the URL's own
suffix and falls back to Chat Completions when nothing matches, which is
what an endpoint that does not name itself is almost always serving.

Base URL and API Path collapse into one field. Splitting them made "does the
base URL include /v1" a question the user had to answer, and it is the
question every client of this shape gets wrong. Paste whatever the gateway's
documentation printed, at whatever depth it printed it; the two captions
underneath say what that produced — Full URL is read from the same value the
request is built from, and the line under it names the body shape, which is
how Automatic explains its own answer and how an explicit pick that
disagrees with the URL stops being a silent surprise. An explicit pick moves
the format, never the address: the person who pasted it keeps it.

Vertex AI goes with the vendor names. It stays in AgentKit, which is an
independent package and does not carry this app's constraints, but nothing
here drives it any more — the editor's project, location and service-account
import are gone, along with five persisted columns and their Keychain path.

`ProviderEndpoint` holds the two things the editor owns, the typed URL and
the picked type, because neither survives a round trip through the composed
result: a URL ending in /messages looks the same whether it was typed or
appended, and Automatic looks the same as picking the format it resolved to.
`AIConfigurationModel.setEndpoint` is the only writer of the derived
`inferenceURL`, `baseURL` and `apiFormat`.

Old rows fold back to the address they used to resolve to rather than to
Automatic, so a provider that worked before the change points at the same
place after it. That fold needs the pre-V12 columns, which is why `kind`,
`baseURL`, `apiPath` and `usesResponsesAPI` are still declared, and it needs
V11 frozen: every VersionedSchema in the plan points at live model types, so
editing a persisted model rewrites what the old version *means* and leaves
an installed store recording a version the plan no longer contains. That is
a refusal to open, not a migration. `TermindSchemaV11Models` is what gives
V11 to V12 two sides — any future attribute change needs the same freeze.

Requires AgentKit 0.5.0, where `ModelAPIFormat` replaces `ModelProviderKind`
and a provider carries `inferenceURL` and `baseURL` instead of a kind, a
base and a path.

Verified with the full test suite (994 tests, including the new
ProviderEndpointTests), swift-format lint --strict,
Scripts/check-zh-localization.sh, npm run build, and a launch of the app
against an existing V11 store.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 11:33:34 +08:00
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