Repository navigation
feat(mobile): rebuild the chat tab on the harness SDK - #5895
Conversation
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummarySince the previous review at Files Reviewed (12 files)
Previous Review Summaries (18 snapshots, latest commit 9319f7a)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 9319f7a)Status: No Issues Found | Recommendation: Merge Executive SummaryThe only change since Files Reviewed (1 file)
Previous review (commit f2f1ea6)Status: No Issues Found | Recommendation: Merge Executive SummaryThe two follow-up commits since Files Reviewed (2 files)
Previous review (commit db90d79)Status: No Issues Found | Recommendation: Merge Executive SummaryThe six follow-up commits since Files Reviewed (11 files)
Previous review (commit f5ccfb5)Status: 6 Issues Found | Recommendation: Address before merge Executive SummaryThe new Kilo MCP path is well-fenced for tokens and cross-account state, but five timing/lifecycle gaps remain: a joined discovery ignores the caller's deadline, the remote-MCP client fetches its credential outside the deadline it documents, its abort link is dropped before a streamed body is read, a slow tool call can never be backgrounded as documented, and the MCP sheet renders an inert switch in the unavailable state. Overview
Fix these issues in Kilo Cloud: https://app.kilo.ai/cloud-agent-fork/review/39691b24-1e79-4dcf-989d-5049d6139dc7 Issue Details (click to expand)CRITICALNone. WARNING
SUGGESTION
Files Reviewed (32 files)
Previous review (commit 203212f)Status: No Issues Found | Recommendation: Merge Executive SummaryThe branch was force-pushed and rebased, so the previously reviewed SHA Files Reviewed (12 files)
Previous review (commit cffb1a1)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental delta from the previously reviewed commit ( Files Reviewed (1 file)
Previous review (commit 1d2b9b7)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental delta from the previously reviewed commit ( Files Reviewed (14 files)
Previous review (commit 9c1ceed)Status: No Issues Found | Recommendation: Merge Executive SummaryThe follow-up fix resolves the prior moved-chat cleanup finding: Files Reviewed (2 files)
Previous review (commit 465cc6c)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe fix commit resolves the three prior findings; the only new issue is that the moved-chat test cleanup is a no-op, leaving the move pointer and a live session across tests. Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (7 files)
Fix these issues in Kilo Cloud Previous review (commit 2573d62)Status: 3 Issues Found | Recommendation: Address before merge Executive SummaryThree residual issues in the new chat registry and hook: a failed reopen leaks its session scope, the Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (14 files)
Fix these issues in Kilo Cloud Previous review (commit 8f2d387)Status: 7 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (45 files)
Fix these issues in Kilo Cloud Previous review (commit b374fb3)Status: No Issues Found | Recommendation: Merge Files Reviewed (5 files)
Previous review (commit e585a7e)Status: No Issues Found | Recommendation: Merge Files Reviewed (31 files)
Previous review (commit 326f2c3)Status: No Issues Found | Recommendation: Merge Files Reviewed (3 files)
Previous review (commit a7e6c90)Status: No Issues Found | Recommendation: Merge Files Reviewed (3 files)
Previous review (commit 02d4575)Status: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (10 files)
Fix these issues in Kilo Cloud Previous review (commit fee11c2)Status: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (10 files)
Fix these issues in Kilo Cloud Previous review (commit 5c686fd)Status: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (3 files)
Fix these issues in Kilo Cloud Additional previous summary content was truncated to keep this comment within platform limits. Reviewed by deepseek-v4.1-flash · Input: 91.9K · Output: 24.6K · Cached: 1.4M Review guidance: REVIEW.md from base branch |
ef4251c to
326f2c3
Compare
326f2c3 to
2bf4d8d
Compare
62dae71 to
0eb98d1
Compare
0eb98d1 to
5c5a68c
Compare
5c5a68c to
84e71c4
Compare
84e71c4 to
4ae54a0
Compare
4ae54a0 to
8f2d387
Compare
8f2d387 to
2573d62
Compare
…on inline A remote tool is waited on for 15 s before the session backgrounds it, and the call's own default deadline was also 15 s, so a backgrounded call failed at that moment instead of answering. A call now defaults to 60 s; discovery keeps 15 s.
The registry builds a chat from the snapshot, not from the return value. A cache hit returned the ready answer while another scope's discovery had published connecting over it, so the chat opened on the base tools.
A caller that joined a running discovery took the first caller's deadline, so an open that met a Retry waited fifteen seconds and a Retry that met an open was cut to four. A caller now joins only a discovery with its own deadline, and only the latest discovery is published.
In the unavailable state the switch read off while the chat's setting was on, so a tap wrote the value already stored and the switch snapped back. The view now says whether the switch can move, and the sheet disables it when not.
…/mobile-harness-chat
Main added a shouldHideTabBar call in app-root-providers.tsx with the old one-argument form. This branch reads the chat conversation from the segments, so the call now passes them too.
…h test Main's lifecycle file already holds queryClientMock at module scope. The branch's test declared it again from a dynamic import, which lint refuses as a shadow and as an unbound method.
vitest.setup.ts now stubs @/lib/config for every pure suite, so the plain dynamic import in config.test.ts returned the stub and KILO_MCP_URL read as undefined. The test now loads the module through vi.importActual.
…/mobile-harness-chat
…/mobile-harness-chat # Conflicts: # apps/mobile/AGENTS.md # apps/mobile/package.json # apps/mobile/src/components/kilo-pass/kilo-pass-subscription-screen.test.ts # apps/mobile/src/components/kilo-pass/kilo-pass-subscription-screen.tsx # apps/mobile/src/components/quick-chat/quick-chat-screen.mounted.test.tsx # apps/mobile/src/components/quick-chat/quick-chat-screen.tsx # apps/mobile/src/i18n/locales/am.json # apps/mobile/src/i18n/locales/az.json # apps/mobile/src/i18n/locales/fa.json # apps/mobile/src/i18n/locales/gu.json # apps/mobile/src/i18n/locales/hy.json # apps/mobile/src/i18n/locales/km.json # apps/mobile/src/i18n/locales/ml.json # apps/mobile/src/i18n/locales/mn.json # apps/mobile/src/i18n/locales/my.json # apps/mobile/src/i18n/locales/ne.json # apps/mobile/src/i18n/locales/or.json # apps/mobile/src/i18n/locales/pa.json # apps/mobile/src/i18n/locales/si.json # apps/mobile/src/i18n/locales/te.json # apps/mobile/src/i18n/locales/uz.json # apps/web/src/routers/quick-chat-router.test.ts # apps/web/src/routers/quick-chat-router.ts # packages/db/src/migrations/meta/0263_snapshot.json # packages/db/src/migrations/meta/_journal.json # pnpm-lock.yaml
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
…uick Chat (#7338) * feat(harness-sdk): the kilo harness SDK #5878 * feat(mobile): rebuild the chat tab on the harness SDK #5895 * chore(kilo-mcp): refresh catalog.json from CI * feat(mobile): connect chat to the Kilo MCP server with the signed-in session (#6420) #6420 * chore: publish the verified app-agent settings tools + remote MCP stack as one PR (level 1) * fix(mobile): preserve settings and remote MCP state across cold loads * fix(mobile): satisfy async and control-flow lint rules * fix(harness-sdk): keep the library's abort link until the operation ends fetch resolves when the headers arrive, so the per-request unlink let close() leave an open stream running until the deadline timer fired. The deadline now holds each joined signal once and removes it at stop. * fix(harness-sdk): bound the credential by the operation's deadline The token was asked before the deadline existed, so a slow refresh could hold a chat open past the discovery bound. The deadline now comes first and the credential races it. * fix(harness-sdk): give a call a deadline above the time it is waited on inline A remote tool is waited on for 15 s before the session backgrounds it, and the call's own default deadline was also 15 s, so a backgrounded call failed at that moment instead of answering. A call now defaults to 60 s; discovery keeps 15 s. * fix(mobile): publish the Kilo tools answer that a cache hit serves The registry builds a chat from the snapshot, not from the return value. A cache hit returned the ready answer while another scope's discovery had published connecting over it, so the chat opened on the base tools. * fix(mobile): keep each Kilo tools discovery on its caller's deadline A caller that joined a running discovery took the first caller's deadline, so an open that met a Retry waited fifteen seconds and a Retry that met an open was cut to four. A caller now joins only a discovery with its own deadline, and only the latest discovery is published. * fix(mobile): lock the Kilo tools switch when there is nothing to use In the unavailable state the switch read off while the chat's setting was on, so a tap wrote the value already stored and the switch snapped back. The view now says whether the switch can move, and the sheet disables it when not. * fix(deps): rebuild the lockfile on main's pins The merge rebuilt the lockfile from the branch side, so pnpm resolved again every package main had added since. That moved @peculiar/asn1-* to 2.9.5 and broke the passkey verification tests in apps/web. The lockfile is now main's, with only the harness SDK's own entries added. * fix(mobile): pass the segments to the toaster's tab bar check Main added a shouldHideTabBar call in app-root-providers.tsx with the old one-argument form. This branch reads the chat conversation from the segments, so the call now passes them too. * test(mobile): read the hoisted query client mock in the account switch test Main's lifecycle file already holds queryClientMock at module scope. The branch's test declared it again from a dynamic import, which lint refuses as a shadow and as an unbound method. * fix(mobile): describe the spend alerts notification setting Main added the spendAlerts notification category. The agent settings catalog maps every category to a description, so typecheck failed on the missing one. * fix(mobile): use the shared MCP servers copy in the chat sheet Main added profiles.mcp.title and profiles.mcp.add with the same English copy as modelChat.mcp.serversSection and modelChat.mcp.addServer, and the catalog check refuses two keys for one copy. The chat section now reads the profile keys, and the two chat keys are removed from every catalog. * test(mobile): load the real config module in the MCP URL test vitest.setup.ts now stubs @/lib/config for every pure suite, so the plain dynamic import in config.test.ts returned the stub and KILO_MCP_URL read as undefined. The test now loads the module through vi.importActual. * test(mobile): allow the remote MCP id slug in the case guard slugFor in remote-mcp-store.ts lowercases a server name to build the callable tool-name id. The id is never shown, so the file joins the non-display list. * feat(mobile): support configurable Quick Chat backends * test(harness): construct synthetic credential URL explicitly * fix(mobile): address Quick Chat backend review findings * fix(mobile): reopen a failed chat from Retry * test(mobile): allow protocol-identifier case normalization in backend files * fix(mobile): wait for stored backends before the send check * feat(mobile): add on-device Apple Foundation Models to Quick Chat * feat(mobile): add on-device Gemini Nano to Quick Chat on Android * fix(mobile): reference the Retry label in the on-device background copy * feat(mobile): add llama.rn GGUF models to Quick Chat * style(mobile): format the on-device GGUF files * test(mobile): allow the GGUF file-extension comparison in the case guard * fix(mobile): keep unreadable model entries from deleting downloads * test(mobile): split the model-index policy tests into their own suite * fix(mobile): never rewrite a model list holding an unreadable entry * fix(mobile): keep any list that did not parse in full from being rewritten * fix(mobile): read a GGUF result that carries nulls or only text * fix(mobile): treat a null parsed content as absent * test(mobile): pin the null-heavy llama.rn result at the client level * feat(mobile): open message details and recover a failed question in Quick Chat A long-press on a Quick Chat message opens the message details sheet. The unanswered question carries Retry and Copy to composer inline. A failed answer reads as a failed response, not as a stopped message. The chat row under the transcript states the reason and keeps its Retry only when no question waits for an answer. Quick Chat messages carry no model and no time. A model switch copies every turn into a new session, so the details sheet omits those rows. * fix(mobile): drop the duplicate llama.rn proguard rule The merge of main added a second extraProguardRules next to main's combined rule, which app.config.ts rejects as a duplicate key. Keep main's combined rule. * ci(trufflehog): exclude the synthetic-credential test fixture security.test.ts builds a credential URL from the literal 'user:private-key@provider.example'. The commit that added it stays in this branch's history, so trufflehog reports it on every base..head scan even though a later commit replaced it with a constructed value. Exclude the fixture path. * fix(db): drop the stale duplicate 0263_drop_quick_chat migration main lands the drop as 0274_drop_quick_chat.sql (registered in the journal). The same drop sits in this branch's lineage as 0263_drop_quick_chat.sql, unregistered and colliding with 0263_spend_alerts_rollup_covering_index. The merge kept it because main never had that path. Remove it; the tree now matches main. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(harness-sdk): the kilo harness SDK #5878 * feat(mobile): rebuild the chat tab on the harness SDK #5895 * chore(kilo-mcp): refresh catalog.json from CI * feat(mobile): connect chat to the Kilo MCP server with the signed-in session (#6420) #6420 * chore: publish the verified app-agent settings tools + remote MCP stack as one PR (level 1) * fix(mobile): preserve settings and remote MCP state across cold loads * fix(mobile): satisfy async and control-flow lint rules * fix(harness-sdk): keep the library's abort link until the operation ends fetch resolves when the headers arrive, so the per-request unlink let close() leave an open stream running until the deadline timer fired. The deadline now holds each joined signal once and removes it at stop. * fix(harness-sdk): bound the credential by the operation's deadline The token was asked before the deadline existed, so a slow refresh could hold a chat open past the discovery bound. The deadline now comes first and the credential races it. * fix(harness-sdk): give a call a deadline above the time it is waited on inline A remote tool is waited on for 15 s before the session backgrounds it, and the call's own default deadline was also 15 s, so a backgrounded call failed at that moment instead of answering. A call now defaults to 60 s; discovery keeps 15 s. * fix(mobile): publish the Kilo tools answer that a cache hit serves The registry builds a chat from the snapshot, not from the return value. A cache hit returned the ready answer while another scope's discovery had published connecting over it, so the chat opened on the base tools. * fix(mobile): keep each Kilo tools discovery on its caller's deadline A caller that joined a running discovery took the first caller's deadline, so an open that met a Retry waited fifteen seconds and a Retry that met an open was cut to four. A caller now joins only a discovery with its own deadline, and only the latest discovery is published. * fix(mobile): lock the Kilo tools switch when there is nothing to use In the unavailable state the switch read off while the chat's setting was on, so a tap wrote the value already stored and the switch snapped back. The view now says whether the switch can move, and the sheet disables it when not. * fix(deps): rebuild the lockfile on main's pins The merge rebuilt the lockfile from the branch side, so pnpm resolved again every package main had added since. That moved @peculiar/asn1-* to 2.9.5 and broke the passkey verification tests in apps/web. The lockfile is now main's, with only the harness SDK's own entries added. * fix(mobile): pass the segments to the toaster's tab bar check Main added a shouldHideTabBar call in app-root-providers.tsx with the old one-argument form. This branch reads the chat conversation from the segments, so the call now passes them too. * test(mobile): read the hoisted query client mock in the account switch test Main's lifecycle file already holds queryClientMock at module scope. The branch's test declared it again from a dynamic import, which lint refuses as a shadow and as an unbound method. * fix(mobile): describe the spend alerts notification setting Main added the spendAlerts notification category. The agent settings catalog maps every category to a description, so typecheck failed on the missing one. * fix(mobile): use the shared MCP servers copy in the chat sheet Main added profiles.mcp.title and profiles.mcp.add with the same English copy as modelChat.mcp.serversSection and modelChat.mcp.addServer, and the catalog check refuses two keys for one copy. The chat section now reads the profile keys, and the two chat keys are removed from every catalog. * test(mobile): load the real config module in the MCP URL test vitest.setup.ts now stubs @/lib/config for every pure suite, so the plain dynamic import in config.test.ts returned the stub and KILO_MCP_URL read as undefined. The test now loads the module through vi.importActual. * test(mobile): allow the remote MCP id slug in the case guard slugFor in remote-mcp-store.ts lowercases a server name to build the callable tool-name id. The id is never shown, so the file joins the non-display list. * feat(mobile): support configurable Quick Chat backends * test(harness): construct synthetic credential URL explicitly * fix(mobile): address Quick Chat backend review findings * fix(mobile): reopen a failed chat from Retry * test(mobile): allow protocol-identifier case normalization in backend files * fix(mobile): wait for stored backends before the send check * feat(mobile): add on-device Apple Foundation Models to Quick Chat * feat(mobile): add on-device Gemini Nano to Quick Chat on Android * fix(mobile): reference the Retry label in the on-device background copy * feat(mobile): add llama.rn GGUF models to Quick Chat * style(mobile): format the on-device GGUF files * test(mobile): allow the GGUF file-extension comparison in the case guard * fix(mobile): keep unreadable model entries from deleting downloads * test(mobile): split the model-index policy tests into their own suite * fix(mobile): never rewrite a model list holding an unreadable entry * fix(mobile): keep any list that did not parse in full from being rewritten * fix(mobile): read a GGUF result that carries nulls or only text * fix(mobile): treat a null parsed content as absent * test(mobile): pin the null-heavy llama.rn result at the client level * fix(mobile): remove the mode chip from the Quick Chat composer Quick Chat is not an agent session, so modes do not apply. The toolbar and the composer take one optional modeControl object. Without it, the toolbar draws no mode chip and the model chip starts the row. * test(mobile): pin the mode control on the session composer * fix(mobile): drop the duplicate llama.rn proguard rule The merge of main added a second extraProguardRules next to main's combined rule, which app.config.ts rejects as a duplicate key. Keep main's combined rule. * ci(trufflehog): exclude the synthetic-credential test fixture security.test.ts builds a credential URL from the literal 'user:private-key@provider.example'. The commit that added it stays in this branch's history, so trufflehog reports it on every base..head scan even though a later commit replaced it with a constructed value. Exclude the fixture path. * fix(db): drop the stale duplicate 0263_drop_quick_chat migration main lands the drop as 0274_drop_quick_chat.sql (registered in the journal). The same drop sits in this branch's lineage as 0263_drop_quick_chat.sql, unregistered and colliding with 0263_spend_alerts_rollup_covering_index. The merge kept it because main never had that path. Remove it; the tree now matches main. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(harness-sdk): the kilo harness SDK #5878 * feat(mobile): rebuild the chat tab on the harness SDK #5895 * chore(kilo-mcp): refresh catalog.json from CI * feat(mobile): connect chat to the Kilo MCP server with the signed-in session (#6420) #6420 * chore: publish the verified app-agent settings tools + remote MCP stack as one PR (level 1) * fix(mobile): preserve settings and remote MCP state across cold loads * fix(mobile): satisfy async and control-flow lint rules * fix(harness-sdk): keep the library's abort link until the operation ends fetch resolves when the headers arrive, so the per-request unlink let close() leave an open stream running until the deadline timer fired. The deadline now holds each joined signal once and removes it at stop. * fix(harness-sdk): bound the credential by the operation's deadline The token was asked before the deadline existed, so a slow refresh could hold a chat open past the discovery bound. The deadline now comes first and the credential races it. * fix(harness-sdk): give a call a deadline above the time it is waited on inline A remote tool is waited on for 15 s before the session backgrounds it, and the call's own default deadline was also 15 s, so a backgrounded call failed at that moment instead of answering. A call now defaults to 60 s; discovery keeps 15 s. * fix(mobile): publish the Kilo tools answer that a cache hit serves The registry builds a chat from the snapshot, not from the return value. A cache hit returned the ready answer while another scope's discovery had published connecting over it, so the chat opened on the base tools. * fix(mobile): keep each Kilo tools discovery on its caller's deadline A caller that joined a running discovery took the first caller's deadline, so an open that met a Retry waited fifteen seconds and a Retry that met an open was cut to four. A caller now joins only a discovery with its own deadline, and only the latest discovery is published. * fix(mobile): lock the Kilo tools switch when there is nothing to use In the unavailable state the switch read off while the chat's setting was on, so a tap wrote the value already stored and the switch snapped back. The view now says whether the switch can move, and the sheet disables it when not. * fix(deps): rebuild the lockfile on main's pins The merge rebuilt the lockfile from the branch side, so pnpm resolved again every package main had added since. That moved @peculiar/asn1-* to 2.9.5 and broke the passkey verification tests in apps/web. The lockfile is now main's, with only the harness SDK's own entries added. * fix(mobile): pass the segments to the toaster's tab bar check Main added a shouldHideTabBar call in app-root-providers.tsx with the old one-argument form. This branch reads the chat conversation from the segments, so the call now passes them too. * test(mobile): read the hoisted query client mock in the account switch test Main's lifecycle file already holds queryClientMock at module scope. The branch's test declared it again from a dynamic import, which lint refuses as a shadow and as an unbound method. * fix(mobile): describe the spend alerts notification setting Main added the spendAlerts notification category. The agent settings catalog maps every category to a description, so typecheck failed on the missing one. * fix(mobile): use the shared MCP servers copy in the chat sheet Main added profiles.mcp.title and profiles.mcp.add with the same English copy as modelChat.mcp.serversSection and modelChat.mcp.addServer, and the catalog check refuses two keys for one copy. The chat section now reads the profile keys, and the two chat keys are removed from every catalog. * test(mobile): load the real config module in the MCP URL test vitest.setup.ts now stubs @/lib/config for every pure suite, so the plain dynamic import in config.test.ts returned the stub and KILO_MCP_URL read as undefined. The test now loads the module through vi.importActual. * test(mobile): allow the remote MCP id slug in the case guard slugFor in remote-mcp-store.ts lowercases a server name to build the callable tool-name id. The id is never shown, so the file joins the non-display list. * feat(mobile): support configurable Quick Chat backends * test(harness): construct synthetic credential URL explicitly * fix(mobile): address Quick Chat backend review findings * fix(mobile): reopen a failed chat from Retry * test(mobile): allow protocol-identifier case normalization in backend files * fix(mobile): wait for stored backends before the send check * feat(mobile): add on-device Apple Foundation Models to Quick Chat * feat(mobile): add on-device Gemini Nano to Quick Chat on Android * fix(mobile): reference the Retry label in the on-device background copy * feat(mobile): add llama.rn GGUF models to Quick Chat * style(mobile): format the on-device GGUF files * test(mobile): allow the GGUF file-extension comparison in the case guard * fix(mobile): keep unreadable model entries from deleting downloads * test(mobile): split the model-index policy tests into their own suite * fix(mobile): never rewrite a model list holding an unreadable entry * fix(mobile): keep any list that did not parse in full from being rewritten * fix(mobile): read a GGUF result that carries nulls or only text * fix(mobile): treat a null parsed content as absent * test(mobile): pin the null-heavy llama.rn result at the client level * feat(mobile): send images to Quick Chat models that read them Quick Chat accepts images from the picker and the clipboard when the selected model reads images. The images stay on the device: the composer reads them as bounded JPEG base64 and hands them to the send path. The Cloud Agent upload path does not change. Capability contract: - backend-capabilities.ts: targetSupportsImages(targetId), resolvedTargetSupportsImages(target), rememberKiloImageModels(models) and useTargetSupportsImages(targetId). - LocalModelProvider.supportsImages(modelId). Every on-device provider returns false. - Kilo models read image support from the gateway catalog (architecture.input_modalities). Custom backend models get an images flag with a toggle. A stored model without the flag reads as text-only. The router replaces image parts with a short text marker for a target that does not read images, so a model switch after an image does not fail at the provider. The unanswered question keeps its images for Retry, and the transcript shows them. * feat(mobile): read images with downloaded vision models A downloaded GGUF model can now read images when it has a vision projector (mmproj). The catalog adds SmolVLM 500M Instruct with its projector, both pinned to one Hugging Face revision with size, SHA-256 and licence. - Downloads: a vision model downloads the model file, then the projector, as one download with one progress bar and one storage check. Cancel, failure and delete remove both files. - Records: a record has a vision flag. A record saved before this change reads as text-only. - Inspection: a vision model loads in full with its projector, and the download is accepted only when llama.cpp reports vision support. - Runtime: the context loads the projector after init with ctx_shift off. supportsImages is true only for a verified vision record. - Template: a user turn with an image goes to llama.rn as content parts with a base64 data URL. llama.rn decodes it, so no image file is written. A model without a projector does not get images. Direct-link models stay text-only. * fix(mobile): keep the catalog file type private * fix(mobile): show no upload progress on a local Quick Chat image A local image never uploads, so its chip starts with no progress value and the strip does not read "0%". * fix(mobile): release the native image on every encode path The encoder now releases the rendered image after a failed read or a failed save, not only after a successful one. Tests pin the release on each path, and that the images flag survives a backend save. * test(mobile): pin the native image release and the backend image flag Tests: the encoder releases each rendered image after a read, a resize, a failed save and a too-large result; a backend save keeps the image flag. * fix(mobile): a local Quick Chat image is not an upload A locally delivered image chip had status 'pending', which the strip treats as an upload in flight: a permanent spinner and an "Uploading…" announcement for an image that never leaves the device. Local chips now carry a 'local' status that starts no upload, shows no progress and announces the file size instead. * fix(mobile): drop the duplicate llama.rn proguard rule The merge of main added a second extraProguardRules next to main's combined rule, which app.config.ts rejects as a duplicate key. Keep main's combined rule. * ci(trufflehog): exclude the synthetic-credential test fixture security.test.ts builds a credential URL from the literal 'user:private-key@provider.example'. The commit that added it stays in this branch's history, so trufflehog reports it on every base..head scan even though a later commit replaced it with a constructed value. Exclude the fixture path. * fix(db): drop the stale duplicate 0263_drop_quick_chat migration main lands the drop as 0274_drop_quick_chat.sql (registered in the journal). The same drop sits in this branch's lineage as 0263_drop_quick_chat.sql, unregistered and colliding with 0263_spend_alerts_rollup_covering_index. The merge kept it because main never had that path. Remove it; the tree now matches main. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(harness-sdk): the kilo harness SDK #5878 * feat(mobile): rebuild the chat tab on the harness SDK #5895 * chore(kilo-mcp): refresh catalog.json from CI * feat(mobile): connect chat to the Kilo MCP server with the signed-in session (#6420) #6420 * chore: publish the verified app-agent settings tools + remote MCP stack as one PR (level 1) * fix(mobile): preserve settings and remote MCP state across cold loads * fix(mobile): satisfy async and control-flow lint rules * fix(harness-sdk): keep the library's abort link until the operation ends fetch resolves when the headers arrive, so the per-request unlink let close() leave an open stream running until the deadline timer fired. The deadline now holds each joined signal once and removes it at stop. * fix(harness-sdk): bound the credential by the operation's deadline The token was asked before the deadline existed, so a slow refresh could hold a chat open past the discovery bound. The deadline now comes first and the credential races it. * fix(harness-sdk): give a call a deadline above the time it is waited on inline A remote tool is waited on for 15 s before the session backgrounds it, and the call's own default deadline was also 15 s, so a backgrounded call failed at that moment instead of answering. A call now defaults to 60 s; discovery keeps 15 s. * fix(mobile): publish the Kilo tools answer that a cache hit serves The registry builds a chat from the snapshot, not from the return value. A cache hit returned the ready answer while another scope's discovery had published connecting over it, so the chat opened on the base tools. * fix(mobile): keep each Kilo tools discovery on its caller's deadline A caller that joined a running discovery took the first caller's deadline, so an open that met a Retry waited fifteen seconds and a Retry that met an open was cut to four. A caller now joins only a discovery with its own deadline, and only the latest discovery is published. * fix(mobile): lock the Kilo tools switch when there is nothing to use In the unavailable state the switch read off while the chat's setting was on, so a tap wrote the value already stored and the switch snapped back. The view now says whether the switch can move, and the sheet disables it when not. * fix(deps): rebuild the lockfile on main's pins The merge rebuilt the lockfile from the branch side, so pnpm resolved again every package main had added since. That moved @peculiar/asn1-* to 2.9.5 and broke the passkey verification tests in apps/web. The lockfile is now main's, with only the harness SDK's own entries added. * fix(mobile): pass the segments to the toaster's tab bar check Main added a shouldHideTabBar call in app-root-providers.tsx with the old one-argument form. This branch reads the chat conversation from the segments, so the call now passes them too. * test(mobile): read the hoisted query client mock in the account switch test Main's lifecycle file already holds queryClientMock at module scope. The branch's test declared it again from a dynamic import, which lint refuses as a shadow and as an unbound method. * fix(mobile): describe the spend alerts notification setting Main added the spendAlerts notification category. The agent settings catalog maps every category to a description, so typecheck failed on the missing one. * fix(mobile): use the shared MCP servers copy in the chat sheet Main added profiles.mcp.title and profiles.mcp.add with the same English copy as modelChat.mcp.serversSection and modelChat.mcp.addServer, and the catalog check refuses two keys for one copy. The chat section now reads the profile keys, and the two chat keys are removed from every catalog. * test(mobile): load the real config module in the MCP URL test vitest.setup.ts now stubs @/lib/config for every pure suite, so the plain dynamic import in config.test.ts returned the stub and KILO_MCP_URL read as undefined. The test now loads the module through vi.importActual. * test(mobile): allow the remote MCP id slug in the case guard slugFor in remote-mcp-store.ts lowercases a server name to build the callable tool-name id. The id is never shown, so the file joins the non-display list. * feat(mobile): support configurable Quick Chat backends * test(harness): construct synthetic credential URL explicitly * fix(mobile): address Quick Chat backend review findings * fix(mobile): reopen a failed chat from Retry * test(mobile): allow protocol-identifier case normalization in backend files * fix(mobile): wait for stored backends before the send check * feat(mobile): add on-device Apple Foundation Models to Quick Chat * feat(mobile): add on-device Gemini Nano to Quick Chat on Android * fix(mobile): reference the Retry label in the on-device background copy * feat(mobile): add llama.rn GGUF models to Quick Chat * style(mobile): format the on-device GGUF files * test(mobile): allow the GGUF file-extension comparison in the case guard * fix(mobile): keep unreadable model entries from deleting downloads * test(mobile): split the model-index policy tests into their own suite * fix(mobile): never rewrite a model list holding an unreadable entry * fix(mobile): keep any list that did not parse in full from being rewritten * fix(mobile): read a GGUF result that carries nulls or only text * fix(mobile): treat a null parsed content as absent * test(mobile): pin the null-heavy llama.rn result at the client level * feat(mobile): give the Apple on-device model the chat's tools Foundation Models calls harness tools through dynamic tools. The model's calls go to JavaScript as harness toolCall parts with the transcript ids. The generation waits while the harness runs them, and the next request resumes it with the results. Later requests rebuild the transcript with the tool calls and their outputs. JavaScript reduces each JSON Schema to what DynamicGenerationSchema can express. A tool that does not fit is left out and logged. Gemini Nano stays text-only because the ML Kit Prompt API has no function calling. * fix(mobile): keep native schema and message types module-private * fix(mobile): count tokens for a request that ends on tool outputs A resumed tool round sends a request whose last entry is a tool output. The Apple module refused to count it, so usage fell back to the estimate. Only generation now needs a user prompt last. * fix(mobile): drop the duplicate llama.rn proguard rule The merge of main added a second extraProguardRules next to main's combined rule, which app.config.ts rejects as a duplicate key. Keep main's combined rule. * fix(kilo-app): build the harness SDK before the EAS bundle The release EAS build bundles apps/mobile with Metro, which resolves @kilocode/harness-sdk through its package.json exports to dist/index.js. The workspace package is not built on EAS, so the Android and iOS bundles fail with 'none of these files exist' and the release never submits. Add the eas-build-post-install hook the EAS build runs after install. It builds the SDK, so Metro finds dist before it bundles. Verified with expo export:embed --eager --platform android: it fails without dist and succeeds after the hook builds it. * ci(trufflehog): exclude the synthetic-credential test fixture security.test.ts builds a credential URL from the literal 'user:private-key@provider.example'. The commit that added it stays in this branch's history, so trufflehog reports it on every base..head scan even though a later commit replaced it with a constructed value. Exclude the fixture path. * fix(db): drop the stale duplicate 0263_drop_quick_chat migration main lands the drop as 0274_drop_quick_chat.sql (registered in the journal). The same drop sits in this branch's lineage as 0263_drop_quick_chat.sql, unregistered and colliding with 0263_spend_alerts_rollup_covering_index. The merge kept it because main never had that path. Remove it; the tree now matches main. * fix(mobile): keep NativeImage module-private knip flags the export as unused: only native-request.ts builds an image part. Drop the export keyword. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Changelog for users
+, reopen one you had, retry a question that never got an answer, and long press a chat to delete it.FEATURE_FLAG_CHAT, off by default.Changelog for maintainers
chatstable and the SDK'ssessions/turns/partson the one encrypted database. The token comes from the app's auth, randomness from expo-crypto, and the data is SQLCipher-encrypted at rest.en.jsondoes not define are removed. The removed keys areprofile.signOut,securityAgent.settingsSave.keepEditing,agentChat.filePart.imageUnavailableWithAlt,agentChat.modelSelector.thinkingEffortXhigh,agentChat.modelSelector.thinkingEffortMedium,agentChat.composer.messagePlaceholder,kiloPass.unavailableDescription,kiloPass.webManagementDescription, andorganization.invoices.loadMoreFailed. A file that also holds an unreviewed value keeps its approved restored values instead of being reverted whole.kiloPass.unavailablecopy becomes "Couldn't load Kilo Pass."; the English subscription description is unchanged.releaseChatreleased the id a chat moved off, which no longer named a running session, so the cleanup cleared nothing. It now resolves the id through the move pointer and ends the chat that carried on, dropping the live state and the pointer. The added test reads both halves after that release: the live chat resets toopening, and the moved-off id stops resolving to it. ReviewreleaseChatfirst: it resolves withsnapshotOf(sessionId).sessionId, so a caller naming a moved-off id ends the live session instead of forgetting a state that no longer exists. The new Android device run is the tip proof for the delete path, replacing the earlier unit-test-only claim for it.E2E proof