diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index ee7ad59..f507427 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -37,8 +37,8 @@ jobs: sed -i "s/\"version\": \"[0-9]*\.[0-9]*\.[0-9]*\"/\"version\": \"$VERSION\"/" src-tauri/tauri.conf.json # src-tauri/Cargo.toml sed -i "s/^version = \"[0-9]*\.[0-9]*\.[0-9]*\"/version = \"$VERSION\"/" src-tauri/Cargo.toml - # src-tauri/Cargo.lock (the coffee-note package entry) - sed -i "0,/^name = \"coffee-note\"/{/^name = \"coffee-note\"/{n; s/version = \"[0-9]*\.[0-9]*\.[0-9]*\"/version = \"$VERSION\"/}}" src-tauri/Cargo.lock + # src-tauri/Cargo.lock (the tiernote package entry) + sed -i "0,/^name = \"tiernote\"/{/^name = \"tiernote\"/{n; s/version = \"[0-9]*\.[0-9]*\.[0-9]*\"/version = \"$VERSION\"/}}" src-tauri/Cargo.lock # website/version.json (drives the installer's update check) echo "{\"version\": \"$VERSION\"}" > website/version.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ab575c0..cdafc67 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -98,12 +98,12 @@ jobs: if [ -z "$ID" ]; then ID=$(gh api --method POST "repos/${REPO}/releases" \ -f tag_name="${TAG}" \ - -f name="Coffee Note ${TAG}" \ - -f body="Coffee Note ${TAG#v} + -f name="TierNote ${TAG}" \ + -f body="TierNote ${TAG#v} This release includes the changes recorded in the repository history since the previous version. - Coffee Note is a local-first desktop workspace for organizing notes, priorities, and AI-assisted work, with Windows, macOS, and Linux builds. + TierNote is a local-first desktop workspace for organizing notes, priorities, and AI-assisted work, with Windows, macOS, and Linux builds. These binaries are not code-signed. Your operating system may display an unverified-developer warning." \ -F draft=true \ @@ -218,16 +218,16 @@ jobs: --jq '.[] | "\(.id)\t\(.name)"' \ | while IFS=$'\t' read -r ID NAME; do case "$NAME" in - *_x64-setup.exe) NEW="Coffee.Note_${VERSION}_Windows_x64-setup.exe" ;; - *_x64_*.msi|*_x64.msi) NEW="Coffee.Note_${VERSION}_Windows_x64.msi" ;; - *_aarch64.dmg) NEW="Coffee.Note_${VERSION}_macOS_arm64.dmg" ;; - *_x64.dmg) NEW="Coffee.Note_${VERSION}_macOS_x64.dmg" ;; - *_amd64.deb) NEW="Coffee.Note_${VERSION}_Linux_x64.deb" ;; - *.x86_64.rpm) NEW="Coffee.Note_${VERSION}_Linux_x64.rpm" ;; - *_arm64.deb) NEW="Coffee.Note_${VERSION}_Linux_arm64.deb" ;; - *.aarch64.rpm) NEW="Coffee.Note_${VERSION}_Linux_arm64.rpm" ;; + *_x64-setup.exe) NEW="TierNote_${VERSION}_Windows_x64-setup.exe" ;; + *_x64_*.msi|*_x64.msi) NEW="TierNote_${VERSION}_Windows_x64.msi" ;; + *_aarch64.dmg) NEW="TierNote_${VERSION}_macOS_arm64.dmg" ;; + *_x64.dmg) NEW="TierNote_${VERSION}_macOS_x64.dmg" ;; + *_amd64.deb) NEW="TierNote_${VERSION}_Linux_x64.deb" ;; + *.x86_64.rpm) NEW="TierNote_${VERSION}_Linux_x64.rpm" ;; + *_arm64.deb) NEW="TierNote_${VERSION}_Linux_arm64.deb" ;; + *.aarch64.rpm) NEW="TierNote_${VERSION}_Linux_arm64.rpm" ;; *_amd64.AppImage|*_x86_64.AppImage) - NEW="Coffee.Note_${VERSION}_Linux_x64.AppImage" ;; + NEW="TierNote_${VERSION}_Linux_x64.AppImage" ;; *) NEW="" ;; esac diff --git a/AGENTS.md b/AGENTS.md index 2e5c6b2..2445046 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,10 +1,12 @@ -# Coffee Note agent notes +# TierNote agent notes -Coffee Note is a sister product forked from the original longevity app. Its visible -product name is **Coffee Note**. The repository directory uses `Coffee-Note`; -internal package names, storage keys, and identifiers use `coffee-note` or -`CoffeeNote` where spaces are invalid; the reverse-domain bundle identifier is -`app.coffeenote.desktop`. +TierNote is a sister product forked from the original longevity app. Its visible +product name is **TierNote**. The repository directory and developer package +names use `TierNote` or `tiernote`. Persisted v0.1.8 identifiers intentionally +remain `app.coffeenote.desktop`, the `Coffee Note` app-data directory, +`.coffee-note` workspace metadata, and `coffee-note:` browser storage keys so +existing users keep their local data after upgrading. Do not rename those +legacy identifiers without an explicit, tested migration. The copied longevity content is transitional and will be replaced with a clean, general-purpose note model. The homepage tier list remains the core experience. diff --git a/CODEX_HANDOFF.md b/CODEX_HANDOFF.md index f2d334b..45c18d5 100644 --- a/CODEX_HANDOFF.md +++ b/CODEX_HANDOFF.md @@ -1,4 +1,4 @@ -# Coffee Note — portable Codex project memory +# TierNote — portable Codex project memory Updated: 2026-08-15 @@ -6,22 +6,24 @@ This file preserves the decisions and working context needed to continue the project on another machine. It contains no API keys, private user parameters, or temporary deployment credentials. -## Coffee Note fork status +## TierNote fork status -- This repository is the Coffee Note sister product forked from the original longevity app. -- Visible product name: **Coffee Note**. -- The repository directory is `Coffee-Note`; internal identifiers use `coffee-note` - or `CoffeeNote` where spaces are invalid, with `app.coffeenote.desktop` as the - reverse-domain bundle identifier. -- Coffee Note is a local-first, general-purpose workspace agent rather than a +- This repository is the TierNote sister product forked from the original longevity app. +- Visible product name: **TierNote**. +- The repository directory is `TierNote`; developer package names use `tiernote` + or `TierNote` where spaces are invalid. +- TierNote is a local-first, general-purpose workspace agent rather than a fixed note system or a longevity product. The user selects an ordinary directory and asks the Agent to work in it. Notes are common work, but source code, documents, data, and other tasks are equally valid. -- Coffee Note uses a clean application identity with no predecessor-brand - compatibility layer: `app.coffeenote.desktop`, `Coffee Note` app-data, - `.coffee-note` knowledge metadata, and `coffee-note:` browser storage keys. -- GitHub release and feedback URLs use the `edison7009/Coffee-Note` repository. -- **Licensing (2026-08-19):** Coffee Note uses AGPL-3.0-or-later for current +- The TierNote rebrand preserves the v0.1.8 persisted identity as a compatibility + layer: `app.coffeenote.desktop`, the `Coffee Note` app-data directory, + `.coffee-note` workspace metadata, and `coffee-note:` browser storage keys. + These legacy identifiers keep provider credentials, conversations, plugin state, + message channels, and tier ordering available after upgrade and must not be + renamed without an explicit, tested migration. +- GitHub release and feedback URLs use the `edison7009/TierNote` repository. +- **Licensing (2026-08-19):** TierNote uses AGPL-3.0-or-later for current releases, with paid commercial licensing available for closed-source customization, white-label distribution, and proprietary embedding. Copies released before the transition retain the MIT permissions already granted; @@ -31,7 +33,7 @@ or temporary deployment credentials. - The homepage editable T1–T5 tier list is the core interaction model because it makes prioritization and decisions immediately legible. - Longevity-specific starter content and product copy below are inherited context - awaiting replacement; they are not the Coffee Note product direction. + awaiting replacement; they are not the TierNote product direction. ## Workspace Agent foundation (2026-08-15) @@ -47,7 +49,7 @@ or temporary deployment credentials. - The selected directory is the workspace. It may be a code repository, writing project, note collection, or any other folder. Never infer a required note hierarchy and never create `inbox`, `dossiers`, or another category directory - merely because Coffee Note is the visible product name. + merely because TierNote is the visible product name. - The Agent must accept programming, debugging, writing, research, organization, and other workspace tasks. It must not refuse work simply because the request is programming or not note-related. @@ -59,7 +61,7 @@ or temporary deployment credentials. `save_note` defaults to the workspace root and uses a subdirectory only when the user explicitly asks or the existing workspace makes that destination clear. - The directory tree must not hide or offer bulk deletion of folders based on old - Coffee Note category names. A folder named `papers`, `templates`, `inbox`, or + TierNote category names. A folder named `papers`, `templates`, `inbox`, or similar may be ordinary user project data. - **Complete workspace file tree (2026-08-19):** The directory tree shows every ordinary non-hidden file, not only Markdown. Markdown remains the only built-in @@ -77,18 +79,18 @@ or temporary deployment credentials. ## Desktop redesign direction (2026-08-07) -- **Plugin platform foundation (2026-08-17):** Coffee Note treats plugins as the +- **Plugin platform foundation (2026-08-17):** TierNote treats plugins as the install/update unit, skills as the Agent invocation unit, and runtimes as shared application-managed infrastructure. Settings > Plugins is the Plugin market; categories filter plugin types, while enabled and installed state lives on the package row and detail page instead of a separate Installed view. The bundled - `Coffee Media` package is the first manifest-driven + `TierNote Media` package is the first manifest-driven official plugin: its media-to-text skill, publisher, version, and prewarmed `media-transcription` runtime are declared under `src-tauri/builtin-plugins/coffee-media/` instead of being duplicated as a Rust prompt constant. Official plugins may bundle many independently switchable skills; a skill must never install its own runtime. Git skill packages remain supported as - prompt-only community extensions, and Coffee Note never automatically executes + prompt-only community extensions, and TierNote never automatically executes their scripts, hooks, MCP servers, or runtime declarations. - Plugin details expose the package and its independently switchable skills only. Publisher and runtime identifiers remain internal metadata. Plugin manifests and @@ -96,7 +98,7 @@ or temporary deployment credentials. application's normal workspace access. Disabling a built-in plugin or one of its skills removes the corresponding Agent tool and the backend rejects direct calls as a second guard. -- **Native presentation plugin (2026-08-17):** The bundled `Coffee Presentation` +- **Native presentation plugin (2026-08-17):** The bundled `TierNote Presentation` package lives under `src-tauri/builtin-plugins/coffee-presentation/`. Its `create-presentation` skill sends a complete structured deck to the shared, prewarmed `presentation-engine` runtime. The runtime is compiled into the desktop @@ -105,7 +107,7 @@ or temporary deployment credentials. business, and dark themes plus title, section, content, two-column, quote, and workspace-image layouts. Generated files use a new filename instead of silently overwriting an existing deck. -- **Native document plugin (2026-08-17):** The bundled `Coffee Documents` package +- **Native document plugin (2026-08-17):** The bundled `TierNote Documents` package lives under `src-tauri/builtin-plugins/coffee-documents/` and exposes independent `create-docx` and `create-pdf` skills on one prewarmed `document-engine`. Both submit a complete semantic block list to the guarded `create_document` tool. @@ -122,7 +124,7 @@ or temporary deployment credentials. image-capable active chat model remains the first choice for recognition; the recognition configuration is its fallback. Image-generation skills use the generation configuration. Video generation keeps an independent external-provider - record without replacing Coffee Video's native fallback. Its built-in service selector + record without replacing TierNote Video's native fallback. Its built-in service selector offers Runway plus direct BytePlus/Volcano Engine Seedance, Kling, Google Vertex AI Veo, MiniMax/Hailuo, Luma, Vidu, Pika, Alibaba Cloud Wan, Tencent Cloud Hunyuan/Youtu, Tencent-hosted PixVerse, LTX, Adobe Firefly, and @@ -149,7 +151,7 @@ or temporary deployment credentials. presentation tool by relative path. This version is cloud-only and does not expose an unfinished local OCR tab. - **Built-in storyboard director and text-to-video fallback (2026-08-17):** The bundled - `Coffee Video` package lives under `src-tauri/builtin-plugins/coffee-video/`. It exposes + `TierNote Video` package lives under `src-tauri/builtin-plugins/coffee-video/`. It exposes a storyboard-only director skill and a render skill; both receive the same bundled, model-neutral cinematic specification. They establish a director brief, beat map, continuity bible, motivated camera language, and paired keyframe/motion prompts before @@ -219,11 +221,11 @@ or temporary deployment credentials. skill directly to its generated turn and must not leave that skill selected in the composer afterward. - **Custom My Contexts (2026-08-14):** The action inside My Contexts is Add Context, - not Add Material. It creates a Markdown page in Coffee Note's dedicated local + not Add Material. It creates a Markdown page in TierNote's dedicated local My Contexts directory, immediately lists it on that page, and gives it the same default-on independent AI retrieval switch as the built-in context pages. General material creation remains available from the library controls outside My Contexts. -- **Local Agent Loop (2026-08-14):** Coffee Note uses its focused Rust ReAct +- **Local Agent Loop (2026-08-14):** TierNote uses its focused Rust ReAct loop as the only agent runtime. `agent_loop.rs` owns model streaming, tool orchestration, durable provider transcripts, token accounting, and local context compaction. Rust also owns Library Graph, My Contexts routing, note @@ -243,7 +245,7 @@ or temporary deployment credentials. Local availability fails closed when live resource status cannot be read; a saved selection alone must never make a partially installed local setup appear usable. - **Media environment prewarm (2026-08-14):** Media-to-text is a frequently reused - built-in capability. After launch, Coffee Note silently prepares the pinned media + built-in capability. After launch, TierNote silently prepares the pinned media fetcher in the current user's app-data directory, verifies and reuses an existing copy, and retries on the actual media request if background preparation failed. Startup and first-use preparation share one process-local lock so they never write @@ -252,7 +254,7 @@ or temporary deployment credentials. or repeatedly install the media-import environment. - **Windows local transcription compatibility (2026-08-15):** The pinned whisper.cpp Windows runtime normally selects its fastest CPU backend. If it exits immediately - after loading that backend, Coffee Note retries in an isolated temporary runtime + after loading that backend, TierNote retries in an isolated temporary runtime containing only the baseline `ggml-cpu-x64.dll`. This keeps optimized CPUs fast while covering machines that crash after selecting the Haswell backend. Failed attempts report the process status and diagnostics instead of treating the final successful @@ -309,7 +311,7 @@ or temporary deployment credentials. - The desktop app is moving to a calm, Codex-informed note-workspace style. This supersedes older instructions below that require a colorful dashboard shell or a blue-green gradient title bar. -- Coffee Note now uses a monochrome black, graphite, and gray shell with no selectable +- TierNote now uses a monochrome black, graphite, and gray shell with no selectable brand color. The homepage is the deliberate exception: its three entry cards and T1-T5 map use restrained category colors. Appearance settings keep system/light/dark modes and color schemes, while General owns language and other non-visual preferences. @@ -332,7 +334,7 @@ or temporary deployment credentials. the compact note priority button, and the menu's small tier swatches. The button keeps its matching tinted background unchanged on hover/open; menu hover and selection use one neutral background with no colored border or glow. -- The display brand uses the `Coffee Note` wordmark in the title bar and AI-chat +- The display brand uses the `TierNote` wordmark in the title bar and AI-chat empty state. The AI-chat empty state intentionally has no logo image. The in-app mark source is `src-tauri/icons/logo.png`, which must remain byte-identical to the copied UI source at `public/brand/logo-new.png`. @@ -368,12 +370,12 @@ or temporary deployment credentials. ## Legacy source-product context The remaining notes describe the source product and are retained temporarily so -the working behavior is not lost during migration. The Coffee Note rules above take +the working behavior is not lost during migration. The TierNote rules above take precedence whenever they conflict. ## Product identity -- Product name: **Coffee Note**. +- Product name: **TierNote**. - Chinese product name: **科学延寿**. Use **延寿** consistently in Chinese product, website, documentation, and starter-library copy; keep the previous product-domain term out of new copy. @@ -446,7 +448,7 @@ to the product template. - The left pane keeps its 210-380px product range. The right rail has no fixed maximum; it may expand until the center workspace reaches its 560px minimum. - The top title/drag bar spans the full window width. Its left side shows a - 16 x 16 product icon, the closed `Coffee Note` wordmark in the bundled `Lora` + 16 x 16 product icon, the closed `TierNote` wordmark in the bundled `Lora` bold-italic face, functional back/forward navigation, and File/Edit/Help menus. File keeps the library-switch action; the right edge of the Home navigation row also exposes the same action as a discoverable global folder icon, matching @@ -501,13 +503,13 @@ to the product template. regional token prices directly rather than converting through an exchange rate. Persist the preference locally under `coffee-note:currency`. - The composer skill picker and Settings > Skills share one source-backed - catalog. Adding a skill plugin asks only for a Git repository URL and a Coffee - Note category; package names, descriptions, versions, and skill instructions + catalog. Adding a skill plugin asks only for a Git repository URL and a TierNote + category; package names, descriptions, versions, and skill instructions are read from the repository's manifest and `SKILL.md` files and are never duplicated into editable app-owned copies. Repositories are cached once under the current user's app-data `skill-sources/` directory for offline use and updates. Selecting a skill reads its original `SKILL.md` and adds it only to - that AI request's prompt. Coffee Note does not execute third-party scripts, + that AI request's prompt. TierNote does not execute third-party scripts, hooks, runtimes, or MCP servers from these repositories. - Settings > Skills is a two-level skill management workspace. The category view lists installed skill packages/sources and keeps package update, move, removal, and @@ -524,7 +526,7 @@ to the product template. their plugin root, supported raster/SVG assets are size-limited, and shared icons are deduplicated in the catalog rather than repeated for every child. - Chat uses a minimal two-sided conversation layout: user messages are compact - bubbles aligned to the right, while Coffee Note answers remain readable, + bubbles aligned to the right, while TierNote answers remain readable, unframed content aligned to the left. Do not show participant names or avatars; message position already communicates the speaker. - Opening AI chat or switching conversations must position the message area at @@ -581,12 +583,12 @@ to the product template. another root immediately invalidates pending loads and mutations so an old root can never republish its snapshot over the new workspace. The frontend reloads after every Agent run so edits appear immediately. -- AI settings separate **provider** and **model**; wire protocol is derived. Coffee Note +- AI settings separate **provider** and **model**; wire protocol is derived. TierNote reads the public `https://models.dev/api.json` catalog for provider names, default OpenAI-compatible endpoints, models, capabilities, context limits, reasoning effort options, and USD pricing; provider marks come from `https://models.dev/logos/{provider}.svg`. The Rust backend caches the bounded, - validated catalog for 24 hours at `Coffee Note/models-dev-catalog.json` in the + validated catalog for 24 hours at `TierNote/models-dev-catalog.json` in the current user's app-data directory and falls back to that cache while offline. Provider UI uses the canonical models.dev display name only. Do not repeat the internal lowercase provider ID below the name; composer model choices also use @@ -597,7 +599,7 @@ to the product template. protocol. DeepSeek's default base URL is `https://api.deepseek.com`; the old mistaken `/anthropic` default is migrated automatically. Provider URL, API key, selected models, active model, derived protocol, and reasoning - effort persist in plaintext `Coffee Note/config.json` in app-data only. Existing + effort persist in plaintext `TierNote/config.json` in app-data only. Existing two-protocol configs migrate without discarding their URL, model, or key. In the provider directory, the default provider stays first and providers with selected models move directly below it; untouched catalog providers follow. @@ -624,7 +626,7 @@ to the product template. model remains in the explicit selected-model array; otherwise it reads Choose model. - The AI composer model menu and reasoning control are functional configuration, not previews. Model changes update the active provider/model immediately. - Every catalog-declared reasoning model exposes Coffee Note's fixed five choices: + Every catalog-declared reasoning model exposes TierNote's fixed five choices: `low`, `medium`, `high`, `xhigh`, and `max`. Do not filter or clamp these from models.dev `reasoning_options`; provider endpoints may normalize unsupported intermediate values themselves. Choices are sent as `reasoning_effort` for OpenAI-compatible Chat @@ -632,14 +634,14 @@ to the product template. catalog-declared reasoning capability show a non-interactive Standard readout and receive no guessed reasoning parameter. - Every outbound model request identifies the app to compatible upstreams with - `HTTP-Referer: https://note.coffeecli.com`, `X-OpenRouter-Title: Coffee Note`, and the - backward-compatible `X-Title: Coffee Note`. This attribution replaces any inherited + `HTTP-Referer: https://tiernote.org`, `X-OpenRouter-Title: TierNote`, and the + backward-compatible `X-Title: TierNote`. This attribution replaces any inherited EchoBird identity and applies to both streaming and synchronous OpenAI-compatible/Anthropic requests. -- The desktop app's Coffee Note brand link opens `https://note.coffeecli.com/`. Download and +- The desktop app's TierNote brand link opens `https://tiernote.org/`. Download and update endpoints remain separately configured until their hosting is migrated. - AI provider settings, including API keys, persist as plaintext JSON in the - current user's app-data directory (`Coffee Note/config.json`). They must + current user's app-data directory (`TierNote/config.json`). They must never be written into the repository or knowledge library. - Borderless modal headers share one text-only standard component. Use typography for hierarchy, never a decorative or category icon to the left of the title; @@ -689,17 +691,17 @@ to the product template. ## Website -- The public website is active again at `https://note.coffeecli.com/`. The +- The public website is active again at `https://tiernote.org/`. The single-page site under `website/` is independent from the desktop UI and keeps its own brand, copy, download routes, and screenshot assets. - Product screenshots are paired by locale. English and Simplified Chinese use matching desktop captures, and the in-place language switch updates both copy and screenshots. Other incomplete locales continue to fall back to English. -- Remote usage: `irm https://note.coffeecli.com/install.ps1 | iex`. The script +- Remote usage: `irm https://tiernote.org/install.ps1 | iex`. The script first tries the website's version/download routes and falls back to the latest GitHub Release asset, so it remains useful while the public site is offline or being rebuilt. -- Primary product URL: `https://note.coffeecli.com/`. +- Primary product URL: `https://tiernote.org/`. ## Architecture and important paths @@ -724,7 +726,7 @@ Prerequisites: Desktop: ```powershell -cd C:\Coffee-Note +cd C:\TierNote npm install npm run library:check npm run typecheck @@ -734,7 +736,7 @@ npm run tauri:dev Website: ```powershell -cd C:\Coffee-Note\website +cd C:\TierNote\website npx serve . ``` @@ -757,7 +759,7 @@ and machine-specific. The website itself has no generated build directory. ## Agent-logic optimization references (added 2026-08-07) -The AI-chat empty state advertises three capabilities that Coffee Note already +The AI-chat empty state advertises three capabilities that TierNote already implements partially. When optimizing the agent loop later, borrow from these references: @@ -780,12 +782,12 @@ Make every token deliver at least twice the value.) ## Starter data ownership (2026-08-08) -The managed Demo library and My Info pages are starter data only. Coffee Note +The managed Demo library and My Info pages are starter data only. TierNote creates their bilingual seed content once, and then treats every file as user data. A permanent `.starter-pack-initialized` marker prevents later launches, upgrades, or starter-content revisions from overwriting or recreating edited or deleted files. When upgrading a pre-marker installation, any existing file means -the directory is adopted as-is; Coffee Note writes the marker without backfilling +the directory is adopted as-is; TierNote writes the marker without backfilling missing seed files. Current Chinese directory names and My Info section IDs are transitional implementation details, not permanent product contracts. @@ -799,7 +801,7 @@ its contents. The desktop Audio to text settings are backed by real app-data state rather than UI-only placeholders. Provider configuration is stored as plaintext JSON -at the current user's local app-data `Coffee Note/transcription.json`; it is never +at the current user's local app-data `TierNote/transcription.json`; it is never written into the repository or selected workspace. Provider records are kept independently so switching services does not discard their endpoint, model, or API key. The hosted path has separate request adapters for OpenAI-compatible, @@ -807,7 +809,7 @@ Deepgram, and AssemblyAI protocols and streams audio files instead of reading the whole upload into memory. The local path downloads pinned runtime and model resources into the current -user's local app-data `Coffee Note/transcription/` directory. Every fixed resource +user's local app-data `TierNote/transcription/` directory. Every fixed resource has an expected byte size and SHA-256 digest; archives are extracted only after verification. Windows supports the CPU and NVIDIA CUDA runtimes, Linux supports the CPU runtime, and macOS is intentionally shown as unavailable until a pinned @@ -826,9 +828,9 @@ selection is not implemented yet. ## Phone message channels (updated 2026-08-14) -Coffee Note supports two paired private phone channels: Tencent Weixin iLink +TierNote supports two paired private phone channels: Tencent Weixin iLink and Telegram Bot API. The Rust channel runtime stores credentials and a -durable task queue under the current user's local app-data `Coffee Note/` +durable task queue under the current user's local app-data `TierNote/` directory; neither credentials nor pending jobs enter the selected workspace. Weixin follows Tencent's MIT-licensed `openclaw-weixin` HTTP/JSON protocol for QR login, optional phone verification, long polling, `context_token` replies, @@ -862,7 +864,7 @@ is acknowledged and removed only after the final phone reply is delivered. evolve `knowledge_map.rs` into a persistent registry + backlinks + orphan/ broken-link lint + deterministic metadata rebuild after agent runs; measure token and tool-call savings. -3. **Phase 3 — Cache hit rate and cost**: keep the stable Coffee Note system +3. **Phase 3 — Cache hit rate and cost**: keep the stable TierNote system prompt small and compare provider-reported cache usage across model providers. 4. **Phase 4 — Evidence-retrieval self-healing routing**: primary/fallback endpoints for Europe PMC / PubMed / ClinicalTrials with @@ -871,10 +873,10 @@ is acknowledged and removed only after the final phone reply is delivered. ## Provider prefix-cache continuity (2026-08-10) AI conversations now have one UI transcript and one durable Agent Loop provider -transcript in Coffee Note. Conversation mutations still share one process-local +transcript in TierNote. Conversation mutations still share one process-local storage lock to protect UI JSON and its index. Cache usage remains the provider-reported aggregate. DeepSeek does not return -token attribution by prompt section, so Coffee Note must not claim a synthetic +token attribution by prompt section, so TierNote must not claim a synthetic rate that subtracts personal-context tokens. The composer labels this value `累计命中` / `Total cache` to make the cold-start-inclusive scope explicit. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 68ae9e1..90b9afa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -# Contributing to Coffee Note / 贡献指南 +# Contributing to TierNote / 贡献指南 -Thanks for helping improve Coffee Note. +Thanks for helping improve TierNote. ## English @@ -14,7 +14,7 @@ Thanks for helping improve Coffee Note. ### Contributor License Agreement (CLA) -Coffee Note is distributed under the **GNU Affero General Public License, +TierNote is distributed under the **GNU Affero General Public License, Version 3.0 or later (AGPL-3.0-or-later)**. The project may also offer paid commercial licenses for closed-source customization, white-label distribution, or proprietary embedding. To keep that licensing model possible, contributions @@ -25,7 +25,7 @@ translations, or other content (your "Contribution"), you agree that: 1. **Ownership.** You represent that you have the right to submit the Contribution and that it is not copied from an incompatibly licensed source. -2. **License grant.** You grant edison7009 and the Coffee Note project a +2. **License grant.** You grant edison7009 and the TierNote project a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license to reproduce, modify, publicly display, sublicense, and distribute the Contribution and derivative works under any license, including @@ -52,7 +52,7 @@ maintainer before submitting. ### 贡献者许可协议(CLA) -Coffee Note 采用 **GNU Affero 通用公共许可证 v3 或更高版本 +TierNote 采用 **GNU Affero 通用公共许可证 v3 或更高版本 (AGPL-3.0-or-later)**。项目也可能向需要闭源定制、白标分发或嵌入专有 产品的机构提供付费商业授权。为保留这种授权能力,贡献须遵守以下条款。 @@ -60,7 +60,7 @@ Coffee Note 采用 **GNU Affero 通用公共许可证 v3 或更高版本 即表示你同意: 1. **权属。** 你声明自己有权提交该贡献,且它并非复制自许可证不兼容的来源。 -2. **许可授予。** 你授予 edison7009 与 Coffee Note 项目一项永久、全球、 +2. **许可授予。** 你授予 edison7009 与 TierNote 项目一项永久、全球、 非独占、免版税、不可撤销的许可,可复制、修改、公开展示、再许可及分发 该贡献与其衍生作品,包括采用 AGPL-3.0-or-later 或商业专有许可证。 3. **专利授权。** 若实施贡献必然涉及你控制的专利权利要求,你向项目及下游 diff --git a/DESIGN.md b/DESIGN.md index 26cc649..92f32a8 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,4 +1,4 @@ -# Coffee Note Desktop Design System +# TierNote Desktop Design System ## Product Context @@ -23,7 +23,7 @@ controls and drag-and-drop content. Text fields keep the browser-native I-beam. The two pane resizers are the only resize-cursor exception: use `col-resize` both while hovering over a divider and throughout an active pane resize. -- **Mood:** Serious, quiet, capable, and spacious. Coffee Note should feel like a professional work surface, not a personalized dashboard template. +- **Mood:** Serious, quiet, capable, and spacious. TierNote should feel like a professional work surface, not a personalized dashboard template. - **Memorable quality:** A Codex-like note tool whose primary object is the user's tiered knowledge, not chat. ## Product Structure @@ -47,7 +47,7 @@ actions. Multi-word names remain intact and the row wraps only between cities; do not spend space on generic location-privacy helper copy. - Use one outer shell for the top bar and persistent left navigation rail. -- Let the shared title bar span the full window width. Place the `Coffee Note` wordmark at its left edge, followed by back/forward navigation and the File, Edit, and Help menus. On macOS, reserve clearance for native traffic-light controls. +- Let the shared title bar span the full window width. Place the `TierNote` wordmark at its left edge, followed by back/forward navigation and the File, Edit, and Help menus. On macOS, reserve clearance for native traffic-light controls. - Start the left rail below the title bar with Home as its first row. Do not repeat the product icon or wordmark there. Library switching remains in the File menu and is also exposed as a discoverable global-action icon at the right edge of the Home row, matching the placement of global actions such as search in Codex. - Leave a modest top inset above the Home row so the left rail breathes under the title bar rather than feeling pinned to it. - Place the center workspace and right contextual rail inside one continuous inner panel. Its top-left border and radius are the primary visual boundary; the right rail is not a second sidebar. @@ -86,7 +86,7 @@ endpoint, and locally saved API-key records. Recognition is a fallback when the active model cannot accept images; image, speech, video, music, and sound effects generation keep independent provider configurations for media-generation skills. Video configuration does not - replace Coffee Video's dependable native fallback. Video model presets are protocol-aware. + replace TierNote Video's dependable native fallback. Video model presets are protocol-aware. Runway exposes its current supported video IDs, while BytePlus/Volcano Engine, Kling, Vertex AI Veo, MiniMax/Hailuo, Luma, Vidu, Pika, Alibaba Cloud Wan, Tencent Cloud Hunyuan/Youtu and PixVerse, LTX, Adobe Firefly, and OpenAI Sora each keep a distinct @@ -156,7 +156,7 @@ never remove or hide a locally saved model, including one newly marked deprecated upstream. The AI composer exposes only models selected here. Every reasoning-capable - model gets Coffee Note's fixed five effort levels (low, medium, high, xhigh, max); + model gets TierNote's fixed five effort levels (low, medium, high, xhigh, max); models.dev reasoning-option metadata must not filter or clamp them. A provider's model list always expands in full inside the outer settings scroller; do not cap its result count or add a nested model-list scrollbar. Non-default providers show a count only when at @@ -183,7 +183,7 @@ chevron reveals arguments and results inline. While the turn is active, keep one separate EchoBird-style status line after the activity stream. Its left edge uses Coffee-CLI's compact Braille-dot spinner. - It uses Coffee Note's warm orange status color, the complete + It uses TierNote's warm orange status color, the complete supported-language verb lists, the left flower glyph sequence, typewriter erase/type timing, a caret during rewrites, and the EchoBird left-to-right text shimmer. Add an elapsed clock only after 15 seconds; the muted elapsed clock does not shimmer. @@ -236,7 +236,7 @@ the component; never shrink the type to fit. - **Weight:** Use 400 for body, 550-600 for controls and navigation, and 650-700 only for page titles. - **Letter spacing:** 0. Avoid uppercase tracking except tiny technical metadata. -- **Brand exception:** The compact title-bar `Coffee Note` wordmark reuses the bundled `Lora` bold-italic face from the AI-chat identity at 16px. +- **Brand exception:** The compact title-bar `TierNote` wordmark reuses the bundled `Lora` bold-italic face from the AI-chat identity at 16px. ## Color @@ -301,29 +301,29 @@ | 2026-08-07 | Keep website design separate | The public site is expressive brand communication; the desktop app is a repeated-use work surface. | | 2026-08-07 | Enforce a minimum type scale | Left navigation, directory tree, and right-rail text at 10-13px was too small to read. Floor: 13px readable / 12px metadata; 15px navigation (EchoBird reference), 14px directory tree. | | 2026-08-08 | Use the default arrow except for pane resizing | A hand cursor is a web pattern; ordinary controls and content keep the default arrow, while the dividers between the three panes use native directional feedback during resize. | -| 2026-08-08 | Move the product identity and app menus into the shared title bar | A compact 16 x 16 icon, Lora bold-italic `Coffee Note` wordmark, page history, and File/Edit/Help menus match the native Codex-like shell while letting Home align directly with the workspace top edge. | +| 2026-08-08 | Move the product identity and app menus into the shared title bar | A compact 16 x 16 icon, Lora bold-italic `TierNote` wordmark, page history, and File/Edit/Help menus match the native Codex-like shell while letting Home align directly with the workspace top edge. | | 2026-08-08 | Gate My Contexts retrieval per note | Five default-on local switches make AI inclusion explicit; a backend allowlist enforces the same state for question-aware and always-on personal context. Cards remain direct neutral navigation entries rather than selectable options. | | 2026-08-08 | Treat managed starter content as user-owned after first creation | Demo and My Contexts seed files are generated only for an empty first-run directory. A permanent marker prevents upgrades from overwriting, backfilling, or recreating edited and deleted files; current localized names remain temporary. | | 2026-08-09 | Replace the settings dialog with a global settings workspace | A persistent category rail and one merged content surface match the desktop shell, remove the dated modal feel, and give model and appearance settings room to remain legible. Library switching remains with Home and File. | -| 2026-08-09 | Use models.dev for provider/model directory data; keep Coffee Note request configuration independent | A live catalog removes hard-coded model names and prices. Anthropic alone uses its native Messages API; every other provider uses the industry-default OpenAI-compatible path. Coffee Note always exposes five reasoning levels for reasoning models and lets provider endpoints normalize them. Composer selections change actual requests. | +| 2026-08-09 | Use models.dev for provider/model directory data; keep TierNote request configuration independent | A live catalog removes hard-coded model names and prices. Anthropic alone uses its native Messages API; every other provider uses the industry-default OpenAI-compatible path. TierNote always exposes five reasoning levels for reasoning models and lets provider endpoints normalize them. Composer selections change actual requests. | | 2026-08-09 | Add ambient weather beside the Home greeting | Home keeps only a quiet animated condition image; its click panel is a read-only current and multi-day forecast with a compact single-line city header. City selection is explicit, local, and replaceable, while Home remains quiet. | | 2026-08-19 | Split General and Appearance settings | General owns language, generated-file location, and the local weather city. Appearance owns system/light/dark mode and color schemes. The Home weather gear and empty state therefore direct people to Settings > General. | -| 2026-08-19 | Show the complete workspace file tree | Ordinary non-hidden files of every format appear in the directory tree. Markdown opens in Coffee Note; other formats show a quiet unsupported-preview state but remain selectable through single click, multi-select, and the context menu as path-based AI context. | -| 2026-08-14 | Make paired phone chats full Coffee Note conversations | A linked private chat should behave like the desktop composer rather than force every message through link capture. Ordinary messages get ordinary AI replies, link-only messages implicitly become saved notes, and all turns share the local conversation history visible in the desktop rail. Pairing, credentials, cursors, and recoverable jobs remain local. | +| 2026-08-19 | Show the complete workspace file tree | Ordinary non-hidden files of every format appear in the directory tree. Markdown opens in TierNote; other formats show a quiet unsupported-preview state but remain selectable through single click, multi-select, and the context menu as path-based AI context. | +| 2026-08-14 | Make paired phone chats full TierNote conversations | A linked private chat should behave like the desktop composer rather than force every message through link capture. Ordinary messages get ordinary AI replies, link-only messages implicitly become saved notes, and all turns share the local conversation history visible in the desktop rail. Pairing, credentials, cursors, and recoverable jobs remain local. | | 2026-08-14 | Adopt a restrained turn-status shimmer | One theme-colored activity line with a left-to-right text shimmer and delayed static elapsed time replaces the repeated Braille spinner; tool rows and conversation history keep static marks. | | 2026-08-15 | Remove leading icons from borderless modal headers | Text-only titles make the lightweight dialogs quieter and more refined while one shared header keeps title and close-action alignment consistent. | | 2026-08-16 | Treat Skills as two-level management | The first level manages installed packages and source actions; opening a package reveals an uncapped two-column list of its concrete skills with independent switches and a clear back action. This separates installation from capability control and remains usable for repositories containing hundreds of skills without implying an in-app download marketplace. | | 2026-08-16 | Preserve official plugin artwork in Skills | Package and child-skill rows use the nearest Codex plugin manifest's compact icon directly, without a second backing tile or border, and fall back to the standalone neutral skill mark. This makes large official collections scannable without adding labels or card decoration. | | 2026-08-16 | Make Tier drag channels geometrically continuous | Visual spacing remains airy, but every wrapped line is divided at card center lines so each pixel maps to a deterministic insertion slot. A gap must never fall through to the row-end position. | -| 2026-08-17 | Establish the plugin-market architecture | Plugins are distribution units, skills are Agent actions, and shared runtimes are managed once by the application. Coffee Media is the first manifest-driven official plugin; Git skill sources remain prompt-only community extensions. | -| 2026-08-17 | Generate presentations in the shared native runtime | Coffee Presentation submits one structured deck to an application-level engine that creates editable `.pptx` files without a per-skill environment. The initial layout and density contract favors reliable, restrained slides over unconstrained drawing commands. | +| 2026-08-17 | Establish the plugin-market architecture | Plugins are distribution units, skills are Agent actions, and shared runtimes are managed once by the application. TierNote Media is the first manifest-driven official plugin; Git skill sources remain prompt-only community extensions. | +| 2026-08-17 | Generate presentations in the shared native runtime | TierNote Presentation submits one structured deck to an application-level engine that creates editable `.pptx` files without a per-skill environment. The initial layout and density contract favors reliable, restrained slides over unconstrained drawing commands. | | 2026-08-17 | Separate recognition and generation providers | Keep one Multimodal models destination with compact internal capability tabs. Recognition falls back to its own external image model when the active model is text-only; image, speech, video, and music generation use independently configured providers. Local OCR remains a later capability. | -| 2026-08-17 | Ship Coffee Video as the safe fallback video workflow | The built-in plugin turns copy into scene images, configured speech, burned captions, restrained motion, and an MP4 through an application-managed encoder. Community Git skills may improve storyboards and prompts but only call the same guarded tools; they cannot execute bundled scripts or runtimes. | +| 2026-08-17 | Ship TierNote Video as the safe fallback video workflow | The built-in plugin turns copy into scene images, configured speech, burned captions, restrained motion, and an MP4 through an application-managed encoder. Community Git skills may improve storyboards and prompts but only call the same guarded tools; they cannot execute bundled scripts or runtimes. | | 2026-08-17 | Make note creation actions skill shortcuts | Generate PPT and Generate video beneath a note title select their corresponding one-shot built-in skill and focus the composer without sending. The current note remains explicit context. Remove the disabled Mobile long image placeholder instead of expanding the row with an unrelated future export. | -| 2026-08-17 | Generate DOCX and PDF through one native document runtime | Coffee Documents contains two independently switchable skills that submit the same heading/paragraph/list/quote model. The app writes editable Open XML DOCX and locally typeset PDF files without requiring an Office installation. | +| 2026-08-17 | Generate DOCX and PDF through one native document runtime | TierNote Documents contains two independently switchable skills that submit the same heading/paragraph/list/quote model. The app writes editable Open XML DOCX and locally typeset PDF files without requiring an Office installation. | | 2026-08-17 | Extend note creation shortcuts to document exports | Generate DOCX and Generate PDF join PPT and video beneath the note title. All four actions only select a bundled skill and focus the existing composer; none sends automatically. | | 2026-08-18 | Make generated file destinations explicit | PPTX, DOCX, PDF, and MP4 default to the current user's Desktop, while Settings > General allows a custom directory. The conversation renders the backend-returned absolute path with direct copy and reveal actions so file discovery never depends on model wording. | -| 2026-08-18 | Direct the storyboard before generating assets | Coffee Video exposes both Cinematic storyboard director and Text to video skills. Both share one provider-neutral specification: director brief, beat map, continuity bible, motivated camera movement, concrete physical action, and paired keyframe/motion prompts. Storyboard-only requests stop before generation; rendered videos map the same plan onto guarded Coffee Video tools. | +| 2026-08-18 | Direct the storyboard before generating assets | TierNote Video exposes both Cinematic storyboard director and Text to video skills. Both share one provider-neutral specification: director brief, beat map, continuity bible, motivated camera movement, concrete physical action, and paired keyframe/motion prompts. Storyboard-only requests stop before generation; rendered videos map the same plan onto guarded TierNote Video tools. | | 2026-08-19 | Follow the selected workspace for generated files | With the complete file tree now showing ordinary files, PPTX, DOCX, PDF, and MP4 default directly to the selected workspace root and automatically follow workspace switches. A fixed custom directory remains available for people who want their workspace to contain notes only. | | 2026-08-19 | Make video model presets protocol-aware | Video generation offers selectable official OpenAI and Runway model IDs while preserving stored custom model values. Runway receives its own protocol and a non-generating credential check; other vendors stay custom until their task creation and polling contracts are implemented. | | 2026-08-19 | Add protocol-aware music model settings | Multimodal models gains a fifth Music generation tab with official Google Lyria, ElevenLabs Music, and MiniMax Music presets. Connection checks only read model or account metadata and never submit a billable generation request. The configuration is intentionally not exposed to the Agent until a guarded audio-generation and local-save workflow exists. | diff --git a/NOTICE b/NOTICE index ae9ca0e..9063355 100644 --- a/NOTICE +++ b/NOTICE @@ -1,8 +1,8 @@ -Coffee Note -Copyright (c) 2026 edison7009 and Coffee Note contributors +TierNote +Copyright (c) 2026 edison7009 and TierNote contributors -This product includes software developed by the Coffee Note project: -https://github.com/edison7009/Coffee-Note +This product includes software developed by the TierNote project: +https://github.com/edison7009/TierNote Current versions are licensed under the GNU Affero General Public License, Version 3.0 or later (AGPL-3.0-or-later). See LICENSE for the full text. diff --git a/README.md b/README.md index f9e5db6..101b8dc 100644 --- a/README.md +++ b/README.md @@ -3,31 +3,31 @@

