* feat: add deep research report workflow and viewer
* docs: update changelog
* ci: update pizza repository reference from infinilabs to pizza-rs org
* fix deep research completion state
* fix: prevent deep research stream timeout
* fix: update deep research cancel copy
* fix: apply rustfmt formatting to attachment.rs
* fix: resolve fst-no-std version conflict in pizza-engine CI check
The 'check (macos-latest)' CI job fails because pizza-engine (added as a
CI dependency) uses infinilabs/fst-no-std while its transitive dependency
fst-regex uses pizza-rs/fst-no-std. Cargo treats these as two separate
crates, causing:
1. Automaton trait incompatibility between the two fst_no_std instances
2. MapBuilder, Error::Io, and Set::from_iter not found because the
infinilabs fork gates them behind 'std' feature while pizza-engine
only enabled 'alloc'
Fix:
- Add [patch."https://github.com/infinilabs/fst-no-std"] to
src-tauri/Cargo.toml to redirect the infinilabs fork to
pizza-rs/fst-no-std, unifying both into a single crate instance.
This patch is a no-op for normal builds without pizza-engine.
- Update the CI workflow to also add fst-no-std with std feature so that
Error::Io (gated by std) and MapBuilder are available after the redirect.
* Update Cargo.toml
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Medcl <m@medcl.net>
* feat: add Open Camera feature with live preview, photo capture, mirror toggle, and camera switching
Agent-Logs-Url: https://github.com/infinilabs/coco-app/sessions/e874b626-f179-4d54-bc6c-c239394459e3
Co-authored-by: medcl <64487+medcl@users.noreply.github.com>
* fix: address code review feedback - add error logging, remove invisible button, document eslint-disable
Agent-Logs-Url: https://github.com/infinilabs/coco-app/sessions/e874b626-f179-4d54-bc6c-c239394459e3
Co-authored-by: medcl <64487+medcl@users.noreply.github.com>
* refactor: convert camera from dedicated window to built-in extension with permission handling
- Create Open Camera built-in extension (search source in Rust)
- Add camera permission check/request via macOS permissions plugin
- Render camera inline in main Coco window (not a separate window)
- Add com.apple.security.device.camera entitlement
- Remove dedicated camera window, tray menu entry, and window commands
- Add cameraOpened state to search store for navigation support
- Handle Escape/Back navigation for camera view
Agent-Logs-Url: https://github.com/infinilabs/coco-app/sessions/bb996add-d287-464c-bc53-c69167630351
Co-authored-by: medcl <64487+medcl@users.noreply.github.com>
* fix: address code review feedback - fix permission check flow, remove duplicate cleanup, fix type
Agent-Logs-Url: https://github.com/infinilabs/coco-app/sessions/bb996add-d287-464c-bc53-c69167630351
Co-authored-by: medcl <64487+medcl@users.noreply.github.com>
* fix: camera not displaying video due to missing CSP media-src, secure context, and stream lifecycle issues
Three root causes fixed:
1. CSP missing media-src directive - Added media-src with blob: and mediastream:
schemes to allow camera streams in the webview
2. Missing useHttpsScheme - Added to main window config to ensure secure context
required by getUserMedia API on macOS WKWebView
3. Camera.tsx stream lifecycle - Rewrote initialization to use a single sequential
flow (permission → getUserMedia → enumerate → assign) instead of three
separate useEffects with circular dependency issues. Uses refs for stream
tracking to prevent stale closure bugs in cleanup.
Agent-Logs-Url: https://github.com/infinilabs/coco-app/sessions/f3b86e6b-3ce2-423d-a5a1-c3a5f4e115f2
Co-authored-by: medcl <64487+medcl@users.noreply.github.com>
* fix: tighten CSP media-src directive and add permission polling timeout
- Remove overly permissive https:/http: from media-src (only need self/blob/mediastream)
- Remove unnecessary img-src override (falls back to default-src)
- Add 60-second timeout to camera permission polling to prevent infinite loops
- Check cancelled flag during polling to support component unmount
Agent-Logs-Url: https://github.com/infinilabs/coco-app/sessions/f3b86e6b-3ce2-423d-a5a1-c3a5f4e115f2
Co-authored-by: medcl <64487+medcl@users.noreply.github.com>
* feat: add Open Camera functionality with icon and translations
* fix: remove unused setCameraOpened from SearchResultsPanel
* feat: update platform adapters to include saveFileDialog method for Tauri and Web
* fix: streamline camera search source registration in built-in extension
* refactor: update extension icon
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: medcl <64487+medcl@users.noreply.github.com>
Co-authored-by: ayangweb <473033518@qq.com>
* fix(logging): include webview target in production log level config
In production mode, COCO_LOG was set to 'coco_lib=trace' which caused
the global log level to be set to Off first, then only coco_lib module
was enabled. This silently dropped all frontend logs whose target is
'webview', making them disappear in packaged builds while working fine
in dev mode (which uses the default Info level for all targets).
Fix by adding 'webview=trace' to the COCO_LOG value so frontend logs
are also captured in the log file when running the packaged app.
* docs: release notes
* fix: apply local results weight to scores generated by rerank()
We have two kinds of scores:
1. Scores calculated by query sources
2. In the post-search phase, we re-score the documents in
`boosted_levenshtein_rerank()`
When applying the setting "local search results weight", previous
implementation modified the first score. Its effect was not noticeable,
since we collect documents evenly from the hits returned by query sources.
This commit refactors the implementation so that the setting adjusts the
second score, making the effect obvious.
* refactor: keep O(1) lookup && update var names
* chore: one more var name to update
* feat: support app search even if Spotlight is disabled
Previously, we relied on Spotlight (mdfind) to fetch the app list,
which means it won't work if users disable their Spotlight index.
This commit bumps the applications-rs library, which can now list
apps using `lsregister`, macOS's launch service tool. (See commit [1]
for details). With this, our app search works even tough Spotlight
is disabled.
[1]: ec174b7761
* release notes
I was digging into an issue that the "File Search" extension does
not appear in the extension list under some cases, then I realized
that, in list_extensions(), "File Search" is another extension that
needs to be processed separately, just like the "Applications"
extension.
Both extensions are of type group/extension, which semantically should
behave like a folder, i.e., they contain sub-extensions, but they
do not. In our implementation, they are more like command extensions.
So we treat them as normal extensions in list_extensioins().
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.
* 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 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.