Coco's version string does not adhere to semver's spec, so we had to
write a custom deserialization impl to do the conversion:
```
0.9.1-SNPASHOT-2560 => 0.9.1-SNAPSHOT.2560
```
But we forget to serialize versions to Coco's format when writing
extensions to disk. When Coco reads extension from disk, it sees
valid semantic versions, which are not expected:
```
[WAR] [third_party:167] invalid extension: [base64-converter]:
field [minimum_coco_version] has invalid version:
failed to parse build number 'SNAPSHOT.2560'', caused by: ['invalid digit found in string']
```
This commit provides a custom serialization impl to fix the issue.
* chore: show error msg (not err code) when installing exts via deeplink fails
When installing extensions via deeplink fails, previous implementation
showed the raw error code returned from the backend interfaces, which
is not user-friendly. We now call installExtensionError() to interrupt
the error code to get a human-readable error message, then show it to
the users.
* fix: correct install extension error when installing via store
* feat: add selection window page
* fix: chat input
* feat: add selection page
* chore: add
* chore: test
* feat: add
* feat: add store
* feat: add selection settings
* chore: remove unused code
* docs: add release note
* docs: add release note
* chore: format code
* chore: format code
* fix: copy error
* disable hashbrown default feature
* Enable unstable feature allocator_api
To make coco-app compile in CI:
```
--> /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hashbrown-0.15.5/src/raw/mod.rs:3856:12
|
3856 | impl<T, A: Allocator> RawIntoIter<T, A> {
| ^^^^^^^^^
|
= note: see issue #32838 <https://github.com/rust-lang/rust/issues/32838> for more information
= help: add `#![feature(allocator_api)]` to the crate attributes to enable
= note: this compiler was built on 2025-06-25; consider upgrading it if it is out of date
```
I don't know why it does not compile, feature `allocator-api2` is
enabled for `hashbrown 0.15.5`, so technically [1] it should not use the
allocator APIs from the std. According to [2], enabling the `nightly`
feature of `allocator-api2` may cause this issue as well, but it is not
enabled in our case either.
Anyway, enabling `#![feature(allocator_api)]` should make it work.
[1]: b751eef8e9/src/raw/alloc.rs (L26-L47)
[2]: https://github.com/rust-lang/hashbrown/issues/564
* put it in main.rs
* format main.rs
* Enable default-features for hashbrown 0.15.5
* format main.rs
* enable feature allocator-api2
* feat: add selection set config
* fix: selection setting
* fix: ci error
* fix: ci error
* fix: ci error
* fix: ci error
* merge: merge main
* fix: rust code warn
* fix: rust code error
* fix: rust code error
* fix: selection settings
* style: selection styles
* style: selection styles
* feat: selection settings add & delete
* feat: selection settings add & delete
* feat: selection settings add & delete
* style: selection styles
* chore: add @tauri-store/zustand plugin
* refactor: the selection store using @tauri-store/zustand
* fix: data error
* fix: data error
* chore: remove config
* chore: selection
* chore: selection
* chore: width
* chore: ignore selection in the app itself
* style: selection styles
* style: remove
* docs: add notes
* chore: add permission check
* chore: selection
* chore: style & store
---------
Co-authored-by: Steve Lau <stevelauc@outlook.com>
* chore: add @tauri-store/zustand plugin
* refactor: the selection store using @tauri-store/zustand
* fix: data error
* fix: data error
* chore: remove config
* feat: add selection window page
* fix: chat input
* feat: add selection page
* chore: add
* chore: test
* feat: add
* feat: add store
* feat: add selection settings
* chore: remove unused code
* docs: add release note
* docs: add release note
* chore: format code
* chore: format code
* fix: copy error
* disable hashbrown default feature
* Enable unstable feature allocator_api
To make coco-app compile in CI:
```
--> /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hashbrown-0.15.5/src/raw/mod.rs:3856:12
|
3856 | impl<T, A: Allocator> RawIntoIter<T, A> {
| ^^^^^^^^^
|
= note: see issue #32838 <https://github.com/rust-lang/rust/issues/32838> for more information
= help: add `#![feature(allocator_api)]` to the crate attributes to enable
= note: this compiler was built on 2025-06-25; consider upgrading it if it is out of date
```
I don't know why it does not compile, feature `allocator-api2` is
enabled for `hashbrown 0.15.5`, so technically [1] it should not use the
allocator APIs from the std. According to [2], enabling the `nightly`
feature of `allocator-api2` may cause this issue as well, but it is not
enabled in our case either.
Anyway, enabling `#![feature(allocator_api)]` should make it work.
[1]: b751eef8e9/src/raw/alloc.rs (L26-L47)
[2]: https://github.com/rust-lang/hashbrown/issues/564
* put it in main.rs
* format main.rs
* Enable default-features for hashbrown 0.15.5
* format main.rs
* enable feature allocator-api2
* feat: add selection set config
* fix: selection setting
* fix: ci error
* fix: ci error
* fix: ci error
* fix: ci error
* merge: merge main
* fix: rust code warn
* fix: rust code error
* fix: rust code error
* fix: selection settings
* style: selection styles
* style: selection styles
---------
Co-authored-by: Steve Lau <stevelauc@outlook.com>
* chore: update outdated code comments
To initialize the app language stored in the backend, the frontend no
longer uses update_app_lang(). Instead, it now uses backend_setup().
* format code
This commit updates the panic hook implementation to log the panic
message to stdout as well, which would make debugging easier. It is
hightly possible that a panic may get ignored by us when we run Coco
app in the dev mode (since the hook only writes msg to the panic log file).
This commit fixes a bug that the search_extension() function panics
when the "GET /store/_search" interface returns a 404 response.
```
GET /store/_search?query=<query string>
{"_id":"_search","result":"not_found"}
```
It also improves the panic message by including varaible "response" in it,
so that we can inspect the actual response.
```
let hits_json = response.remove("hits").unwrap_or_else(|| {
panic!(
"the JSON response should contain field [hits], response [{:?}]",
response
)
});
```
Previously, View extensions loaded their HTML files directly from disk.
Now, Coco starts a lightweight local HTTP server to serve the static files,
and the extension loads them via HTTP instead.
This refactoring is needed because Tauri is not allowed to load local
files directly, we have to call convertFileSrc() to do the URL
conversion to make it work. In previous implementations, we did such
conversions to all the paths specified in the HTML file, but we realized
that there are paths in JS/CSS files as well, and it is impossible to
convert them all. So we have to change the way how view extensions load
their files.
This commit introduces a new field, `minimum_coco_version`, to the
`plugin.json` JSON. It specifies the lowest Coco version required
for an extension to run.
This ensures better compatibility by preventing new extensions from
being loaded on older Coco apps that may lack necessary APIs or features.
Co-authored-by: ayang <473033518@qq.com>
This commit removes the CI step that installs LLVM on Windows because:
1. It was constantly failing when I worked on [1]
```text
Failed in attempting to update the source: winget
The `msstore` source requires that you view the following agreements before using.
Terms of Transaction: https://aka.ms/microsoft-store-terms-of-transaction
The source requires the current machine's 2-letter geographic region to be sent to
the backend service to function properly (ex. "US").
Failed when searching source: winget
An unexpected error occurred while executing the command:
0x8a15000f : Data required by the source is missing
No packages were found among the working sources.
```
2. Actually, we don't need to install it since the Windows Github
action image already includes it. See [2]
[1]: https://github.com/infinilabs/coco-app/pull/946
[2]: https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md#language-and-runtime
This commit refactors the code that evenly collects documents from query
sources to let it collect at least 2 documents in every source, which
could correct the case when `max_hits_per_source` is 0. This was possible
with the previous impl, no longer allowed after this commit
* refactor: custom_version_comparator() now compares semantic versions
Previously, when comparing 2 versions, custom_version_comparator() only
compared their build numbers, which was incorrect. See this case:
```text
0.8.0-2500 -> 0.9.0-SNAPSHOT-2501 -> 0.8.1-2502
```
Coco adopts SemVer[1], and according to the specification, "0.8.1-2502"
is older than "0.9.0-SNAPSHOT-2501" even though it has a larger build
number.
This commit refactors it to compare the semantic versions.
[1]: Even though Coco uses SemVer, our version string does not follow the
spec. In this implementation, we use `to_semver()` to do the conversion, see
the code comments for more details.
* correct comments
Extract a procedure that calls convert_pages() to process HTML files
into a function. It is used in both install/store.rs and
install/local_extension.rs, doing this avoids code duplication.
This commit:
1. Bump dep tauri_nspenel to v2.1
2. On macOS, our main window is not a window but panel. Previously, we
were using window.show() and window.hide() in show_coco() and
hide_coco(). In this commit, we switch from window.show/hide to
panel.show/hide
Co-authored-by: ayang <473033518@qq.com>
* chore: use a custom log directory
This commit changes our log dirctory from the one set by Tauri to
a custom one. It is mostly the same as Tauri’s one, except that
the "{bundleIdentifier}" will be "Coco AI" rather than the real
identifier.
We are doing this because our bundle ID ("rs.coco.app") ends with ".app", log
directory "/Users/xxx/Library/Logs/rs.coco.app" is mistakenly thought as an
application by Finder on macOS, making it inconvenient to open. We do not want
to change the bundle identifier. The data directory, which stores all the data, still
references it. So doing that will be a breaking change. Using a custom log
directory make more sense.
* fmt
Take the 'Spotify Control' extension as an example:
- Spotify Control
- Toggle Play/Pause
- Next Track
- Previous Track
Previously, these sub-extensions were only returned when the query string
matched them, and thus counterintuitively, searching for 'Spotify Control' would
not hit them.
This commit changes that behavior: when a main extension (of type Extension)
matches the query, all of its sub-extensions are now included in the results.
When the expression to evaluate contains only a number, the result is
guaranteed to be this number. In this case, we no longer evaluate the
expression as telling users that "x = x" is meaningless.
Found another case where the `NextDisplay` command does not work (I said
another because the bug that commit ca71f07f3a3cc[1] fixed was also found
by playing with the `NextDisplay` command). After debugging, the root cause
of the issue is that the macOS API `AXUIElementSetAttributeValue()` does
not work in the expected way.
> When I execute the `NextDisplay` command to move the focused window from
> a big display (2560x1440) to a small display (1440*900), the window size
> could be set to 1460.
I don't know why it does not work so the only thing we can do is to retry.
Luckily, retrying works, at least in my tests.
[1]: ca71f07f3a
This commit fixes the issue that when the current desktop contains more
than 1 windows, moving the focused window via `NextDesktop` and
`PreviousDesktop` won't work.
How? By adding 2 missing `sleep()` functions:
1. b91a18dbb8/Silica/Sources/SIWindow.m (L242)
2. b91a18dbb8/Silica/Sources/SIWindow.m (L249)
Also, this commit improves the implementation by resetting the mouse position.
`NextDesktop` and `PreviousDesktop` are implemented by emulating mouse and
keyboard events, draging the focused window and switching to the corresponding
desktop. To make a window draggable, we have to move the mouse to the window's
traffic light area. It is disturbing to not move the mouse back so this commit
implements it.
This commit fixes a bug that most Window Management extension commands
won't work if you:
1. operate the focused window from another display
2. and they are adjacent
To reproduce this:
say you have 2 displays
1. Put the focused window on a non-main display, maximize the window
2. Move the mourse to the main display, making it the active display
3. Launch Coco, then execute the `TopHalf` command
The focused window will be moved to the main display, while it should
stay in the non-main display.
The root cause of the issue is that the previous implementation of
`intersects()` didn't handle an edge case correctly, adjavent rectangles
should not be considered overlapping. This commit replaces the buggy
implementation with the `CGRectIntersectsRect()` function from macOS
core graphics library.
This commit introduces a new extension type View, which enables developers
to implement extensions with GUI. It is implemented using iframe, developers
can specify the path to the HTML file in the `Extension.page` field, then
Coco will load and render that page when the extension gets opened.
coco-api
We provide a TypeScript library [1] that will contain the APIs developers
need to make the experience better.
We start from file system APIs. Since the embedded HTML page will be loaded
by WebView, which has no access to the local file system, we provide APIs
to bridge that gap. Currently, `fs:read_dir()` is the only API we implemented, more
will come soon.
Permission
As View extensions run user-provided code, we introduce a permision
mechanism to sandbox the code. Developers must manually specify the
permission their extension needs in the "plugin.json" file, e,g.:
"permissions": {
"fs": [
{ "path": "/Users/foo/Downloads", "access": ["read", "write"] },
{ "path": "/Users/foo/Documents", "access": ["read"] }
],
"http": [
{ "host": "api.github.com" }
],
"api": ["fs:read_dir"]
}
Currently, both fs and api permissions are implemented. Permission checks
apply only to View extensions for now; Command extensions will support
them in the future.
[1]: https://github.com/infinilabs/coco-api
The file search extension relies on the OS's desktop search to work, and it
is possible that the desktop search indexer may not index the search paths
we specify.
This commit adds a hook that signals to the indexer and lets it index
the paths we need. This hook will be invoked when:
* initialing the extension
* enabling the extension
* upon every configuration change
to make our best effort to fix the issue.
* feat: extension Window Management for macOS
* release note
* revert frontend code changes
* new line char
* remove todo
* it is macos-only
* format code
* macos-only
* more conditional compilation
* correct field Document.icon
This commit fixes(I guess?) the issue that the Settings window may not be
rendered or loaded, you will see that the whole window is gray in that case.
Background, aka, why this issue exists
=============================================================
In commit [1], we wrapped all the backend setup routines in a tauri command, so
that frontend code can call it before invoking any other backend interfaces to
guarantee that these interfaces won't be called until the data/state they rely
on is ready.
The implementation in [1] had an issue that it didn't work with window reloading.
To fix this issue, we made another commit [2]. Commit [2] fixed the refresh
issue, but it also caused the settings window issue that this commit tries to fix.
The backend setup tauri command needs a state to track whether the setup has
completed. In the previous implementation, this was done in the frontend. In
this commit, it is moved to the backend.
Why didn't you guys move that state to backend in previous commits, e.g., commit [2]?
=============================================================
We tried, but failed. In the previous tries, the backend would send an event
to the frontend, but the frontend couldn't receive it, for reasons we still
don’t understand. And this weird issue still exists, we just happen to find
a way to work around it.
[1]: f93c527561
[2]: 993da9a8ad
Co-authored-by: ayang <473033518@qq.com>
In the previous macOS file search implementation, we spawned an mdfind child
process and killed it when we got the results we needed to avoid zombie
processes. However, this kill step would be skipped if an error happened
during query results processing as we propagate errors.
This commit replaces the manual kill operation with the `ChildProcHandle.kill_on_drop()`
API to let RAII do the job to fix the issue.
This commit implements the file search extension for Linux with the
GNOME desktop environment by employing the engine that powers GNOME's
desktop search - Tracker.
It also fixes an edge case bug that the search and exclude path
configuration entries will not work. For example, say I set the search path
to ["~/Dcouments"], and I have a file named "Documents_foobarbuzz" under
my home directory, this file is not in the specified search path but
Coco would return it because we verified this by checking string prefix.
Claude Code found this when I asked it to write unit tests. Thank both
tests and Claude Code.
* refactor: relax the file search conditions on macOS
This commit makes the file search conditions more permissive on macOS:
* Searching by filename
Now this is case-insensitive
* Searching by filename and content
We previously only searched for 2 attributes:
1. kMDItemFSName
2. kMDItemTextContent
as the semantics should be exactly right (Search fileanme and content). But
kMDItemTextContent does not work as expected. For example, if a PDF document
contains both "Waterloo" and "waterloo", it is only matched by "Waterloo".
To workaround this (I consider this a bug of Spotlight), now we search all
the attributes.
* format code
* document
Coco panicked on Windows when I was testing the applications-rs crate on
Windows, the error message seemingly indicates that we should run hotkey setup
on the main thread, and doing that indeed fixes the issue, so let's do
it.
I wasn't aware that both '-' (specified by the standard) and '_' (not in the
standard, but is commonly used) can be used as the tag delimiter in locale
strings[1] when I originally wrote this commit[2].
Both "zh-CN" and "zh_CN" are valid locale strings!
Since '_' is more commonly used, I thought it was the only correct form and
thus our code only accepts it.
This commit refactors the implementation to accept both.
[1]: https://stackoverflow.com/a/36752015/14092446
[2]: f5b33af7f1
After this commit, we index both English and Chinese application names
so that searches in either language will work. And the names of the
applications in search results and application list will be in the app language.
Pizza index structure has been updated, but backward compatibility is preserved
by keeping the support code for the old index field.
The changes in this commit are not macOS-specific, it applies to all supported
platforms. Though this feature won't work on Linux and Windows until we implement
the localized app name support in the underlying applications-rs crate.
Bumps the 'applications' crate to include this commit[1]. With this,
Coco now indexes iOS apps and macOS apps that store icon in Assets.car.
[1]: 814b16ea84
refactor: coordinate third-party extension operations using lock
During debugging 783cb73b29,
I realized that some extension operations were not synchronized and thus would
behave incorrectly under concurrency. Though GUI apps like Coco typically
won't have concurrency. This commit synchronizes them by putting them behind
the lock.
This commit implementes a new extension setting entry
"hide_before_open":
> Extension plugin.json
```json
{
"name": "Screenshot",
"settings": {
"hide_before_open": true
}
}
```
that, if set to true, Coco will hide the main window before opening the
extension.
Only entensions that can be opened can set their "settings" field, a
check rule is added to guarantee this.
Deep linking is handled on the frontend, so this commit removes the related and
unused backend code.
"src-tauri/tauri.conf.json" is also modified, field "plugins.deep-link.schema"
does not exist so I removed it as well.
This commit reverts the logic introduced in
e7dd27c744:
> Pinning the main window would bring "NSWindowCollectionBehaviorCanJoinAllSpaces"
> back to make it really stay pinned across all the spaces.
Commit 6bc78b41ef (diff-b55e9c1de63ea370ce736826e4dea5685bfa3992d8dee58427337e68b71a1fc1)
did a tiny refactor to the frontend code merged in the above commit,
these changes are reverted as well.
We revert these changes because we observed an issue with window
focus, and we don't know the root cause and how to fix the issue either.
The following change is kept because we don't want to hit this NS panel
bug[1]. But if the issue still exists after this commit, it will
be removed as well.
In "src-tauri/src/setup/mac.rs":
```diff
panel.set_collection_behaviour(
- NSWindowCollectionBehavior::NSWindowCollectionBehaviorCanJoinAllSpaces
+ NSWindowCollectionBehavior::NSWindowCollectionBehaviorMoveToActiveSpace
```
[1]: https://github.com/ahkohd/tauri-nspanel/issues/76
Before this commit, sub extensions were not allowed to set their
"platforms" field, this restriction is lifted in this commit.
By allowing this, a group extension can have sub extensions for
different platforms, here is an example (irrelavent fields are omitted
for the sake of simplicity):
```json
{
"name": "Suspend my machine",
"type": "Group",
"platforms": ["macos", "windows"],
"commands": [
{
"name": "Suspend macOS":
"platforms": ["macos"],
"action": {...}
},
{
"name": "Suspend Windows":
"platforms": ["windows"],
"action": {...}
}
]
}
```
While loading or installing extensions, incompatible sub extensions will
be filtered out by Coco, e.g., you won't see that "Suspend Windows"
command if you are on macOS.
An extra check is added in this commit to ensure a sub extensions won't
support the platforms that are incompatible with its main extension.
Even though main extensions and sub extensions can both have "platforms"
specified, the semantics of this field, when not set, differs between them.
For main extensions, it means this extension is compatible with all the
platforms supported by Coco (null == all). For sub extensions, having it
not set implicitly says that this field has the same value as the main
extension's "platforms" field.
The primary reason behind this design is that if we choose the semantics used
by the main extension, treating null as all, all the extensions we currently
have will become invalid, because they are all macOS-only, the main extensions's
"platforms" field is "macos" and sub extensions' "platforms" is not set (null),
they will be equivalent to:
```json
{
"name": "this is macOS-only",
"type": "Group",
"platforms": ["macos"],
"commands": [
{
"name": "How the fxxk can this support all the platforms!"
"platforms": ["macos", "windows", "linux"],
"type": "Command",
"action": {...}
}
]
}
```
This hits exactly the check we mentioned earlier and will be rejected by
Coco. If we have users installed them, the installed extensions will be
treated invalid and rejected by future Coco release, boom, we break backward
compatibility.
Also, the current design actually makes sense. Nobody wants to repeatedly
tell Coco that all the sub extensions support macOS if this can be said only
once:
```json
{
"name": "this is macOS-only",
"platforms": ["macos"],
"commands": [
{
"name": "This supports macOS"
"platforms": ["macos"],
},
{
"name": "This supports macOS too"
"platforms": ["macos"],
},
{
"name": "Guess what! this also supports macOS"
"platforms": ["macos"],
},
{
"name": "Come on dude, do I really to say this platform=macos so many times"
"platforms": ["macos"],
}
]
}
```
Coco App has 4 sources of Extension/plugin.json that should be checked:
1. From the "<data directory>/third_party_extensions" directory
2. Imported via "Import Local Extension"
3. Downloaded from the "store/extension/<extension ID>/_download" API
4. From coco-extensions repository
Granted, Coco APP won't check these files directly, but we will
re-use the code and run them in that repository's CI.
Previously, only the Extensions from the first source were checked/validated.
This commit extracts the validation logic to a function and applies it to all
4 sources.
Also, the return value of the Tauri command "list_extensions()" has changed.
We no longer return a boolean indicating if any invalid extensions
are found during loading, which only makes sense when installing
extensions requires users to manually edit data files. Since we now
support extension store and local extension imports, it could be omitted.
This commit removes the generic argument R from all the AppHandle imports, which
is feasible as it has a default type. This change is made not only for simplicity,
but also **consistency**. Trait SearchSource uses this type:
```rust
pub trait SearchSource {
async fn search(
&self,
tauri_app_handle: AppHandle,
query: SearchQuery,
) -> Result<QueryResponse, SearchError>;
}
```
In order to make trait SearchSource object-safe, the AppHandle used in it cannot
contain generic arguments. So some parts of Coco already omit this generic
argument. This commit cleans up the remaining instances and unifies the usage
project-wide.
This commit adds support for installing extensions from a local folder path:
```text
extension-directory/
├── assets/
│ ├── icon.png
│ └── other-assets...
└── plugin.json
```
Useful for testing and development of extensions before publishing.
Co-authored-by: ayang <473033518@qq.com>
This commit splits query_coco_fusion() into 2 functions:
1. query_coco_fusion_single_query_source()
2. query_coco_fusion_multi_query_sources()
query_coco_fusion_single_query_source(), as the name suggests, will only search
1 query source. Due to this simplicity, it does not need the complex re-ranking
procedure used by query_coco_fusion_multi_query_sources(), which is the primary
reason why this commit was made.
Another reason behind the change is that the re-ranking logic makes the
search results of querying single query source incorrect, it removes documents
from the results. I didn't investigate the issue because dropping the complex
logic in single query source search would be the best solution here.
On Ubuntu (the GNOME version), Coco would panic when users open an app due
to the reason that Coco thinks it is running in an unsupported desktop
environment (DE).
We rely on the environment variable XDG_CURRENT_DESKTOP to detect the DE,
Ubuntu sets this variable to "ubuntu:GNOME" instead of just "GNOME",
which was not handled by the previous implementation.
This commit supports this case. Also, when Coco runs in an unsupported DE,
opening apps should not panic the app. After this commit, we would return
an error.
This commit fixes the following panic:
```
Time: [2025-07-23-17-03-23]
Location: [/Users/steve/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tauri-2.5.1/src/lib.rs:742:7]
Message: [state() called before manage() for tauri_plugin_global_shortcut::GlobalShortcut<tauri_runtime_wry::Wry<tauri::EventLoopMessage>>]
```
The root cause is that, in a Tauri application, before you can access a piece of
managed state with the .state() method, you must first register it with Tauri
using .manage(). When a user reigsters hotkey for an extension,
initializing extensions will invoke the .state() method, at that point,
.manage() hasn't been called.
The fix is simple, we simply call .manage() earlies (invoked by our
`shortcut::enable_shortcut(app)` function).
Having backtrace in the panic log will help debugging a lot. Under
release builds, we strip our binary so the symbols information is
unavailable, but this information is still useful in debug builds.
Panic log in release builds:
```
Time: [YYYY-MM-DD-HH-MM-SS]
Location: [/Users/foo/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tauri-2.5.1/src/lib.rs:742:7]
Message: [state() called before manage() for tauri_plugin_global_shortcut::GlobalShortcut<tauri_runtime_wry::Wry<tauri::EventLoopMessage>>]
Backtrace:
0: __mh_execute_header
1: __mh_execute_header
2: __mh_execute_header
3: __mh_execute_header
4: __mh_execute_header
5: __mh_execute_header
6: __mh_execute_header
7: __mh_execute_header
8: __mh_execute_header
9: __mh_execute_header
10: __mh_execute_header
11: __mh_execute_header
12: __mh_execute_header
13: __mh_execute_header
14: __mh_execute_header
15: __mh_execute_header
16: __mh_execute_header
17: <unknown>
18: <unknown>
```
We found that Windows Search would error out if it encounters a single
quote character, the natural solution would be to escape it. But I couldn't
find out how. The approach mentioned by most posts:
```
~="<Unsupported Char>"
```
won't work in my test. So I decided to replace it with a whitespace.
Single quote is not the first unsupported character I know, the newline
character is not supported as well, so it will be handled in the same
way.
This commit fixes the search issue introduced by [commit](5c0a865822). We have no idea why the tauri command `get_app_search_source` won't be invoked after that commit on Windows.
This commit resolves the issue by moving the extension init logic to the Rust side.
Also, update the querysource logs in `quey_coco_fusion()`, the old one won't say anything if the querysource list is empty, the new one will tell us that.
* chore: not request the interface if not logged in
* chore: res
* chore: res
* chore: common interface
* chore: no login
* chore: login
* chore: login
* chore: add
* dbg print servers
* chore: id
* docs: update notes
---------
Co-authored-by: Steve Lau <stevelauc@outlook.com>
This commit fixes the Windows panic issue.
Coco panicked because it accessed `GLOBAL_TAURI_APP_HANDLE` when this global variable wasn't initialized. I removed all the uses of this variable except for the one use in `src-tauri/src/server/http_client.rs`, which I don't have a good way to refactor.
If you are wondering why this didn't happen in the past, the access was triggered by the frontend code, something there likely changed. Regardless, this global variable is still dangerous and error-prone, so we should avoid it.
Also, this commit fixes the issue that the panic hook does not work on Windows because the log filename contains ":", which is not allowed by the Windows file system.
Found this tauri command while reading the code, then I realized that
token management logic should all be kept in the backend, there is no
need to expose it to the frontend. And indeed, searching for it in the
frontend code showed that it is not used at all.
```sh
$ cd src
$ rg get_server_token
commands/servers.ts
75:export function get_server_token(id: string): Promise<ServerTokenResponse> {
76: return invokeWithErrorHandler(`get_server_token`, { id });
```
So remove it.
* refactor: do status code check before deserializing response
This commit adds a status code check to the following requests, only when
this check passes, we deserialize the response JSON body:
- get_connectors_by_server
- mcp_server_search
- datasource_search
A helper function `status_code_check(response, allowed_status_codes)`
is added to make refactoring easier.
* chore: release notes
This commit bumps the windows crate from "0.60.0" to "0.61.3", it should
solve the CI issue happened here[1]:
```text
error[E0277]: `DBOBJECT` doesn't implement `Debug`
--> C:\Users\runneradmin\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\windows-0.60.0\src\Windows\Win32\System\Search\mod.rs:21828:5
|
21826 | #[derive(Clone, Debug, PartialEq)]
| ----- in this derive macro expansion
21827 | pub struct SSVARIANT_0_4 {
21828 | pub dbobj: DBOBJECT,
| ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `DBOBJECT`
|
= note: add `#[derive(Debug)]` to `DBOBJECT` or manually `impl Debug for DBOBJECT`
```
[1]: https://github.com/infinilabs/ci/actions/runs/16314479643/job/46076989290
This commit implements the file search extension for Windows platforms using the [Windows Search](https://learn.microsoft.com/en-us/windows/win32/search/-search-3x-wds-qryidx-overview) functionality.
Something to note:
1. Searching by file content is not natively supported. Coco would search for all the columns (attributes/fields within the index) with this option:
```rust
SearchBy::NameAndContents => {
// Windows File Search does not support searching by file content.
//
// `CONTAINS('query_string')` would search all columns for `query_string`,
// this is the closest solution we have.
format!("((System.FileName LIKE '%{query_string}%') OR CONTAINS('{query_string}'))")
}
```
2. Tests have been added, but they failed in our CI for unknown reasons so I disabled them:
```rust
// Skip these tests in our CI, they fail with the following error
// "SQL is invalid: "0x80041820""
//
// I have no idea about the underlying root cause
#[cfg(all(test, not(ci)))]
mod test {
```
3. The Windows Search index is not real-time and can return obsolete results. Opening the returned documents could fail if the chosen file has been deleted or moved.
* chore: rename QuickLink/quick_link to Quicklink/quicklink
Standardize varaible naming to match the correct term: "Quicklink" and "quicklink".
This updates all incorrect variants such as "QuickLink" and "quick_link".
* chore: release notes
* chore: bump dep applications-rs
Currently Coco depends on atty v0.2.14, a crate that has
[vulnerability](https://github.com/infinilabs/coco-app/security/dependabot/25),
here is the dependency chain:
```
coco -> applications-rs -> freedesktop-file-parser 0.1.0 -> atty 0.2.14
```
I bumped the [`freedesktop-file-parser`](7bdb070e45)
crate in our applications-rs crate, which would eliminate the `atty` crate
from the chain to fix the vulnerability.
This commit bumps the applications-rs crate to include the above change.
* chore: release notes
* refactor: adjust extension code hierarchy
In this commit, I refactored the extension code structure.
* We can only install third-party extensions so the `store.rs` file should
belong to the `third_party` directory.
* Move tauri command `uninstall_extension()` to `extension/mod.rs` from
`third_party.rs` since one can uninstall an extension regardless of
how you installed it.
* Refactor the `install_extension_from_store()` function, add more
descriptive code comments.
Also, a trivial change, bump Rust toolchain and edition to use the
[let-chains](https://blog.rust-lang.org/2025/06/26/Rust-1.88.0/#let-chains) syntax.
* chore: release notes
* chore: replace meval-rs with our fork to clear dep warning
This commit replaces the meval-rs dependency with our
[fork](https://github.com/infinilabs/meval-rs). The original meval-rs
crate has not been maintained for a long time and uses nom 1.0, a crate
that was released 9 years ago, which would be rejected by future Rust
compiler because it contains outdated Rust syntaxes. This is the reason
why we are seeing the following warning:
```
warning: the following packages contain code that will be rejected by a future version of Rust: nom v1.2.4
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1
```
Switching to our fork would solve this warning.
* chore: release notes
* fix: windows platform run with shell
* chore: add rust target
* fix: fix app version and release body
* chore: update step id
---------
Co-authored-by: hardy <luohf@infinilabs.com>
* refactor: use author/ext_id as extension unique identifier
* refactor: refactoring extended component interfaces and logic
* refactor: update
* style: remove console
* refactor: update
* drop pizza engine
* refactor: restore hotkey upon start no matter if the ext is enabled or not
* chore: release note
---------
Co-authored-by: ayang <473033518@qq.com>
* refactor: optimize global state synchronization
* refactor: reconstruct the language change processing logic
---------
Co-authored-by: ayang <473033518@qq.com>
* refactor: search result related components
* refactor: search result related components
* docs: update notes
* refactor: search result related components
* fix: ArrowLeft error
* chore: remove log
* fix: ask ai
The **AI Overview** feature can automatically refine and summarize current search results in search mode, helping users quickly grasp the key points of the search results without having to browse each individual result. This feature is particularly useful in scenarios where information needs to be extracted quickly.
- **Automatic Refinement and Summary**: When a user performs a search, AI Overview automatically generates a concise summary based on the current search results, providing key information from the results.
- **Improve Work Efficiency**: By avoiding the need to manually browse through numerous results, AI Overview helps users quickly focus on the most relevant information, saving time.
To use the **AI Overview** feature, you need to configure it in the settings:
1. Open the **Settings** page and select the **Extensions** option.
2. In the **AI Overview Extension** configuration, choose an **AI assistant** that you want to use for summarization.
3. Configure the **trigger strategy**:
- **Minimum number of search results**: Set the minimum number of search results required to trigger AI Overview.
- **Minimum input length**: Set the minimum length of the input query; the summary function will only start when the input content is long enough.
- **Delay after typing stops**: Set the time delay after input stops to start the summary function, avoiding unnecessary summaries triggered by frequent input.
4. After saving the settings, in search mode, press `Meta + O` to enable the AI Overview feature, and AI Overview will automatically generate summaries for the search results according to your configuration.
> 💡 **Tip**: **The style and depth of the summary depend on the AI assistant you choose.**
>
> Think of it as an "information assistant"; the role you assign to it determines its reporting style:
>
> - **"Summary Abstract" assistant**: Provides quick, general summaries.
>
> - **"Technical Expert" assistant**: May generate summaries that focus more on technical specifications and code snippets.
>
> - **"Market Analyst" assistant**: Will pay more attention to market data, competitive dynamics, etc.
>
>
> 💡 **Tip**: **For faster response speed**
>
> If you pursue **ultimate response speed**, it is recommended to configure an assistant using a **fast token-generation, non-inference type model** for the AI Overview feature. Such models can quickly generate summaries for you, making information acquisition smooth.
The **Applications** feature allows you to directly search for and launch locally installed applications in Coco AI. You can quickly find and open any application through the unified search entry without switching windows or manually searching.
- You can add or remove paths according to actual needs to avoid displaying irrelevant programs.
2.**Rebuild Index**
Rescan and update the local application index.
- Usually, there is no need to perform this manually.
- If you find that an installed application does not appear in the search results, you can click **Rebuild Index** to manually retry and update the results.
Coco AI provides a concise calculator function that allows users to perform quickquick basic mathematical calculations directly in the input box without opening a separate calculator application. Simply enter an arithmetic expression, and the system will instantly provide the result. It also supports copying the arithmetic expression and the calculation result for easy use at any time.
- **Quick Calculation**: Enter basic mathematical expressions in Coco AI's input box, and the system will automatically calculate and display the result.
- **Support for Basic Mathematical Operations**: Currently supports basic arithmetic operations such as addition, subtraction, multiplication, and division.
- **Copy Expression and Result**: Supports copying the complete arithmetic expression and calculation result for easy pasting into other applications.
## Usage Method
1.**Enter an Expression**:
- Directly input a basic mathematical expression in Coco AI's input box, for example: `256 * 42`
- The system will automatically calculate and display the result.
2.**Copy Expression and Result**:
- When the result is displayed, press `Enter` to copy the calculation result.
- Use the shortcut key `Meta + K` to open more operations, and select **Copy Answer**, **Copy Question and Answer**, or **Copy Answer (in Word)**
The File Search feature allows you to directly use the system's local search capability in Coco AI to quickly find files on your computer. You can flexibly set the search scope, excluded directories, file types, and search methods to get more accurate results.
- **System-level search integration**: Coco AI leverages the file indexing capabilities provided by the operating system (such as macOS Spotlight, Windows Search, etc.) to achieve efficient local file search.
- **Flexible search control**: Supports custom search scopes and excluded paths, and can filter file types according to needs.
- **Content-level search**: On supported systems, you can choose to search file contents at the same time, not just file names.
Coco AI is already equipped with local file search capabilities. You don't need any additional operations; you can start typing keywords in the search box to experience it immediately. If you want to exclude certain folders or add new search locations, you can manage your preferences at any time through **"Settings → Extensions → File Search"**.
1.**Search By**
Select the matching method for the search:
- **Name**: Only match file names (faster).
- **Name + Contents**: Match both file names and file contents (depending on operating system support).
2.**Search Scope**
Select the folders or disk locations to be included in the search.
- For example: `/Users/username/Documents` or `D:\Projects`
3.**Exclude Scope**
Specify paths that are not included in the search, used to reduce irrelevant results or improve search speed.
- For example: `node_modules`, `tmp`, `Library` and other system cache directories.
4.**Search File Types**
Limit the file extensions or types to be searched.
- For example: `.pdf`, `.docx`, `.md`, `.txt`
> 💡 **Tips**: **System Support Differences**
>
> - **macOS**: Implements mixed search of file names and contents through **Spotlight**, supporting fast response and fuzzy matching.
> - **Windows**: Relies on the system's **Windows Search Indexer**, supporting file name search; content search requires enabling content indexing for corresponding file types in system index settings.
> - **Linux**: Generally only supports file name search, depending on the distribution and configuration.
The **Quick AI Access** feature allows you to directly start a conversation with AI through the search box without switching to chat mode. This feature provides users with a smoother and more efficient interaction experience, especially suitable for scenarios where quick feedback or handling simple questions is needed.
- **Quickly Start a Conversation**: After entering content in the search box, press `Meta + Enter` to directly start a conversation with the AI assistant without switching to chat mode.
- **Instant Response**: Coco AI will display the conversation reply in the same window, providing answers or suggestions quickly.
- **Switch from Conversation Mode**: After completing a quick conversation, press `Meta + Enter` to switch to the full chat mode and continue multi-turn conversations.
Enter commands included in Window Management in the **Coco AI search box** to browse and execute window management commands, such as:
- **Almost Maximize Bottom** — Maximize the window to the lower area of the screen
- **Bottom Half** — Move the current window to the lower half of the screen
- **Bottom Left Quarter** — Position the window to the bottom-left quarter
- **Bottom Right Sixth** — Place the window in the bottom-right sixth area
The window's position and size will be adjusted immediately after selecting a command.
> 💡 **Tips**
>
> - System-level window operations are supported; some special types of windows (such as full-screen or independent floating windows) may not be controllable.
> - It is recommended to combine custom shortcuts for commands to quickly achieve common window layouts.
- Use the global shortcut (default: `Shift + Meta + Space`) to open the Coco AI interface.
- The interface is in chat mode (use the switch button or the shortcut `Meta + T` to switch modes).
- Enter natural language questions in the input box. Press `Enter` to start the conversation.
## Chat Interface and Functions
Coco AI's chat interface is designed to be concise and intuitive, allowing you to quickly switch AI assistants, access different Coco Servers, browse historical conversations, or use advanced capabilities such as deep thinking, web search, and tool calls.
In chat mode, the Coco AI interface mainly consists of the following areas:
- **Top Bar**
- **Assistant Selection**: The drop-down menu in the upper left corner allows you to quickly switch between different AI assistants.
- **Historical Conversations**: Click the icon in the upper left corner to view recent conversations, and click any one to restore the conversation context.
- **Server Switching**: The cloud icon in the upper right corner shows the currently connected Coco Server, and you can switch or refresh the server with one click.
- **Independent Window Mode**: The icon in the upper right corner can pop up the current conversation into an independent window, facilitating multi-task collaboration or comparison viewing.
- **Middle Area**
- Displays conversation content and AI responses.
- **Bottom Input Area**
- Enter messages and press `Enter` to send, supporting voice input.
- The left function bar includes controls such as web search, tool call (MCP), and deep thinking switch.
#### Multiple Servers and Assistants
##### Switching Coco Server
Coco AI supports connecting to multiple Coco Servers, and each server can contain a different number of AI assistants.
Click the **server icon** in the upper right corner to view the current connection status:
- Displays the server name and online status.
- Lists the number of available AI assistants on the server.
- Supports one-click switching, refreshing, or entering the settings page.
> 💡 **Tip**: When switching assistants in the same conversation, Coco AI will automatically retain the context of the current conversation. This means you can let different assistants take turns answering or supplementing analysis in the same round of conversation without re-entering background content.
#### Bottom Function Bar
The function buttons at the bottom left of the input box can quickly call the following capabilities:
Extensions of Coco AI are plug-in modules that add specific functions to the core system. By installing extensions, you can greatly enhance the capabilities of Coco AI and create a personalized intelligent working environment.
In the Extension Store, you can browse or search for the required extensions. After finding the desired extension, press `↵` to view details, and click the install button on the details page. Coco AI will automatically complete the download and installation process.
After installing an extension, you can call it through the unified search box.
#### Command-type Extensions (Commands)
In search mode, enter the command name or keywords, select the corresponding command from the search results, and press Enter to execute it.
#### View-type Extensions (Views)
View-type extensions provide a complete user interface, embedding visual applications in Coco AI, which can display complex information and offer rich interactive experiences.
In search mode, enter the extension name or keywords, select the corresponding extension from the search results, and press `↵` to enter the corresponding extension's interaction interface.
On the Extensions page in Settings, select the extension you want to uninstall. On the right side of the extension title in the details section, click the `…` button and select Uninstall.
Coco AI provides an intuitive set of keyboard shortcuts to help you navigate efficiently, execute commands, switch modes, and manage conversations. Mastering these shortcuts can greatly enhance your user experience.
## You don't need to memorize the shortcuts
Simply go to **Settings** (shortcut: `Meta + ,`) → **General → Tooltip**, and turn on the shortcut hint switch. After enabling, when you hold down the modifier key, the corresponding shortcut hints will be displayed in real-time in each functional area of the interface.
Coco AI's search function is designed to provide a unified, intelligent, and efficient cross-platform information retrieval experience. In search mode, you can quickly find local files, applications, commands, extensions, data sources in Coco Server (including Google Drive, Notion, Yuque, Hugo sites, RSS, Github, Postgres, etc.), and AI assistants through the search box.
Coco AI will automatically return a set of concise, structured search results after you enter keywords.
#### Default Display Rules
- By default, the **first 10 results** are displayed.
- When results come from multiple data sources (such as Hugo sites, Google Drive, local files, etc.), they will be displayed **grouped by data source**.
- If there are fewer than 10 results, they will be displayed **without grouping** in a single list.
- Each result shows:
- **Title** (file name, note name, or conversation title)
- **Directory information** (belonging path or location)
- Key matching fragments or summaries
> 💡 **Tip**: Grouping allows you to quickly understand the range of matching content in different data sources, saving time in filtering.
In Coco AI, you can adjust various settings of the application according to your personal needs (shortcut: `Meta + ,`) . The settings page is divided into several main sections, allowing you to easily manage startup items, shortcuts, extensions, connections, and advanced features.
## General
In the General Settings section, you can adjust Coco AI's startup items, startup shortcuts, interface appearance, and language.
In the Connect Settings, you can view and manage connections to Coco Server. This section involves logging in, enabling/disabling, and deleting connected servers.
Coco AI is always ready to help you quickly go from "wanting to ask" to "finding answers". This page will briefly introduce the core concepts and quick start process of Coco AI.
## Core Operations
- Use the global shortcut (default: `Shift + Meta + Space`) to open the Coco AI interface.
- In the interface, use the toggle button or shortcut key (default: `Meta + T`) to switch between search and AI chat modes.
- In search mode, enter keywords in the input box to search for local files, cloud data sources, applications, commands, etc., then press `Enter` to open them.
- In chat mode, select different AI assistants and talk directly to them.
- Enhance functions with extensions: such as multimedia control, screenshot, window management, etc.
## Quick Start
The following operations can help you quickly get familiar with Coco AI:
1. Press the shortcut key `Shift + Meta + Space` to open Coco AI.
2. In search mode, enter a keyword (e.g., "project report") in the input box to see Coco AI search for related files.
3. In search mode, enter a mathematical operation (e.g., `256*42`) in the input box to view the quick calculation result.
4. In search mode, select a search result and press the hotkey `tab` to activate the data source or category filter.
5. In search mode, search for and open the Extensions Store, then install an extension.
6. In chat mode, enter a question (e.g., "What is Coco AI") in the input box to see the answer from the AI assistant.
7. In chat mode, click the icon in the upper right corner of the window (shortcut key: `Meta + E`) to activate the independent window chat.
8. In the settings (shortcut key: `Meta + ,`), go to the connection settings to connect to Coco Cloud or your self-deployed Coco Server, so as to access cloud data sources and AI assistants, allowing Coco AI to achieve one-stop search.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.