- Coffee Note icon -

Coffee Note

+ TierNote icon +

TierNote

- Latest release - Release build + Latest release + Release build Platforms AGPL-3.0-or-later license

- Website · - Download · + Website · + Download · 简体中文 · - Feedback + Feedback

- Coffee Note desktop home + TierNote desktop home

## Overview -Coffee Note is a cross-platform desktop note agent built around local Markdown files. Its core experience is an editable **T1–T5 priority map**: your most important notes stay visible, while AI can search, organize, summarize, and create without turning the app into a coding tool or task manager. +TierNote is a cross-platform desktop note agent built around local Markdown files. Its core experience is an editable **T1–T5 priority map**: your most important notes stay visible, while AI can search, organize, summarize, and create without turning the app into a coding tool or task manager. | Project | Current state | | --- | --- | @@ -53,18 +53,18 @@ Coffee Note is a cross-platform desktop note agent built around local Markdown f ## Install -Download the appropriate installer from the [latest GitHub Release](https://github.com/edison7009/Coffee-Note/releases/latest), or use the remote installer: +Download the appropriate installer from the [latest GitHub Release](https://github.com/edison7009/TierNote/releases/latest), or use the remote installer: **Windows PowerShell** ```powershell -irm https://note.coffeecli.com/install.ps1 | iex +irm https://tiernote.org/install.ps1 | iex ``` **macOS / Linux** ```bash -curl -fsSL https://note.coffeecli.com/install.sh | sh +curl -fsSL https://tiernote.org/install.sh | sh ``` ## Supported platforms @@ -142,7 +142,7 @@ cargo test --manifest-path src-tauri/Cargo.toml - Your note library and complete conversation records stay on your computer by default. - Only requests you initiate send the selected context to your configured model provider. - Knowledge-library access is path-scoped and canonicalized to block traversal outside the selected root. -- Provider configuration, including API keys, is stored as plaintext JSON only in the current user's Coffee Note app-data directory. It is never written into this repository or the note library. +- Provider configuration, including API keys, is stored as plaintext JSON only in the current user's TierNote app-data directory. It is never written into this repository or the note library. - No telemetry service is required for the local note workflow. ## Release process @@ -151,7 +151,7 @@ Tags matching `v*` trigger quality checks and native builds for Windows x64, mac ## License & commercial use -**Open-source edition** — Coffee Note is free, forever, under the +**Open-source edition** — TierNote is free, forever, under the [GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later)](LICENSE). Companies are welcome to use it as-is. Modified versions distributed to others, and modified versions offered to users over a network, must follow AGPL's source @@ -159,13 +159,13 @@ availability requirements. See [NOTICE](NOTICE) for the legacy MIT notice and [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) for third-party acknowledgements. **Commercial & enterprise licensing** — A paid commercial license is only -needed when you want to step outside AGPL obligations: to customize Coffee Note +needed when you want to step outside AGPL obligations: to customize TierNote and keep the changes closed-source, redistribute it under your own brand or as a white-label product, or embed it in a proprietary product you distribute. Custom development, priority support, and SLAs are also available. Tell us what you are building and we will tailor a plan and quote. -Contact sales: **[hi@coffeecli.com](mailto:hi@coffeecli.com?subject=Coffee%20Note%20Enterprise)** +Contact sales: **[hi@coffeecli.com](mailto:hi@coffeecli.com?subject=TierNote%20Enterprise)** **Contributing** — See [CONTRIBUTING.md](CONTRIBUTING.md). Contributions are accepted under the project CLA so commercial relicensing remains possible. diff --git a/README.zh-CN.md b/README.zh-CN.md index cb9b0fb..6dec794 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -3,31 +3,31 @@

- Coffee Note 图标 -

Coffee Note

+ TierNote 图标 +

TierNote

- 最新版本 - 发布构建 + 最新版本 + 发布构建 支持平台 AGPL-3.0-or-later 许可证

- 官网 · - 下载 · + 官网 · + 下载 · English · - 问题反馈 + 问题反馈

- Coffee Note 桌面端首页 + TierNote 桌面端首页

## 项目概览 -Coffee Note 是围绕本地 Markdown 文件构建的跨平台桌面 Note Agent。产品核心是一张可编辑的 **T1–T5 优先级地图**:重要笔记始终保持可见,AI 可以检索、整理、总结与创作,但不会把笔记软件变成编程工具或任务管理器。 +TierNote 是围绕本地 Markdown 文件构建的跨平台桌面 Note Agent。产品核心是一张可编辑的 **T1–T5 优先级地图**:重要笔记始终保持可见,AI 可以检索、整理、总结与创作,但不会把笔记软件变成编程工具或任务管理器。 | 项目 | 当前状态 | | --- | --- | @@ -53,18 +53,18 @@ Coffee Note 是围绕本地 Markdown 文件构建的跨平台桌面 Note Agent ## 安装 -可以从 [GitHub 最新版本](https://github.com/edison7009/Coffee-Note/releases/latest) 下载对应安装包,或使用远程安装命令。 +可以从 [GitHub 最新版本](https://github.com/edison7009/TierNote/releases/latest) 下载对应安装包,或使用远程安装命令。 **Windows PowerShell** ```powershell -irm https://note.coffeecli.com/install.ps1 | iex +irm https://tiernote.org/install.ps1 | iex ``` **macOS / Linux** ```bash -curl -fsSL https://note.coffeecli.com/install.sh | sh +curl -fsSL https://tiernote.org/install.sh | sh ``` ## 支持平台 @@ -142,7 +142,7 @@ cargo test --manifest-path src-tauri/Cargo.toml - 笔记库与完整对话记录默认保存在当前电脑上。 - 只有用户主动发起模型请求时,所选上下文才会发送给已配置的模型服务商。 - 知识库访问会进行路径限定和 canonicalize 检查,阻止越过所选根目录。 -- 模型配置(包括 API Key)仅以明文 JSON 保存在当前用户的 Coffee Note 应用数据目录,不会写入仓库或笔记库。 +- 模型配置(包括 API Key)仅以明文 JSON 保存在当前用户的 TierNote 应用数据目录,不会写入仓库或笔记库。 - 本地笔记工作流不依赖遥测服务。 ## 发布流程 @@ -151,18 +151,18 @@ cargo test --manifest-path src-tauri/Cargo.toml ## 开源协议与商业授权 -**开源版** — Coffee Note 采用 +**开源版** — TierNote 采用 [GNU Affero 通用公共许可证 v3 或更高版本(AGPL-3.0-or-later)](LICENSE), 永久免费,企业可原样使用。向他人分发修改版本,或通过网络向用户提供修改版本时, 必须遵守 AGPL 的源码提供义务。历史 MIT 授权说明见 [NOTICE](NOTICE),第三方组件 与许可说明见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。 **企业采购 / 商业授权** — 仅当需要跳出 AGPL 开源义务时才需付费商业授权: -**定制 Coffee Note 并保持改动闭源**、**以自有品牌 / 白标对外分发**,或 +**定制 TierNote 并保持改动闭源**、**以自有品牌 / 白标对外分发**,或 **嵌入贵司要分发的商业产品**。也提供**定制开发、优先支持与 SLA**。 告诉我们贵司的用途与需求,我们按需出方案与报价。 -联系采购:**[hi@coffeecli.com](mailto:hi@coffeecli.com?subject=Coffee%20Note%20Enterprise)** +联系采购:**[hi@coffeecli.com](mailto:hi@coffeecli.com?subject=TierNote%20Enterprise)** **贡献代码** — 参见 [CONTRIBUTING.md](CONTRIBUTING.md)。项目通过 CLA 接收贡献, 以保留提供商业授权的能力。 diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 6396b04..f99dcef 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -2,17 +2,17 @@ ## printpdf -Coffee Note uses printpdf 0.7 to write PDF files and subset local TrueType fonts. +TierNote uses printpdf 0.7 to write PDF files and subset local TrueType fonts. Copyright (c) 2017 Felix Schütt. Licensed under the MIT License: https://github.com/fschutt/printpdf/blob/v0.7.0/LICENSE ## FFmpeg -Coffee Note bundles FFmpeg as a separate command-line encoder for the built-in video +TierNote bundles FFmpeg as a separate command-line encoder for the built-in video plugin. The Windows and Linux binaries supplied by `@ffmpeg-installer/ffmpeg` are licensed under GNU GPL version 3; platform builds may include differently licensed -FFmpeg configurations. Coffee Note communicates with the executable only through its +FFmpeg configurations. TierNote communicates with the executable only through its command-line interface and does not link FFmpeg into the application. FFmpeg copyright belongs to the FFmpeg developers and its component authors. License @@ -21,7 +21,7 @@ https://github.com/FFmpeg/FFmpeg/tree/f22fcd4483 ## Tencent openclaw-weixin -Coffee Note's Weixin channel follows the HTTP/JSON protocol and portions of the +TierNote's Weixin channel follows the HTTP/JSON protocol and portions of the transport design published in Tencent's `openclaw-weixin` project. Copyright (C) 2026 Tencent. All rights reserved. @@ -29,11 +29,11 @@ Copyright (C) 2026 Tencent. All rights reserved. Licensed under the MIT License: https://github.com/Tencent/openclaw-weixin/blob/main/LICENSE -The Coffee Note integration is independent and does not bundle or require the +The TierNote integration is independent and does not bundle or require the OpenClaw runtime. ## Channel marks The Weixin and Telegram names and logos are trademarks of their respective -owners. Coffee Note uses these marks only to identify the corresponding optional +owners. TierNote uses these marks only to identify the corresponding optional message-channel integrations and is not endorsed by either service. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index ede8157..c3d4404 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,8 +1,8 @@ -# Coffee Note 架构说明 +# TierNote 架构说明 ## 产品定位 -Coffee Note 是一个本地优先的纯笔记工作台:用户用 T1-T5 分级组织本地 +TierNote 是一个本地优先的纯笔记工作台:用户用 T1-T5 分级组织本地 Markdown 笔记,AI 以「省钱的 Note Agent」形式协助整理与治理笔记。 产品边界见 [NOTE_AGENT_SAVINGS.md](./NOTE_AGENT_SAVINGS.md):它不是 @@ -19,7 +19,7 @@ coding agent,不绑定昂贵模型,以完成笔记治理任务为优先, ## 独立资料库 -Coffee Note 的默认资料库位于各平台的应用数据目录: +TierNote 为兼容 v0.1.8,继续读取原有的本地资料目录: ```text Windows %USERPROFILE%/.coffee-note/演示笔记 @@ -36,7 +36,7 @@ Linux ~/.coffee-note/演示笔记 ## Agent:DeepSeek Harness 单一运行时 Agent 循环完全交由固定版本的 DeepSeek Harness 运行时负责,包括模型流式 -请求、工具编排、持久会话、Token 计量与上下文压缩。Coffee Note 不再维护 +请求、工具编排、持久会话、Token 计量与上下文压缩。TierNote 不再维护 并行的自研循环;`dsh_runtime.rs` 只承担 Tauri 事件适配、进程生命周期、 产品上下文注入和本地工具桥接。 @@ -46,7 +46,7 @@ Library Graph、记忆路由和网页读取通过仅监听 localhost、带随机 ## 本地知识与个人记忆 -Coffee Note 的记忆路由有两个用户可见的真源,以及一份可重建索引: +TierNote 的记忆路由有两个用户可见的真源,以及一份可重建索引: - **我的资料**(应用管理的 Markdown):用户确认的长期目标、偏好、约束、 经验与健康背景写入对应的 `plans/*.md` 页面;这是个人事实的唯一真源。 @@ -56,7 +56,7 @@ Coffee Note 的记忆路由有两个用户可见的真源,以及一份可重 `memory.json` 是用于去重和来源追踪的本地索引,丢失时不会影响 Markdown 中的个人事实,下一次确认记忆会从可见页面重新建立索引。 -每次 Agent 请求由 Coffee Note 路由器组合三类上下文:当前问题相关的 +每次 Agent 请求由 TierNote 路由器组合三类上下文:当前问题相关的 「我的资料」摘要、当前笔记目录的 Library Graph 命中,以及首次迁移时的 最近对话。个人资料检索保持在约 16 KB;当前笔记只注入相关片段。之后的 会话维护和压缩由 DSH 负责。系统提示保持稳定,动态资料放入用户消息, @@ -96,6 +96,6 @@ Coffee Note 的记忆路由有两个用户可见的真源,以及一份可重 - 所有读操作限制在用户选择的知识目录; - 路径 canonicalize 后检查,阻止 `../` 越界; - AI 收录只写入 `knowledge/inbox/`,且不会覆盖同名文件; -- AI 服务商配置(包括 API Key)以明文 JSON 保存在当前用户的应用数据 +- AI 服务商配置(包括 API Key)以明文 JSON 保存在当前用户的兼容应用数据 目录 `Coffee Note/config.json`,不写入仓库或知识库; - 个人资料只在用户发起模型请求时发送给其配置的模型服务商。 diff --git a/docs/BILINGUAL_LIBRARY.md b/docs/BILINGUAL_LIBRARY.md index f4a67d6..b29d3ab 100644 --- a/docs/BILINGUAL_LIBRARY.md +++ b/docs/BILINGUAL_LIBRARY.md @@ -1,6 +1,6 @@ # Bilingual starter library -Coffee Note keeps one logical knowledge library rather than two independent copies. +TierNote keeps one logical knowledge library rather than two independent copies. ## File pairing diff --git a/docs/NOTE_AGENT.md b/docs/NOTE_AGENT.md index 5426aef..99a2f65 100644 --- a/docs/NOTE_AGENT.md +++ b/docs/NOTE_AGENT.md @@ -1,6 +1,6 @@ -# Coffee Note Note Agent +# TierNote Note Agent -Coffee Note is a **Note Agent**, not a coding agent or a general-purpose shell +TierNote is a **Note Agent**, not a coding agent or a general-purpose shell harness. Its job is to make a user's notes useful, searchable, and cheap to maintain. @@ -19,7 +19,7 @@ maintain. ## Note Agent vs. coding agent -| Coding agent | Coffee Note Note Agent | +| Coding agent | TierNote Note Agent | | --- | --- | | edits source files and runs commands | curates Markdown notes and plans | | optimizes for implementation speed | optimizes for clarity, recall, and cost | diff --git a/docs/NOTE_AGENT_SAVINGS.md b/docs/NOTE_AGENT_SAVINGS.md index 4c3036b..8ec8cf0 100644 --- a/docs/NOTE_AGENT_SAVINGS.md +++ b/docs/NOTE_AGENT_SAVINGS.md @@ -1,15 +1,15 @@ -# Coffee Note 产品亮点说明 +# TierNote 产品亮点说明 > 状态:产品定位备忘(docs/ 不参与版本,本地阅读) > -> 这份文档记录 Coffee Note 的三个核心亮点——它们共同构成「本地优先的 +> 这份文档记录 TierNote 的三个核心亮点——它们共同构成「本地优先的 > AI 第二大脑」的产品特色,也是对外沟通、官网文案和定价说明的底稿。 --- ## 亮点一:省钱 —— 深度优化 DeepSeek 和其他模型 -**Coffee Note 是省钱的 Note Agent。** 它不是要求用户购买 Claude、GPT 或 +**TierNote 是省钱的 Note Agent。** 它不是要求用户购买 Claude、GPT 或 Opus 的 coding 工具,也不是把用户推向更昂贵的模型;而是让用户选择自己 负担得起的模型(深度优化 DeepSeek 等低价模型),用更少 token 管好自己的 笔记。 @@ -39,7 +39,7 @@ Opus 的 coding 工具,也不是把用户推向更昂贵的模型;而是让 ## 亮点二:任意视频网址 → 笔记 **把任意视频网址导入成结构化笔记。** 用户粘贴 YouTube、B 站、抖音、 -小红书、X 等平台的视频链接,Coffee Note 自动把视频转成文字(音频转写), +小红书、X 等平台的视频链接,TierNote 自动把视频转成文字(音频转写), 再让 Agent 整理成有条理的 Markdown 笔记——视频讲过的内容,从此可以检索、 引用和复习。 @@ -80,7 +80,7 @@ Opus 的 coding 工具,也不是把用户推向更昂贵的模型;而是让 多选→PPT/视频(亮点三)→ 出得来:笔记一键长成演示成品 ``` -**收得进、用得起、出得来** —— 这是 Coffee Note 区别于其他笔记工具和 +**收得进、用得起、出得来** —— 这是 TierNote 区别于其他笔记工具和 coding agent 的完整产品故事。 ## 一句话方向 diff --git a/docs/RELEASE.md b/docs/RELEASE.md index be8a502..3262756 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -1,4 +1,4 @@ -# Coffee Note 发布流程 +# TierNote 发布流程 > 每次修改版本号、创建 tag 或发布 GitHub Release 前都必须重新阅读本文。 > 核心顺序:**版本提交 → 本地预检 → 推送 main → 等 CI 全绿 → 创建 tag → 守到正式发布 → 验收下载**。 @@ -11,8 +11,8 @@ git fetch origin main --tags git status --short git rev-list --left-right --count HEAD...origin/main -gh run list --repo edison7009/Coffee-Note --workflow CI --limit 5 -gh run list --repo edison7009/Coffee-Note --workflow "Release desktop apps" --limit 5 +gh run list --repo edison7009/TierNote --workflow CI --limit 5 +gh run list --repo edison7009/TierNote --workflow "Release desktop apps" --limit 5 ``` - 必须在 `main` 上发布,且本地与 `origin/main` 同步。 @@ -27,8 +27,8 @@ gh run list --repo edison7009/Coffee-Note --workflow "Release desktop apps" --li | `package.json` | `version` | | `package-lock.json` | 顶层 `version` 和 `packages[""].version` | | `src-tauri/tauri.conf.json` | `version` | -| `src-tauri/Cargo.toml` | Coffee Note package 的 `version` | -| `src-tauri/Cargo.lock` | `name = "coffee-note"` 条目的 `version` | +| `src-tauri/Cargo.toml` | TierNote package 的 `version` | +| `src-tauri/Cargo.lock` | `name = "tiernote"` 条目的 `version` | | `website/version.json` | `version` | 先用 npm 同步前两个文件,再精确修改其余四个文件: @@ -50,7 +50,7 @@ npm run release:preflight 它依次执行: -1. 准备当前平台的 Coffee Video FFmpeg sidecar; +1. 准备当前平台的 TierNote Video FFmpeg sidecar; 2. 检查 6 个版本文件; 3. TypeScript 类型检查、前端测试、双语资源检查和前端构建; 4. Rust 格式检查、Clippy `-D warnings` 和完整 Rust 测试。 @@ -63,7 +63,7 @@ npm run release:preflight git add package.json package-lock.json src-tauri/tauri.conf.json src-tauri/Cargo.toml src-tauri/Cargo.lock website/version.json git commit -m "chore: bump version to X.Y.Z" git push origin main -gh run list --repo edison7009/Coffee-Note --workflow CI --branch main --limit 3 +gh run list --repo edison7009/TierNote --workflow CI --branch main --limit 3 ``` 找到与版本提交 SHA 对应的 CI run,并等待它 `completed/success`。CI 的前端与 Rust 质量门都必须成功后才能继续。 @@ -88,8 +88,8 @@ Linux arm64 必须使用原生 `ubuntu-24.04-arm` runner,不能改回 glib/pkg 持续监控,不要在工作流刚启动或 Release 仍是 draft 时宣布完成: ```powershell -gh run list --repo edison7009/Coffee-Note --workflow "Release desktop apps" --branch vX.Y.Z --limit 3 -gh run watch RUN_ID --repo edison7009/Coffee-Note --exit-status +gh run list --repo edison7009/TierNote --workflow "Release desktop apps" --branch vX.Y.Z --limit 3 +gh run watch RUN_ID --repo edison7009/TierNote --exit-status ``` ## 六、发布完成验收 @@ -99,17 +99,17 @@ gh run watch RUN_ID --repo edison7009/Coffee-Note --exit-status - GitHub Release 为非 draft、非 prerelease、latest; - tag 指向已经通过 main CI 的版本提交; - 共有 9 个附件:Windows EXE/MSI、macOS arm64/x64 DMG、Linux x64 DEB/RPM/AppImage、Linux arm64 DEB/RPM; -- 附件名全部为 `Coffee.Note_X.Y.Z_*`; -- `https://note.coffeecli.com/version.json?platform=windows` 返回 `{"version":"X.Y.Z"}`; -- `https://note.coffeecli.com/download/windows` 返回 `application/octet-stream`,文件名为该版本 Windows EXE,不能是 HTML; +- 附件名全部为 `TierNote_X.Y.Z_*`; +- `https://tiernote.org/version.json?platform=windows` 返回 `{"version":"X.Y.Z"}`; +- `https://tiernote.org/download/windows` 返回 `application/octet-stream`,文件名为该版本 Windows EXE,不能是 HTML; - 本地 `main` 与 `origin/main` 同步,工作区只剩明确保留的用户文件。 常用检查: ```powershell -gh release view vX.Y.Z --repo edison7009/Coffee-Note --json tagName,isDraft,isPrerelease,publishedAt,url,assets -curl.exe -sS "https://note.coffeecli.com/version.json?platform=windows" -curl.exe -sS -I "https://note.coffeecli.com/download/windows" +gh release view vX.Y.Z --repo edison7009/TierNote --json tagName,isDraft,isPrerelease,publishedAt,url,assets +curl.exe -sS "https://tiernote.org/version.json?platform=windows" +curl.exe -sS -I "https://tiernote.org/download/windows" ``` ## 七、版本同步 workflow 的真实行为 diff --git a/docs/THIRD_PARTY_NOTICES.md b/docs/THIRD_PARTY_NOTICES.md index 3798bdc..84e6fa9 100644 --- a/docs/THIRD_PARTY_NOTICES.md +++ b/docs/THIRD_PARTY_NOTICES.md @@ -2,7 +2,7 @@ ## Open-Meteo -Coffee Note's optional weather panel uses geocoding and forecast data from +TierNote's optional weather panel uses geocoding and forecast data from [Open-Meteo](https://open-meteo.com/). Home itself shows only the compact condition image and read-only forecast; the Open-Meteo attribution appears in Settings > Appearance alongside the weather configuration. Open-Meteo combines open data @@ -10,12 +10,12 @@ from multiple national weather services; its API data is provided under the [Creative Commons Attribution 4.0 International licence](https://creativecommons.org/licenses/by/4.0/). The no-key public endpoint is suitable for development and non-commercial use. -A commercial Coffee Note release must use an appropriately licensed endpoint or a +A commercial TierNote release must use an appropriately licensed endpoint or a compliant self-hosted/proxied deployment. ## models.dev -Coffee Note reads provider names, API endpoints, model capabilities, context limits, +TierNote reads provider names, API endpoints, model capabilities, context limits, pricing metadata, and provider logo assets from [anomalyco/models.dev](https://github.com/anomalyco/models.dev). The catalog is cached only in the current user's app-data directory. Provider names and logos @@ -45,7 +45,7 @@ SOFTWARE. ## DeepSeek-Reasonix -Coffee Note's staged context maintenance and provider cache-usage normalization +TierNote's staged context maintenance and provider cache-usage normalization were adapted from ideas and implementation patterns in [esengine/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix), reviewed at commit `2c54501`. diff --git a/docs/import-pipeline-plan.md b/docs/import-pipeline-plan.md index 93c0531..7d38719 100644 --- a/docs/import-pipeline-plan.md +++ b/docs/import-pipeline-plan.md @@ -7,7 +7,7 @@ ## 0. 核心思路(一句话) -**不转格式,只送内容。** 用户在「导入你的资料」界面选择本地文件(或粘贴链接/本地路径),Coffee-Note 把来源变成**文字内容**送进 Agent 上下文,**Agent 自己整理成 Markdown 并保存**(`save_note` 已有)。 +**不转格式,只送内容。** 用户在「导入你的资料」界面选择本地文件(或粘贴链接/本地路径),TierNote 把来源变成**文字内容**送进 Agent 上下文,**Agent 自己整理成 Markdown 并保存**(`save_note` 已有)。 - 文字类来源:**0 转化**——读到就是内容 - 唯一真正的格式转换是**音频类**(视频/音频 → 文字),`transcription.rs` 已实现 diff --git a/docs/reference-analysis-awesome-llm-apps.md b/docs/reference-analysis-awesome-llm-apps.md index 2498613..2f09728 100644 --- a/docs/reference-analysis-awesome-llm-apps.md +++ b/docs/reference-analysis-awesome-llm-apps.md @@ -8,7 +8,7 @@ ## 概览 100+ AI Agents / Agent Skills / RAG Apps,6 大类。技术栈以 Python -(LangGraph/FastAPI)为主,**代码不能直接搬**(Coffee-Note 是 Rust+Tauri), +(LangGraph/FastAPI)为主,**代码不能直接搬**(TierNote 是 Rust+Tauri), 但**思路和产品形态值得借鉴**。 ## 最值得借鉴的 5 个点 @@ -52,7 +52,7 @@ ### 5. Voice AI 与 MCP agents — 前瞻储备 -- `voice_ai_agents/`:Coffee-Note 已有 transcription,未来可扩展语音笔记 +- `voice_ai_agents/`:TierNote 已有 transcription,未来可扩展语音笔记 - `mcp_ai_agents/`(multi_mcp_agent_router 等):未来接 MCP 生态的路由参考 ## 不建议借鉴 @@ -63,7 +63,7 @@ ## 落地建议 -| 优先级 | 借鉴点 | 落到 Coffee-Note | +| 优先级 | 借鉴点 | 落到 TierNote | |---|---|---| | P0 | 拖文件→Agent→结构化产物 | 导入流水线(进行中) | | P0 | 确定性工作用代码,思考用 LLM | `read_local_file` 工具设计 | diff --git a/index.html b/index.html index 21305bd..878c065 100644 --- a/index.html +++ b/index.html @@ -6,9 +6,9 @@ - Coffee Note + TierNote
diff --git a/package-lock.json b/package-lock.json index 4289e9c..46cf249 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "coffee-note", + "name": "tiernote", "version": "0.1.8", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "coffee-note", + "name": "tiernote", "version": "0.1.8", "license": "AGPL-3.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 5518015..c6fd16a 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "coffee-note", + "name": "tiernote", "private": true, "version": "0.1.8", "description": "A local-first workspace agent with tier-based organization and AI assistance.", diff --git a/scripts/check-release-version.mjs b/scripts/check-release-version.mjs index d772672..dab3a5e 100644 --- a/scripts/check-release-version.mjs +++ b/scripts/check-release-version.mjs @@ -19,7 +19,7 @@ const cargoVersion = cargoManifest.match( /^\s*version\s*=\s*"([^"]+)"\s*$/m, )?.[1]; const cargoLockVersion = cargoLock.match( - /\[\[package\]\]\r?\nname = "coffee-note"\r?\nversion = "([^"]+)"/, + /\[\[package\]\]\r?\nname = "tiernote"\r?\nversion = "([^"]+)"/, )?.[1]; const websiteVersion = JSON.parse( readFileSync(new URL('../website/version.json', import.meta.url), 'utf8'), diff --git a/scripts/prepare-video-runtime.mjs b/scripts/prepare-video-runtime.mjs index 296c3e8..2741e79 100644 --- a/scripts/prepare-video-runtime.mjs +++ b/scripts/prepare-video-runtime.mjs @@ -16,7 +16,7 @@ const triples = { }; const key = `${process.platform}-${process.arch}`; const triple = triples[key]; -if (!triple) throw new Error(`Coffee Video does not support the ${key} build target yet.`); +if (!triple) throw new Error(`TierNote Video does not support the ${key} build target yet.`); const extension = process.platform === 'win32' ? '.exe' : ''; const destination = path.join( @@ -28,4 +28,4 @@ const destination = path.join( await mkdir(path.dirname(destination), { recursive: true }); await copyFile(ffmpeg.path, destination); if (process.platform !== 'win32') await chmod(destination, 0o755); -console.log(`Prepared Coffee Video encoder: ${path.relative(root, destination)}`); +console.log(`Prepared TierNote Video encoder: ${path.relative(root, destination)}`); diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 263e4bd..6c4e84e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -598,41 +598,6 @@ dependencies = [ "error-code", ] -[[package]] -name = "coffee-note" -version = "0.1.8" -dependencies = [ - "base64 0.22.1", - "chrono", - "dirs", - "flate2", - "futures", - "futures-util", - "hound", - "log", - "printpdf", - "quick-xml", - "reqwest 0.12.28", - "reqwest-eventsource", - "serde", - "serde_json", - "serde_yaml", - "sha2", - "symphonia", - "tar", - "tauri", - "tauri-build", - "tauri-plugin-clipboard-manager", - "tauri-plugin-dialog", - "tauri-plugin-opener", - "tauri-plugin-shell", - "tauri-plugin-single-instance", - "tokio", - "tokio-util", - "uuid", - "zip", -] - [[package]] name = "combine" version = "4.6.7" @@ -4701,6 +4666,41 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "tiernote" +version = "0.1.8" +dependencies = [ + "base64 0.22.1", + "chrono", + "dirs", + "flate2", + "futures", + "futures-util", + "hound", + "log", + "printpdf", + "quick-xml", + "reqwest 0.12.28", + "reqwest-eventsource", + "serde", + "serde_json", + "serde_yaml", + "sha2", + "symphonia", + "tar", + "tauri", + "tauri-build", + "tauri-plugin-clipboard-manager", + "tauri-plugin-dialog", + "tauri-plugin-opener", + "tauri-plugin-shell", + "tauri-plugin-single-instance", + "tokio", + "tokio-util", + "uuid", + "zip", +] + [[package]] name = "tiff" version = "0.11.3" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cb065b7..c25092c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,14 +1,14 @@ [package] -name = "coffee-note" +name = "tiernote" version = "0.1.8" description = "Local-first workspace agent with tier-based organization and AI assistance" -authors = ["Coffee Team"] +authors = ["TierNote Team"] license = "AGPL-3.0-or-later" edition = "2021" rust-version = "1.77.2" [lib] -name = "coffee_note_lib" +name = "tiernote_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] diff --git a/src-tauri/builtin-plugins/coffee-documents/coffee-plugin.json b/src-tauri/builtin-plugins/coffee-documents/coffee-plugin.json index dfc8616..c4442df 100644 --- a/src-tauri/builtin-plugins/coffee-documents/coffee-plugin.json +++ b/src-tauri/builtin-plugins/coffee-documents/coffee-plugin.json @@ -4,7 +4,7 @@ "name": "文档生成", "description": "把笔记、资料和对话内容整理为可编辑的 Word 文档或可直接分享的 PDF。", "version": "1.0.0", - "publisher": "Coffee Note", + "publisher": "TierNote", "categoryId": "copywriting", "runtime": { "id": "document-engine", diff --git a/src-tauri/builtin-plugins/coffee-documents/skills/create-docx/SKILL.md b/src-tauri/builtin-plugins/coffee-documents/skills/create-docx/SKILL.md index fce2e4a..ddae895 100644 --- a/src-tauri/builtin-plugins/coffee-documents/skills/create-docx/SKILL.md +++ b/src-tauri/builtin-plugins/coffee-documents/skills/create-docx/SKILL.md @@ -5,7 +5,7 @@ description: Create an editable Word DOCX document from selected notes, workspac # Create DOCX -Create the document with Coffee Note's shared document runtime. Never install a package, +Create the document with TierNote's shared document runtime. Never install a package, start a separate service, generate source code for the user to run, or invoke Microsoft Office. 1. Read the selected note and any requested workspace sources before drafting. diff --git a/src-tauri/builtin-plugins/coffee-documents/skills/create-pdf/SKILL.md b/src-tauri/builtin-plugins/coffee-documents/skills/create-pdf/SKILL.md index bc98afa..fbd55a4 100644 --- a/src-tauri/builtin-plugins/coffee-documents/skills/create-pdf/SKILL.md +++ b/src-tauri/builtin-plugins/coffee-documents/skills/create-pdf/SKILL.md @@ -5,7 +5,7 @@ description: Create a polished PDF from selected notes, workspace documents, res # Create PDF -Create the document with Coffee Note's shared document runtime. Never install a package, +Create the document with TierNote's shared document runtime. Never install a package, start a separate service, generate source code for the user to run, or invoke Microsoft Office or LibreOffice. diff --git a/src-tauri/builtin-plugins/coffee-media/coffee-plugin.json b/src-tauri/builtin-plugins/coffee-media/coffee-plugin.json index 807b9ae..a657bc9 100644 --- a/src-tauri/builtin-plugins/coffee-media/coffee-plugin.json +++ b/src-tauri/builtin-plugins/coffee-media/coffee-plugin.json @@ -4,7 +4,7 @@ "name": "媒体处理", "description": "把音视频内容转换为可编辑、可继续整理的本地文字。", "version": "1.0.0", - "publisher": "Coffee Note", + "publisher": "TierNote", "categoryId": "media", "runtime": { "id": "media-transcription", diff --git a/src-tauri/builtin-plugins/coffee-media/skills/media-to-text/SKILL.md b/src-tauri/builtin-plugins/coffee-media/skills/media-to-text/SKILL.md index 7114962..648e53f 100644 --- a/src-tauri/builtin-plugins/coffee-media/skills/media-to-text/SKILL.md +++ b/src-tauri/builtin-plugins/coffee-media/skills/media-to-text/SKILL.md @@ -5,7 +5,7 @@ description: Transcribe public audio or video links and local media files, clean # Media to text -Use Coffee Note's shared media runtime. Never install a downloader, speech engine, or model from this skill. +Use TierNote's shared media runtime. Never install a downloader, speech engine, or model from this skill. 1. Extract one public media URL or absolute local media path from the request. 2. Call `transcribe_media` with that source and the configured recognition mode. diff --git a/src-tauri/builtin-plugins/coffee-presentation/coffee-plugin.json b/src-tauri/builtin-plugins/coffee-presentation/coffee-plugin.json index 9838bb5..ee900a0 100644 --- a/src-tauri/builtin-plugins/coffee-presentation/coffee-plugin.json +++ b/src-tauri/builtin-plugins/coffee-presentation/coffee-plugin.json @@ -4,7 +4,7 @@ "name": "演示文稿", "description": "把笔记、资料和想法整理为结构清晰、可继续编辑的 PowerPoint 演示文稿。", "version": "1.0.0", - "publisher": "Coffee Note", + "publisher": "TierNote", "categoryId": "ppt", "runtime": { "id": "presentation-engine", diff --git a/src-tauri/builtin-plugins/coffee-presentation/skills/create-presentation/SKILL.md b/src-tauri/builtin-plugins/coffee-presentation/skills/create-presentation/SKILL.md index 0ce866e..c048eec 100644 --- a/src-tauri/builtin-plugins/coffee-presentation/skills/create-presentation/SKILL.md +++ b/src-tauri/builtin-plugins/coffee-presentation/skills/create-presentation/SKILL.md @@ -5,7 +5,7 @@ description: Create an editable PowerPoint presentation from selected notes, wor # Create presentation -Create the deck with Coffee Note's shared presentation runtime. Never install a package, +Create the deck with TierNote's shared presentation runtime. Never install a package, start a separate service, or generate source code for the user to run. 1. Read the selected notes or requested workspace sources before planning the deck. diff --git a/src-tauri/builtin-plugins/coffee-video/coffee-plugin.json b/src-tauri/builtin-plugins/coffee-video/coffee-plugin.json index 7564f8c..165ed38 100644 --- a/src-tauri/builtin-plugins/coffee-video/coffee-plugin.json +++ b/src-tauri/builtin-plugins/coffee-video/coffee-plugin.json @@ -4,7 +4,7 @@ "name": "文字生成视频", "description": "用专业镜头语言设计分镜,并可继续生成画面、旁白和可分享的 MP4 视频。", "version": "1.0.0", - "publisher": "Coffee Note", + "publisher": "TierNote", "categoryId": "video", "runtime": { "id": "coffee-video-engine", diff --git a/src-tauri/builtin-plugins/coffee-video/references/cinematic-storyboard.md b/src-tauri/builtin-plugins/coffee-video/references/cinematic-storyboard.md index 3155d34..5b7c0c0 100644 --- a/src-tauri/builtin-plugins/coffee-video/references/cinematic-storyboard.md +++ b/src-tauri/builtin-plugins/coffee-video/references/cinematic-storyboard.md @@ -1,6 +1,6 @@ # Cinematic storyboard specification -Use this specification for both storyboard-only requests and rendered Coffee Video projects. It is +Use this specification for both storyboard-only requests and rendered TierNote Video projects. It is model-neutral: direct what happens on screen before adapting syntax to a particular generator. ## Director brief @@ -92,7 +92,7 @@ framing, or state. A motion prompt should explain what exists at the start, what exact end state. Avoid multiple competing camera moves, impossible choreography, unexplained style changes, and excessive cuts inside a short model clip. -For the native Coffee Video fallback, the keyframe prompt must stand on its own as a strong still, +For the native TierNote Video fallback, the keyframe prompt must stand on its own as a strong still, and the planned movement must map to `zoom-in`, `zoom-out`, `pan-left`, `pan-right`, or `still`. For a video model, keep the full temporal motion prompt and adapt provider syntax only after the model is known. @@ -111,10 +111,10 @@ Before returning or rendering, verify: ## Influences -This original Coffee Note specification was informed by the production-planning patterns in +This original TierNote specification was informed by the production-planning patterns in [visual-skills](https://github.com/smixs/visual-skills) by Serge Shima (CC BY 4.0), [AI Video Storyboard Generator](https://github.com/aicontentskills/ai-video-storyboard-skill) (MIT), [Kling 3 Prompting Skill](https://github.com/aedev-tools/kling-3-prompting-skill) (Apache-2.0), and [Higgsfield AI Prompt Skill](https://github.com/OSideMedia/higgsfield-ai-prompt-skill) -(MIT). Coffee Note's wording, model-neutral schema, dual keyframe/motion prompts, and native-runtime +(MIT). TierNote's wording, model-neutral schema, dual keyframe/motion prompts, and native-runtime mapping are its own adaptation. diff --git a/src-tauri/builtin-plugins/coffee-video/skills/create-video/SKILL.md b/src-tauri/builtin-plugins/coffee-video/skills/create-video/SKILL.md index 0df0c41..73bc524 100644 --- a/src-tauri/builtin-plugins/coffee-video/skills/create-video/SKILL.md +++ b/src-tauri/builtin-plugins/coffee-video/skills/create-video/SKILL.md @@ -5,7 +5,7 @@ description: Create an MP4 video from copy, notes, workspace documents, or conve # Create video -Create the video with Coffee Note's shared image, speech, and video runtimes. Never install a +Create the video with TierNote's shared image, speech, and video runtimes. Never install a package, start a service, or generate Remotion/Python source code for the user to run. Apply the bundled Cinematic storyboard specification before generating any scene asset. diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 5f5c7b0..d14db83 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -1,7 +1,7 @@ { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", - "description": "Default capabilities for the Coffee Note main window", + "description": "Default capabilities for the TierNote main window", "windows": ["main"], "permissions": [ "core:default", diff --git a/src-tauri/gen/schemas/capabilities.json b/src-tauri/gen/schemas/capabilities.json index b038b9b..f7eaa91 100644 --- a/src-tauri/gen/schemas/capabilities.json +++ b/src-tauri/gen/schemas/capabilities.json @@ -1 +1 @@ -{"default":{"identifier":"default","description":"Default capabilities for the Coffee Note main window","local":true,"windows":["main"],"permissions":["core:default","core:window:allow-close","core:window:allow-minimize","core:window:allow-start-dragging","core:window:allow-toggle-maximize","dialog:allow-open","dialog:allow-message","opener:default","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text"]}} \ No newline at end of file +{"default":{"identifier":"default","description":"Default capabilities for the TierNote main window","local":true,"windows":["main"],"permissions":["core:default","core:window:allow-close","core:window:allow-minimize","core:window:allow-start-dragging","core:window:allow-toggle-maximize","dialog:allow-open","dialog:allow-message","opener:default","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text"]}} \ No newline at end of file diff --git a/src-tauri/installer.nsi b/src-tauri/installer.nsi index 7229728..7b12b37 100644 --- a/src-tauri/installer.nsi +++ b/src-tauri/installer.nsi @@ -57,6 +57,10 @@ ${StrLoc} !define MINIMUMWEBVIEW2VERSION "{{minimum_webview2_version}}" !define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}" !define MANUPRODUCTKEY "Software\${MANUFACTURER}\${PRODUCTNAME}" +; v0.1.8 shipped under the Coffee Note product name. Detect and remove that +; installation during the TierNote transition while leaving app data intact. +!define LEGACY_UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\Coffee Note" +!define LEGACY_MANUPRODUCTKEY "Software\Coffee Team\Coffee Note" !define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}" !define ESTIMATEDSIZE "{{estimated_size}}" !define STARTMENUFOLDER "{{start_menu_folder}}" @@ -66,6 +70,7 @@ Var UpdateMode Var NoShortcutMode Var WixMode Var OldMainBinaryName +Var LegacyProductMode Name "${PRODUCTNAME}" BrandingText "${COPYRIGHT}" @@ -193,8 +198,16 @@ Function PageReinstall wix_loop_done: ; Check if there is an existing installation, if not, abort the reinstall page + StrCpy $LegacyProductMode 0 ReadRegStr $R0 SHCTX "${UNINSTKEY}" "" ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString" + ${If} "$R0$R1" == "" + ReadRegStr $R0 SHCTX "${LEGACY_UNINSTKEY}" "" + ReadRegStr $R1 SHCTX "${LEGACY_UNINSTKEY}" "UninstallString" + ${If} "$R0$R1" != "" + StrCpy $LegacyProductMode 1 + ${EndIf} + ${EndIf} ${IfThen} "$R0$R1" == "" ${|} Abort ${|} ; Compare this installar version with the existing installation @@ -203,6 +216,8 @@ Function PageReinstall StrCpy $R4 "$(older)" ${If} $WixMode = 1 ReadRegStr $R0 HKLM "$R6" "DisplayVersion" + ${ElseIf} $LegacyProductMode = 1 + ReadRegStr $R0 SHCTX "${LEGACY_UNINSTKEY}" "DisplayVersion" ${Else} ReadRegStr $R0 SHCTX "${UNINSTKEY}" "DisplayVersion" ${EndIf} @@ -293,6 +308,12 @@ Function PageLeaveReinstall Goto reinst_uninstall ${EndIf} + ; The old and new product names use different uninstall keys and install + ; directories, so always remove the legacy application before continuing. + ${If} $LegacyProductMode = 1 + Goto reinst_uninstall + ${EndIf} + ; In update mode, always proceeds without uninstalling ${If} $UpdateMode = 1 Goto reinst_done @@ -329,6 +350,15 @@ Function PageLeaveReinstall ${If} $WixMode = 1 ReadRegStr $R1 HKLM "$R6" "UninstallString" ExecWait '$R1' $0 + ${ElseIf} $LegacyProductMode = 1 + ReadRegStr $4 SHCTX "${LEGACY_MANUPRODUCTKEY}" "" + ${If} $4 == "" + ReadRegStr $4 SHCTX "${LEGACY_UNINSTKEY}" "InstallLocation" + ${EndIf} + ReadRegStr $R1 SHCTX "${LEGACY_UNINSTKEY}" "UninstallString" + ${IfThen} $PassiveMode = 1 ${|} StrCpy $R1 "$R1 /P" ${|} + StrCpy $R1 "$R1 _?=$4" + ExecWait '$R1' $0 ${Else} ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" "" ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString" diff --git a/src-tauri/src/agent_loop.rs b/src-tauri/src/agent_loop.rs index 66f9935..9d25582 100644 --- a/src-tauri/src/agent_loop.rs +++ b/src-tauri/src/agent_loop.rs @@ -1,4 +1,4 @@ -// General-purpose workspace ReAct loop for Coffee Note. +// General-purpose workspace ReAct loop for TierNote. // Streams text + tool calls to the frontend via Tauri events. use serde::{Deserialize, Serialize}; @@ -388,7 +388,7 @@ fn build_system_prompt(locale: &str) -> String { "使用简体中文回答。" }; format!( - "You are Coffee Note, a local-first general-purpose workspace agent with tool-calling ability. \ + "You are TierNote, a local-first general-purpose workspace agent with tool-calling ability. \ The user's currently selected directory is your working directory. It may be a code repository, \ a writing project, a collection of notes, or any other folder. Never assume it follows a note \ architecture and never invent Inbox or other fixed subdirectories. Notes are only one common \ @@ -405,7 +405,7 @@ fn build_system_prompt(locale: &str) -> String { and 'content'. It saves to the workspace root unless the user requests a relative Markdown path. \ Do not create a category directory automatically. If a tool call is rejected for missing, empty, \ or malformed arguments, fix the arguments and retry with a complete JSON object. \ - Coffee Note-specific features such as My Contexts, semantic Markdown search, and the optional \ + TierNote-specific features such as My Contexts, semantic Markdown search, and the optional \ T1–T5 priority view are capabilities, not required workspace structure. Use update_plan only when \ the user explicitly asks to update a My Contexts page. Use search_library/read_note only for \ semantic note retrieval, and update_tier only when the user explicitly asks for T1–T5 priority. \ @@ -604,7 +604,7 @@ fn snip_tool_result(content: &str) -> String { .skip(count - SNIPPED_TOOL_TAIL_CHARS) .collect::(); format!( - "{head}\n\n[… Coffee Note locally snipped {} characters from this stale tool result …]\n\n{tail}", + "{head}\n\n[… TierNote locally snipped {} characters from this stale tool result …]\n\n{tail}", count - SNIPPED_TOOL_HEAD_CHARS - SNIPPED_TOOL_TAIL_CHARS ) } @@ -629,7 +629,7 @@ fn maintain_stale_tool_results(messages: &mut [Message], prune: bool) { } *content = if prune { format!( - "[Coffee Note pruned a stale tool result locally; original preserved in conversation history, {} bytes]", + "[TierNote pruned a stale tool result locally; original preserved in conversation history, {} bytes]", content.len() ) } else { @@ -1279,10 +1279,10 @@ pub async fn run_agent( if finalizing { let final_text = if text_accum.trim().is_empty() { if request.locale == "en" { - "Coffee Note reached its emergency safety limit. Completed tool results were preserved, but the model did not return a final status." + "TierNote reached its emergency safety limit. Completed tool results were preserved, but the model did not return a final status." .to_string() } else { - "Coffee Note 已达到异常安全上限。已完成的工具结果均已保留,但模型没有返回最终说明。" + "TierNote 已达到异常安全上限。已完成的工具结果均已保留,但模型没有返回最终说明。" .to_string() } } else { diff --git a/src-tauri/src/agent_tools.rs b/src-tauri/src/agent_tools.rs index 0e91c27..f835cb2 100644 --- a/src-tauri/src/agent_tools.rs +++ b/src-tauri/src/agent_tools.rs @@ -1,5 +1,5 @@ // Agent tools for the selected local workspace. Note-specific tools remain -// available as optional Coffee Note features, not as a required directory model. +// available as optional TierNote features, not as a required directory model. use serde_json::{json, Value}; use std::fs; @@ -165,7 +165,7 @@ pub fn get_tool_definitions(availability: ToolAvailability) -> Vec { 'experience' for My experience, 'lessons' for My lessons, and \ 'daily_routine' for key records. The legacy 'diet' module remains available \ for existing diet-plan content. Provide the complete Markdown page and preserve \ - its established structure. Confirmed-memory sections are protected by Coffee Note \ + its established structure. Confirmed-memory sections are protected by TierNote \ and must not be invented, copied, removed, or rewritten by the model." .into(), parameters: json!({ @@ -435,7 +435,7 @@ pub fn get_tool_definitions(availability: ToolAvailability) -> Vec { }, ToolDef { name: "create_video".into(), - description: "Compose an MP4 video in the user's configured generated-files directory from an ordered list of workspace images, generated narration, burned-in captions, and restrained pan/zoom motion. Generate every scene image first, then submit the complete timeline in one call. The runtime uses the user's configured speech service and the bundled Coffee Video encoder.".into(), + description: "Compose an MP4 video in the user's configured generated-files directory from an ordered list of workspace images, generated narration, burned-in captions, and restrained pan/zoom motion. Generate every scene image first, then submit the complete timeline in one call. The runtime uses the user's configured speech service and the bundled TierNote Video encoder.".into(), parameters: json!({ "type": "object", "properties": { @@ -516,7 +516,7 @@ pub fn get_tool_definitions(availability: ToolAvailability) -> Vec { description: "Suggest one to three long-term memory candidates for the user to confirm. \ Use only for durable user-stated goals, preferences, constraints, corrections, profile facts, or health context that should help future conversations. \ This tool does not save memory; it only asks the frontend to show confirmation cards. \ - Once confirmed, Coffee Note writes the fact into a visible page under My information and keeps only source metadata in its local memory index.".into(), + Once confirmed, TierNote writes the fact into a visible page under My information and keeps only source metadata in its local memory index.".into(), parameters: json!({ "type": "object", "properties": { diff --git a/src-tauri/src/channels.rs b/src-tauri/src/channels.rs index 86fca31..997c2ac 100644 --- a/src-tauri/src/channels.rs +++ b/src-tauri/src/channels.rs @@ -1,8 +1,8 @@ -//! Local messaging channels for Coffee Note. +//! Local messaging channels for TierNote. //! //! The Weixin transport follows Tencent's MIT-licensed `openclaw-weixin` //! implementation and public iLink HTTP/JSON protocol. Linked private chats are -//! alternate entry points into Coffee Note's regular local conversation agent. +//! alternate entry points into TierNote's regular local conversation agent. use base64::Engine; use serde::{Deserialize, Serialize}; @@ -486,7 +486,7 @@ fn weixin_headers(token: Option<&str>) -> reqwest::header::HeaderMap { fn weixin_base_info() -> Value { json!({ "channel_version": CHANNEL_VERSION, - "bot_agent": format!("CoffeeNote/{CHANNEL_VERSION}") + "bot_agent": format!("TierNote/{CHANNEL_VERSION}") }) } @@ -739,7 +739,7 @@ pub async fn connect_telegram( let bot_name = response .pointer("/result/username") .and_then(Value::as_str) - .unwrap_or("Coffee Note bot"); + .unwrap_or("TierNote bot"); let settings = mutate_settings(|settings| { settings.telegram.enabled = true; settings.telegram.bot_token = token.to_string(); @@ -1303,7 +1303,7 @@ async fn telegram_loop(app: AppHandle, cancel: CancellationToken) { let _ = telegram_send( &token, &chat_id, - "Coffee Note 已连接。现在可以像在客户端一样直接对话;发送链接时,AI 也可以整理并保存为本地笔记。", + "TierNote 已连接。现在可以像在客户端一样直接对话;发送链接时,AI 也可以整理并保存为本地笔记。", ) .await; set_status(&app, "telegram", "connected", ""); diff --git a/src-tauri/src/document.rs b/src-tauri/src/document.rs index 2bdbd6e..8ed2a13 100644 --- a/src-tauri/src/document.rs +++ b/src-tauri/src/document.rs @@ -322,7 +322,7 @@ fn content_types_xml() -> String { fn core_properties_xml(request: &DocumentRequest, created: &str) -> String { format!( - r#"{}{}Coffee Note{created}{created}"#, + r#"{}{}TierNote{created}{created}"#, xml_escape(&request.title), xml_escape(&request.author) ) @@ -630,12 +630,12 @@ fn xml_escape(value: &str) -> String { const ROOT_RELS: &str = r#""#; const DOCUMENT_RELS: &str = r#""#; -const APP_PROPERTIES: &str = r#"Coffee Note1.0"#; +const APP_PROPERTIES: &str = r#"TierNote1.0"#; const SETTINGS: &str = r#""#; const FONT_TABLE: &str = r#""#; const NUMBERING: &str = r#""#; const STYLES: &str = r#""#; -const THEME: &str = r#""#; +const THEME: &str = r#""#; #[cfg(test)] mod tests { @@ -664,7 +664,7 @@ mod tests { request(json!({ "title": "项目复盘", "format": "docx", - "subtitle": "Coffee Note 文档", + "subtitle": "TierNote 文档", "author": "测试作者", "blocks": [ {"type": "heading", "level": 1, "text": "关键结论"}, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index e66f4b7..0ba5198 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -36,22 +36,20 @@ const MAX_CAPTURE_INPUT_BYTES: usize = 180_000; const MAX_CAPTURE_DOWNLOAD_BYTES: usize = 600_000; const MAX_CAPTURE_SOURCE_BYTES: usize = 110_000; const MAX_RESEARCH_CONTEXT_BYTES: usize = 32_000; -const LATEST_RELEASE_API: &str = - "https://api.github.com/repos/edison7009/Coffee-Note/releases/latest"; -const WEBSITE_VERSION_API: &str = "https://note.coffeecli.com/version.json?platform=windows"; +const LATEST_RELEASE_API: &str = "https://api.github.com/repos/edison7009/TierNote/releases/latest"; +const WEBSITE_VERSION_API: &str = "https://tiernote.org/version.json?platform=windows"; #[cfg(target_os = "windows")] -const WEBSITE_WINDOWS_DOWNLOAD: &str = "https://note.coffeecli.com/download/windows"; +const WEBSITE_WINDOWS_DOWNLOAD: &str = "https://tiernote.org/download/windows"; #[cfg(target_os = "windows")] -const RELEASE_DOWNLOAD_PREFIX: &str = - "https://github.com/edison7009/Coffee-Note/releases/download/"; +const RELEASE_DOWNLOAD_PREFIX: &str = "https://github.com/edison7009/TierNote/releases/download/"; const TRANSCRIPTION_CONFIG_FILE: &str = "transcription.json"; const IMAGE_SETTINGS_CONFIG_FILE: &str = "image-models.json"; const LEGACY_MULTIMODAL_CONFIG_FILE: &str = "multimodal.json"; const MAX_AGENT_IMAGE_BYTES: u64 = 20 * 1024 * 1024; const TIER_METADATA_MAX_BYTES: u64 = 32 * 1024; const TIER_ORDER_RELATIVE_PATH: &str = ".coffee-note/tier-order.json"; -pub(crate) const MODEL_APP_URL: &str = "https://note.coffeecli.com"; -pub(crate) const MODEL_APP_TITLE: &str = "Coffee Note"; +pub(crate) const MODEL_APP_URL: &str = "https://tiernote.org"; +pub(crate) const MODEL_APP_TITLE: &str = "TierNote"; include!(concat!(env!("OUT_DIR"), "/starter_files.rs")); #[derive(Debug, Clone, Serialize)] @@ -440,20 +438,22 @@ impl From for ModelSettings { pub(crate) fn app_data_dir() -> PathBuf { let base = dirs::data_local_dir().unwrap_or_else(|| PathBuf::from(".")); + // Keep the v0.1.8 data location so the rebrand does not strand provider + // credentials, conversations, plugins, or message-channel state. base.join("Coffee Note") } -fn coffee_note_home() -> PathBuf { +fn legacy_workspace_home() -> PathBuf { let base = dirs::home_dir().unwrap_or_else(|| PathBuf::from(".")); base.join(".coffee-note") } fn my_info_root() -> PathBuf { - coffee_note_home().join("我的资料") + legacy_workspace_home().join("我的资料") } fn default_knowledge_root() -> PathBuf { - coffee_note_home().join("我的笔记(演示)") + legacy_workspace_home().join("我的笔记(演示)") } fn model_config_path() -> PathBuf { @@ -551,7 +551,7 @@ async fn check_transcription_config( .post(endpoint) .header("Content-Type", "application/octet-stream"), } - .header("User-Agent", "Coffee Note"); + .header("User-Agent", "TierNote"); request = match provider.protocol.as_str() { "deepgram" => request.header( "Authorization", @@ -3226,7 +3226,7 @@ async fn fetch_capture_source(url: &reqwest::Url) -> Result { .ok_or_else(|| "The source URL has no usable port".to_string())?; let mut builder = reqwest::Client::builder() .timeout(Duration::from_secs(35)) - .user_agent("Coffee-Note/0.0.1") + .user_agent("TierNote/0.0.1") .redirect(reqwest::redirect::Policy::custom({ let source_host = source_host.clone(); move |attempt| { @@ -3534,7 +3534,7 @@ async fn prepare_capture(request: PrepareCaptureRequest) -> Result Option { fn research_client() -> Result { reqwest::Client::builder() .user_agent(format!( - "Coffee-Note/{} (scientific evidence search)", + "TierNote/{} (scientific evidence search)", env!("CARGO_PKG_VERSION") )) .timeout(Duration::from_secs(28)) @@ -3681,7 +3681,7 @@ async fn search_pubmed( ("retmode", "json"), ("retmax", "4"), ("sort", "relevance"), - ("tool", "Coffee Note"), + ("tool", "TierNote"), ]) .send() .await @@ -3703,7 +3703,7 @@ async fn search_pubmed( ("db", "pubmed"), ("id", joined_ids.as_str()), ("retmode", "json"), - ("tool", "Coffee Note"), + ("tool", "TierNote"), ]) .send() .await @@ -3743,7 +3743,7 @@ async fn search_pubmed( ("id", joined_ids.as_str()), ("rettype", "abstract"), ("retmode", "xml"), - ("tool", "Coffee Note"), + ("tool", "TierNote"), ]) .send() .await @@ -4082,7 +4082,7 @@ async fn chat_completion(request: ChatRequest) -> Result { "使用简体中文回答。" }; let system_prompt = format!( - "You are Coffee Note, a local-first general-purpose workspace assistant. \ + "You are TierNote, a local-first general-purpose workspace assistant. \ The selected directory may be a code repository, writing project, note collection, or any other \ workspace. Do not assume a fixed note architecture and do not refuse programming or other \ non-note work. Use supplied local context when it is relevant, and cite its file path in \ @@ -4138,7 +4138,7 @@ async fn chat_completion(request: ChatRequest) -> Result { fn release_client() -> Result { reqwest::Client::builder() - .user_agent(format!("Coffee-Note/{}", env!("CARGO_PKG_VERSION"))) + .user_agent(format!("TierNote/{}", env!("CARGO_PKG_VERSION"))) .timeout(Duration::from_secs(30)) .build() .map_err(|error| format!("Unable to prepare the update request: {error}")) @@ -4292,7 +4292,7 @@ async fn run_windows_update(app: tauri::AppHandle) -> Result<(), String> { } let expected_size = expected_asset_size.max(response.content_length().unwrap_or(0)); - let installer_path = std::env::temp_dir().join("Coffee-Note-update-setup.exe"); + let installer_path = std::env::temp_dir().join("TierNote-update-setup.exe"); let mut installer = fs::File::create(&installer_path) .map_err(|error| format!("Unable to create the update installer: {error}"))?; let mut downloaded = 0_u64; @@ -4504,7 +4504,7 @@ fn configure_tray_menu(app: &tauri::AppHandle, locale: &str) -> tauri::Result<() let quit = MenuItem::with_id(app, "quit", quit_label, true, None::<&str>)?; let menu = Menu::with_items(app, &[&show_app, &quit])?; let tray = app.tray_by_id("main").ok_or_else(|| { - tauri::Error::AssetNotFound("Coffee Note tray icon was not initialized".into()) + tauri::Error::AssetNotFound("TierNote tray icon was not initialized".into()) })?; tray.set_menu(Some(menu)) } @@ -4639,7 +4639,7 @@ pub fn run() { ]) .manage(transcription::TranscriptionDownloadState::default()) .run(tauri::generate_context!()) - .expect("error while running Coffee Note"); + .expect("error while running TierNote"); } #[cfg(test)] @@ -5616,8 +5616,8 @@ mod tests { let request = String::from_utf8_lossy(&request_bytes[..read]); let request_headers = request.to_ascii_lowercase(); assert!(request.starts_with("POST /v1/chat/completions ")); - assert!(request_headers.contains("http-referer: https://note.coffeecli.com")); - assert!(request_headers.contains("x-openrouter-title: coffee note")); + assert!(request_headers.contains("http-referer: https://tiernote.org")); + assert!(request_headers.contains("x-openrouter-title: tiernote")); assert!(request.contains("\"max_tokens\":3000")); assert!(request.contains("\"reasoning_effort\":\"high\"")); let model_content = @@ -5698,8 +5698,8 @@ mod tests { let request_headers = request.to_ascii_lowercase(); assert!(request.starts_with("POST /v1/messages ")); assert!(request_headers.contains("x-api-key: test-key")); - assert!(request_headers.contains("http-referer: https://note.coffeecli.com")); - assert!(request_headers.contains("x-openrouter-title: coffee note")); + assert!(request_headers.contains("http-referer: https://tiernote.org")); + assert!(request_headers.contains("x-openrouter-title: tiernote")); assert!(request.contains("\"output_config\":{\"effort\":\"medium\"}")); assert!(request.contains("\"system\":\"System rule\"")); let payload = json!({ diff --git a/src-tauri/src/llm_stream.rs b/src-tauri/src/llm_stream.rs index e97fff3..a0d7687 100644 --- a/src-tauri/src/llm_stream.rs +++ b/src-tauri/src/llm_stream.rs @@ -1,5 +1,5 @@ // LLM Client — OpenAI and Anthropic protocols with SSE streaming. -// Ported from EchoBird's services/llm_client.rs and adapted to Coffee Note. +// Ported from EchoBird's services/llm_client.rs and adapted to TierNote. use futures_util::StreamExt; use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION, CONTENT_TYPE}; @@ -1024,12 +1024,12 @@ mod tests { use super::*; #[test] - fn app_attribution_headers_identify_coffee_note() { + fn app_attribution_headers_identify_tiernote() { let mut headers = HeaderMap::new(); insert_app_attribution_headers(&mut headers); - assert_eq!(headers["HTTP-Referer"], "https://note.coffeecli.com"); - assert_eq!(headers["X-OpenRouter-Title"], "Coffee Note"); - assert_eq!(headers["X-Title"], "Coffee Note"); + assert_eq!(headers["HTTP-Referer"], "https://tiernote.org"); + assert_eq!(headers["X-OpenRouter-Title"], "TierNote"); + assert_eq!(headers["X-Title"], "TierNote"); } #[test] diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 89281cc..3739a9b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,5 +1,5 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { - coffee_note_lib::run(); + tiernote_lib::run(); } diff --git a/src-tauri/src/presentation.rs b/src-tauri/src/presentation.rs index e42728f..4233b8c 100644 --- a/src-tauri/src/presentation.rs +++ b/src-tauri/src/presentation.rs @@ -594,14 +594,14 @@ fn content_types(slide_count: usize, images: &[Option]) -> String { fn app_properties(slide_count: usize) -> String { format!( - r#"Coffee NoteWidescreen{slide_count}00falseCoffee Note1.0"# + r#"TierNoteWidescreen{slide_count}00falseTierNote1.0"# ) } fn core_properties(title: &str) -> String { let timestamp = Utc::now().format("%Y-%m-%dT%H:%M:%SZ"); format!( - r#"{}Coffee NoteCoffee Note{timestamp}{timestamp}"#, + r#"{}TierNoteTierNote{timestamp}{timestamp}"#, xml_escape(title) ) } @@ -629,14 +629,14 @@ fn presentation_rels(slide_count: usize) -> String { fn slide_master_xml(theme: DeckTheme) -> String { format!( - r#""#, + r#""#, theme.background ) } fn theme_xml(theme: DeckTheme) -> String { format!( - r#""#, + r#""#, theme.foreground, theme.background, theme.muted, theme.panel, theme.accent ) } @@ -1062,7 +1062,7 @@ mod tests { "title": "季度复盘", "theme": "business", "slides": [ - {"layout": "title", "title": "季度复盘", "subtitle": "Coffee Note"}, + {"layout": "title", "title": "季度复盘", "subtitle": "TierNote"}, {"layout": "two-column", "title": "结果与下一步", "body": ["收入稳步增长"], "rightBody": ["扩大重点渠道"]} ] })), diff --git a/src-tauri/src/skills.rs b/src-tauri/src/skills.rs index c034a98..a3ee227 100644 --- a/src-tauri/src/skills.rs +++ b/src-tauri/src/skills.rs @@ -141,7 +141,7 @@ fn default_builtin_plugins() -> BTreeMap { fn builtin_media_manifest() -> BuiltinPluginManifest { let manifest: BuiltinPluginManifest = serde_json::from_str(BUILTIN_MEDIA_PLUGIN_MANIFEST) - .expect("the bundled Coffee Media manifest must be valid JSON"); + .expect("the bundled TierNote Media manifest must be valid JSON"); debug_assert_eq!(manifest.schema_version, 1); debug_assert_eq!(manifest.id, BUILTIN_MEDIA_PLUGIN_ID); debug_assert_eq!(manifest.runtime.lifecycle, "application"); @@ -153,7 +153,7 @@ fn builtin_media_manifest() -> BuiltinPluginManifest { fn builtin_presentation_manifest() -> BuiltinPluginManifest { let manifest: BuiltinPluginManifest = serde_json::from_str(BUILTIN_PRESENTATION_PLUGIN_MANIFEST) - .expect("the bundled Coffee Presentation manifest must be valid JSON"); + .expect("the bundled TierNote Presentation manifest must be valid JSON"); debug_assert_eq!(manifest.schema_version, 1); debug_assert_eq!(manifest.id, BUILTIN_PRESENTATION_PLUGIN_ID); debug_assert_eq!(manifest.runtime.lifecycle, "application"); @@ -164,7 +164,7 @@ fn builtin_presentation_manifest() -> BuiltinPluginManifest { fn builtin_document_manifest() -> BuiltinPluginManifest { let manifest: BuiltinPluginManifest = serde_json::from_str(BUILTIN_DOCUMENT_PLUGIN_MANIFEST) - .expect("the bundled Coffee Documents manifest must be valid JSON"); + .expect("the bundled TierNote Documents manifest must be valid JSON"); debug_assert_eq!(manifest.schema_version, 1); debug_assert_eq!(manifest.id, BUILTIN_DOCUMENT_PLUGIN_ID); debug_assert_eq!(manifest.runtime.lifecycle, "application"); @@ -175,7 +175,7 @@ fn builtin_document_manifest() -> BuiltinPluginManifest { fn builtin_video_manifest() -> BuiltinPluginManifest { let manifest: BuiltinPluginManifest = serde_json::from_str(BUILTIN_VIDEO_PLUGIN_MANIFEST) - .expect("the bundled Coffee Video manifest must be valid JSON"); + .expect("the bundled TierNote Video manifest must be valid JSON"); debug_assert_eq!(manifest.schema_version, 1); debug_assert_eq!(manifest.id, BUILTIN_VIDEO_PLUGIN_ID); debug_assert_eq!(manifest.runtime.lifecycle, "application"); diff --git a/src-tauri/src/transcription.rs b/src-tauri/src/transcription.rs index 33c081f..c6f5cdd 100644 --- a/src-tauri/src/transcription.rs +++ b/src-tauri/src/transcription.rs @@ -760,7 +760,7 @@ fn needs_fresh_browser_cookies(stderr: &[u8]) -> bool { /// Return only browsers that appear to have a local profile. Cookie extraction /// is used as a narrow retry for Douyin's fresh-session challenge; cookies stay -/// in the yt-dlp child process and are never exported or persisted by Coffee Note. +/// in the yt-dlp child process and are never exported or persisted by TierNote. fn browser_cookie_sources() -> Vec<&'static str> { let mut sources = Vec::new(); let mut add_if_present = |name: &'static str, path: PathBuf| { @@ -1094,7 +1094,7 @@ async fn download_fixed_file(spec: ResourceSpec, target: &Path) -> Result<(), St let partial = target.with_extension("part"); let response = reqwest::Client::new() .get(spec.url) - .header("User-Agent", "Coffee Note") + .header("User-Agent", "TierNote") .send() .await .map_err(|error| format!("Could not prepare media import: {error}"))? @@ -1154,7 +1154,7 @@ async fn ensure_media_fetcher() -> Result { } /// Prepare the small, pinned media-import dependency in the background after -/// Coffee Note starts. Speech runtimes and models remain explicit user downloads. +/// TierNote starts. Speech runtimes and models remain explicit user downloads. pub(crate) async fn prepare_media_environment() -> Result<(), String> { ensure_media_fetcher().await.map(|_| ()) } @@ -1334,7 +1334,7 @@ async fn download_media_audio( let message = String::from_utf8_lossy(&output.stderr).trim().to_string(); if retry_with_browser { return Err(format!( - "Douyin still rejected the fresh local browser session. Open the link in Edge, Chrome, or Firefox, refresh it, then retry. Coffee Note does not store browser cookies.{}", + "Douyin still rejected the fresh local browser session. Open the link in Edge, Chrome, or Firefox, refresh it, then retry. TierNote does not store browser cookies.{}", if message.is_empty() { String::new() } else { @@ -1629,7 +1629,7 @@ pub async fn download_transcription_resource( let partial = target_dir.join(format!("{}.part", spec.file_name)); let response = reqwest::Client::new() .get(spec.url) - .header("User-Agent", "Coffee Note") + .header("User-Agent", "TierNote") .send() .await .map_err(|error| format!("Could not download resource: {error}"))? @@ -1839,9 +1839,9 @@ mod tests { "https://www.bilibili.com/video/BVexample", "https://b23.tv/example", "https://v.douyin.com/example", - "https://www.tiktok.com/@coffeenote/video/1", + "https://www.tiktok.com/@tiernote/video/1", "https://www.xiaohongshu.com/explore/example", - "https://x.com/coffeenote/status/1", + "https://x.com/tiernote/status/1", ] { let url = reqwest::Url::parse(source).expect("fixture URL should parse"); assert!(supports_media_url(&url), "{source} should be supported"); @@ -1870,7 +1870,7 @@ mod tests { } for source in [ "https://douyin.com.evil.example/video/1", - "https://www.tiktok.com/@coffeenote/video/1", + "https://www.tiktok.com/@tiernote/video/1", "https://example.com/douyin.com", ] { let url = reqwest::Url::parse(source).expect("fixture URL should parse"); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 40ebcfb..50365a0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "$schema": "https://schema.tauri.app/config/2", - "productName": "Coffee Note", + "productName": "TierNote", "version": "0.1.8", "identifier": "app.coffeenote.desktop", "build": { @@ -18,7 +18,7 @@ "windows": [ { "label": "main", - "title": "Coffee Note", + "title": "TierNote", "width": 1360, "height": 860, "minWidth": 920, @@ -36,11 +36,11 @@ }, "bundle": { "active": true, - "publisher": "Coffee Team", + "publisher": "TierNote Team", "targets": "all", "category": "Productivity", "shortDescription": "Local-first notes organized with a clear tier system.", - "longDescription": "Coffee Note is a local-first AI second brain for knowledge, ideas, and clear decisions.", + "longDescription": "TierNote is a local-first AI second brain for knowledge, ideas, and clear decisions.", "icon": [ "icons/32x32.png", "icons/128x128.png", @@ -55,7 +55,7 @@ "nsis": { "template": "installer.nsi", "installerIcon": "icons/icon.ico", - "startMenuFolder": "Coffee Note" + "startMenuFolder": "TierNote" } } } diff --git a/src-tauri/tauri.macos.conf.json b/src-tauri/tauri.macos.conf.json index f98a6db..d065c47 100644 --- a/src-tauri/tauri.macos.conf.json +++ b/src-tauri/tauri.macos.conf.json @@ -3,7 +3,7 @@ "windows": [ { "label": "main", - "title": "Coffee Note", + "title": "TierNote", "width": 1360, "height": 860, "minWidth": 920, diff --git a/src/App.tsx b/src/App.tsx index ff8c802..ef0ec53 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -234,13 +234,13 @@ import { } from './transcriptionAvailability'; const APP_VERSION = packageMetadata.version; -const PRODUCT_WEBSITE = 'https://note.coffeecli.com/'; +const PRODUCT_WEBSITE = 'https://tiernote.org/'; const BUILTIN_MEDIA_SKILL_ID = 'coffee-note-media-transcribe'; const BUILTIN_DOCX_SKILL_ID = 'coffee-note-document-create-docx'; const BUILTIN_PDF_SKILL_ID = 'coffee-note-document-create-pdf'; const BUILTIN_PRESENTATION_SKILL_ID = 'coffee-note-presentation-create'; const BUILTIN_VIDEO_SKILL_ID = 'coffee-note-video-create'; -const FEEDBACK_URL = 'https://github.com/edison7009/Coffee-Note/issues'; +const FEEDBACK_URL = 'https://github.com/edison7009/TierNote/issues'; const CONVERSATION_USAGE_KEY = storageKey('conversation-usage:v1'); const CAPTURE_TRANSCRIPTION_MODE_KEY = storageKey('capture-transcription-mode:v1'); @@ -3946,7 +3946,7 @@ function AppTitlebar({ >
- Coffee Note + TierNote
@@ -4042,7 +4042,7 @@ function AppTitlebar({
diff --git a/src/api.ts b/src/api.ts index a42fc1b..03799d1 100644 --- a/src/api.ts +++ b/src/api.ts @@ -117,7 +117,7 @@ const fallbackSkillCatalog: SkillCatalog = { skillCount: 1, enabled: true, builtin: true, - publisher: 'Coffee Note', + publisher: 'TierNote', origin: 'bundled', runtimeId: 'media-transcription', }, @@ -132,7 +132,7 @@ const fallbackSkillCatalog: SkillCatalog = { skillCount: 1, enabled: true, builtin: true, - publisher: 'Coffee Note', + publisher: 'TierNote', origin: 'bundled', runtimeId: 'presentation-engine', }, @@ -147,7 +147,7 @@ const fallbackSkillCatalog: SkillCatalog = { skillCount: 2, enabled: true, builtin: true, - publisher: 'Coffee Note', + publisher: 'TierNote', origin: 'bundled', runtimeId: 'document-engine', }, @@ -166,7 +166,7 @@ function normalizeFallbackSkillCatalog(catalog: SkillCatalog): SkillCatalog { ...existing, id: fallback.id, builtin: true, - publisher: existing?.publisher ?? 'Coffee Note', + publisher: existing?.publisher ?? 'TierNote', origin: 'bundled' as const, }; }); @@ -211,7 +211,7 @@ function readFallbackSkillCatalog(): SkillCatalog { catalog.plugins = (catalog.plugins ?? []).map((plugin) => ({ ...plugin, enabled: plugin.enabled !== false, - publisher: plugin.publisher || (plugin.builtin ? 'Coffee Note' : 'Community'), + publisher: plugin.publisher || (plugin.builtin ? 'TierNote' : 'Community'), origin: plugin.origin || (plugin.builtin ? 'bundled' : 'git'), })); catalog.skills = (catalog.skills ?? []).map((skill) => ({ diff --git a/src/data.ts b/src/data.ts index 796d9c8..713bbd1 100644 --- a/src/data.ts +++ b/src/data.ts @@ -1,8 +1,8 @@ import type { LibrarySnapshot } from './types'; export const fallbackLibrary: LibrarySnapshot = { - root: 'Coffee Note Library', - myInfoRoot: 'Coffee Note Contexts', + root: 'TierNote Library', + myInfoRoot: 'TierNote Contexts', connected: true, priorities: [], people: [], diff --git a/src/i18n.ts b/src/i18n.ts index 06b8b2a..1a24c9e 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -2,7 +2,7 @@ import type { Locale } from './types'; const messages = { zh: { - appName: 'Coffee Note', + appName: 'TierNote', home: '首页', aiChat: 'AI对话', myPlan: '我的设定', @@ -42,7 +42,7 @@ const messages = { operationFailed: '操作失败', fileGone: '文件已不存在', contextFilesGone: '部分已选文件已不存在,已从 AI 对话中移除。', - filePreviewUnavailable: '此文件无法在 Coffee Note 中预览。', + filePreviewUnavailable: '此文件无法在 TierNote 中预览。', fileContextReady: '它已添加到下方 AI 对话,可直接让 AI 处理这个文件。', fileContextNotAttached: '可从左侧文件树或右键菜单重新添加到 AI 对话。', people: '选择', @@ -127,7 +127,7 @@ const messages = { captureSub: '粘贴链接、文字或零散笔记,AI 整理后会直接进入对话。', captureStep1: '复制任何与当前目标有关的链接、文字或笔记。', captureStep2: '直接粘贴,不必先分类或改格式。', - captureStep3: '告诉 Coffee Note 你想看清什么选择,或下一步该做什么。', + captureStep3: '告诉 TierNote 你想看清什么选择,或下一步该做什么。', captureTranscriptionApi: '语音模型', captureTranscriptionLocal: '本地语音模型', captureTranscriptionPrefix: '语音识别方式:', @@ -180,7 +180,7 @@ const messages = { peopleCard: '我的设定', peopleCardSub: '沉淀经验与教训,连接长期目标与短期计划', mapCard: '校准优先级', - mapCardSub: '拖动内容,告诉 Coffee Note 什么更重要', + mapCardSub: '拖动内容,告诉 TierNote 什么更重要', aiPlanCard: '与AI对话', aiPlanCardSub: '创造新文案、生成文档、PPT或视频,帮你搞定!', planTitle: '我的设定', @@ -189,7 +189,7 @@ const messages = { comingSoon: '这里会逐步沉淀你的长期个人信息。', }, en: { - appName: 'Coffee Note', + appName: 'TierNote', home: 'Home', aiChat: 'AI Chat', myPlan: 'My Contexts', @@ -229,7 +229,7 @@ const messages = { operationFailed: 'Operation failed', fileGone: 'File no longer exists', contextFilesGone: 'Some selected files no longer exist and were removed from AI chat.', - filePreviewUnavailable: 'This file cannot be previewed in Coffee Note.', + filePreviewUnavailable: 'This file cannot be previewed in TierNote.', fileContextReady: 'It is attached to the AI chat below, ready for an AI request.', fileContextNotAttached: 'Add it to AI chat again from the file tree or context menu.', people: 'Choices', diff --git a/src/settings/MessageSettings.tsx b/src/settings/MessageSettings.tsx index 46cf647..178cf5f 100644 --- a/src/settings/MessageSettings.tsx +++ b/src/settings/MessageSettings.tsx @@ -166,8 +166,8 @@ export function MessageSettings({ locale }: { locale: Locale }) {

{locale === 'zh' ? '消息渠道' : 'Message channels'}

{locale === 'zh' - ? '连接后可像在客户端一样与 Coffee Note 对话;AI 会按你的意图回答、读取或整理本地笔记,单独发送链接也可以转成文档。手机对话会同步到客户端的对话记录。' - : 'Chat with Coffee Note from your phone just like in the desktop app. AI can answer, use local notes, or turn a shared link into a document, and the conversation appears in desktop history.'} + ? '连接后可像在客户端一样与 TierNote 对话;AI 会按你的意图回答、读取或整理本地笔记,单独发送链接也可以转成文档。手机对话会同步到客户端的对话记录。' + : 'Chat with TierNote from your phone just like in the desktop app. AI can answer, use local notes, or turn a shared link into a document, and the conversation appears in desktop history.'}

{connectedCount > 0 @@ -319,8 +319,8 @@ export function MessageSettings({ locale }: { locale: Locale }) {

{locale === 'zh' - ? '仅接受已绑定账号的私聊。手机端使用与客户端相同的 AI 工作区能力,因此可以按你的要求读取、创建或修改当前工作区中的代码、文档和笔记;它不能执行终端命令或修改应用设置。电脑需保持开机,Coffee Note 可在后台运行。' - : 'Only direct messages from the paired account are accepted. Phone chats use the same AI workspace capabilities as the desktop app, so they can read, create, or edit code, documents, and notes in the current workspace when asked; they cannot run terminal commands or change app settings. Keep this computer on with Coffee Note running in the background.'} + ? '仅接受已绑定账号的私聊。手机端使用与客户端相同的 AI 工作区能力,因此可以按你的要求读取、创建或修改当前工作区中的代码、文档和笔记;它不能执行终端命令或修改应用设置。电脑需保持开机,TierNote 可在后台运行。' + : 'Only direct messages from the paired account are accepted. Phone chats use the same AI workspace capabilities as the desktop app, so they can read, create, or edit code, documents, and notes in the current workspace when asked; they cannot run terminal commands or change app settings. Keep this computer on with TierNote running in the background.'}

); diff --git a/src/settings/SkillsSettings.tsx b/src/settings/SkillsSettings.tsx index 831b98c..eb81b66 100644 --- a/src/settings/SkillsSettings.tsx +++ b/src/settings/SkillsSettings.tsx @@ -44,7 +44,7 @@ function categoryLabel(id: string, fallback: string, locale: Locale) { } function pluginName(plugin: SkillPlugin, locale: Locale) { - if (locale === 'en' && plugin.id === 'coffee-media') return 'Coffee Media'; + if (locale === 'en' && plugin.id === 'coffee-media') return 'TierNote Media'; if (locale === 'en' && plugin.id === 'coffee-documents') return 'Documents'; if (locale === 'en' && plugin.id === 'coffee-presentation') return 'Presentations'; return plugin.name; @@ -518,8 +518,8 @@ export function SkillsSettings({

{locale === 'zh' - ? '支持 Coffee 插件清单,以及包含一个或多个 SKILL.md 的 Git 技能包。第三方代码和运行时不会自动执行。' - : 'Supports Coffee manifests and Git packages containing one or more SKILL.md files. Third-party code and runtimes are never executed automatically.'} + ? '支持 TierNote 插件清单,以及包含一个或多个 SKILL.md 的 Git 技能包。第三方代码和运行时不会自动执行。' + : 'Supports TierNote manifests and Git packages containing one or more SKILL.md files. Third-party code and runtimes are never executed automatically.'}

diff --git a/tests/ai-context-copy.test.mjs b/tests/ai-context-copy.test.mjs index 99303c4..e240143 100644 --- a/tests/ai-context-copy.test.mjs +++ b/tests/ai-context-copy.test.mjs @@ -8,7 +8,7 @@ const i18nSource = readFileSync(new URL('../src/i18n.ts', import.meta.url), 'utf test('AI chat card copy promotes creating copy, documents, PPTs, or videos', () => { assert.match(i18nSource, /创造新文案、生成文档、PPT或视频,帮你搞定!/); assert.match(i18nSource, /Create copy, documents, PPTs, or videos, done for you!/); - assert.doesNotMatch(appSource, /把当前目标和相关资料交给 Coffee Note/); + assert.doesNotMatch(appSource, /把当前目标和相关资料交给 TierNote/); }); test('media card English copy describes transcription rather than generic organizing', () => { diff --git a/tests/message-channels.test.mjs b/tests/message-channels.test.mjs index 9ec6b4a..4a68ec7 100644 --- a/tests/message-channels.test.mjs +++ b/tests/message-channels.test.mjs @@ -31,7 +31,7 @@ test('Weixin follows Tencent iLink QR login and long polling', () => { assert.match(rustSource, /ilink\/bot\/get_qrcode_status/); assert.match(rustSource, /ilink\/bot\/getupdates/); assert.match(rustSource, /ilink\/bot\/sendmessage/); - assert.match(rustSource, /CoffeeNote\/\{CHANNEL_VERSION\}/); + assert.match(rustSource, /TierNote\/\{CHANNEL_VERSION\}/); }); test('channel messages enter the shared persisted conversation agent', () => { @@ -47,7 +47,7 @@ test('channel messages enter the shared persisted conversation agent', () => { assert.match(rustSource, /"message-conversation-updated"/); assert.doesNotMatch(rustSource, /process_capture|prepare_capture\(super::PrepareCaptureRequest|super::save_capture/); assert.doesNotMatch(rustSource, /收到,正在整理并保存/); - assert.match(settingsSource, /像在客户端一样与 Coffee Note 对话/); + assert.match(settingsSource, /像在客户端一样与 TierNote 对话/); assert.match(settingsSource, /手机对话会同步到客户端的对话记录/); assert.match(apiSource, /listenMessageConversationUpdated/); assert.match(appSource, /listenMessageConversationUpdated\(\(conversationId\)/); diff --git a/tests/settings-workspace.test.mjs b/tests/settings-workspace.test.mjs index 8ee2e26..98028b2 100644 --- a/tests/settings-workspace.test.mjs +++ b/tests/settings-workspace.test.mjs @@ -10,7 +10,7 @@ const desktopCapabilities = readFileSync( ); test('desktop brand link keeps the current production domain', () => { - assert.match(appSource, /const PRODUCT_WEBSITE = 'https:\/\/note\.coffeecli\.com\/'/); + assert.match(appSource, /const PRODUCT_WEBSITE = 'https:\/\/tiernote\.org\/'/); }); test('settings replaces the three-pane workspace instead of opening a modal', () => { @@ -58,7 +58,7 @@ test('settings navigation rail stays compact', () => { test('settings footer stacks feedback above the product version', () => { assert.match( appSource, - /
[\s\S]*?FEEDBACK_URL[\s\S]*?Coffee Note · v\{APP_VERSION\}/s, + /
[\s\S]*?FEEDBACK_URL[\s\S]*?TierNote · v\{APP_VERSION\}/s, ); assert.match( styles, diff --git a/tests/sidebar-actions.test.mjs b/tests/sidebar-actions.test.mjs index 3588300..134c7ce 100644 --- a/tests/sidebar-actions.test.mjs +++ b/tests/sidebar-actions.test.mjs @@ -21,7 +21,7 @@ test('title bar uses the aligned wordmark without a duplicate logo', () => { /
]*>([\s\S]*?)<\/div>/s, )?.[1]; assert.ok(titlebarBrand, 'titlebar brand markup should exist'); - assert.match(titlebarBrand, /Coffee Note<\/strong>/); + assert.match(titlebarBrand, /TierNote<\/strong>/); assert.doesNotMatch(titlebarBrand, /([\s\S]*?)<\/div>/s, diff --git a/tests/skills-management-ui.test.mjs b/tests/skills-management-ui.test.mjs index 1884e39..bc94714 100644 --- a/tests/skills-management-ui.test.mjs +++ b/tests/skills-management-ui.test.mjs @@ -49,7 +49,7 @@ test('plugin source form only asks for Git address and category', () => { assert.match(settingsSource, /编辑技能插件|Edit skill plugin/); assert.doesNotMatch(settingsSource, /modal-backdrop|aria-modal|title=|window\.confirm|plugin-dialog|askConfirmation/); assert.match(settingsSource, /一个插件可以包含多个小技能/); - assert.match(settingsSource, /支持 Coffee 插件清单/); + assert.match(settingsSource, /支持 TierNote 插件清单/); assert.match(cssSource, /\.skills-package-grid\s*\{[^}]*grid-template-columns:\s*repeat\(2, minmax\(0, 1fr\)\);/s); }); diff --git a/tests/workspace-file-tree-ui.test.mjs b/tests/workspace-file-tree-ui.test.mjs index d4806bd..f32410d 100644 --- a/tests/workspace-file-tree-ui.test.mjs +++ b/tests/workspace-file-tree-ui.test.mjs @@ -66,7 +66,7 @@ test('non-Markdown files show a restrained unsupported-preview state', () => { assert.match(app, /filePreviewSupported && \(\s*__.` +// Asset filenames follow `TierNote___.` // (renamed by the release.yml CI step). Keys are the platform slugs that // install.ps1 / install.sh / docs/RELEASE.md request; each slug maps to a // single asset. The old/pre-rename patterns are kept as a fallback so a @@ -47,7 +47,7 @@ async function latestAssets() { const response = await fetch(`https://api.github.com/repos/${REPO}/releases/latest`, { headers: { Accept: "application/vnd.github+json", - "User-Agent": "Coffee-Note-Website", + "User-Agent": "TierNote-Website", }, cf: { cacheEverything: true, cacheTtl: 300 }, }); @@ -105,7 +105,7 @@ export default { const asset = (await latestAssets())[platform]; if (!asset) return new Response("Installer is not available yet", { status: 404 }); - const file = await fetch(asset.url, { headers: { "User-Agent": "Coffee-Note-Website" } }); + const file = await fetch(asset.url, { headers: { "User-Agent": "TierNote-Website" } }); if (!file.ok) return new Response("Unable to download installer", { status: 502 }); return new Response(file.body, { @@ -114,7 +114,7 @@ export default { "Content-Disposition": `attachment; filename="${asset.name}"`, "Content-Length": file.headers.get("Content-Length") ?? "", "Cache-Control": "no-store", - "X-Coffee-Note-Version": asset.version, + "X-TierNote-Version": asset.version, }, }); } catch (error) { diff --git a/website/index.html b/website/index.html index 4c7f12b..eba57d9 100644 --- a/website/index.html +++ b/website/index.html @@ -3,8 +3,8 @@ -Coffee Note — The AI note tool that saves you money, deeply optimized for DeepSeek - +TierNote — The AI note tool that saves you money, deeply optimized for DeepSeek + @@ -412,14 +412,14 @@