Repository navigation
Conversation
Louis-CFM
added a commit
that referenced
this pull request
Oct 6, 2026
* feat: add GitHub Copilot CLI, Muse Code, OpenCode, Amp agents (#262) - agent_copilot: writes ~/.copilot/hooks/coucou.json with camelCase Claude Code events; fail-closed — relay outputs {"permissionDecision":"ask"} on timeout so Copilot re-prompts instead of denying - agent_muse: merges into ~/.config/muse/settings.json like Gemini; relay normalises snake_case events (pre_tool_use → PreToolUse, etc.) - agent_opencode: writes ~/.config/opencode/plugins/coucou.js (JS plugin, fire-and-forget, never blocks OpenCode) - agent_amp: writes ~/.config/amp/plugins/coucou.ts (TS plugin, display only, never blocks Amp) - PillCatalog: agent_copilot #818CF8, agent_muse #38BDF8, agent_opencode #4ADE80, agent_amp #F59E0B — all githubOnly - SettingsView: installer GroupBox + trigger/confirm functions for all 4 - IslandViewContent: pill-tap → terminal, isConfigured, isHooks, hints - Python relay (both GitHub and App Store builds): normalize_event adds Muse snake_case mappings; fire-and-forget outputs {} for muse like gemini/antigravity; Copilot PermissionRequest timeout → ask JSON - docs/AGENTS.md: entries for all 4 new agents Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat/more-agents: fix Copilot, Muse, OpenCode and Amp end-to-end Copilot CLI: - Hook format: camelCase event keys, bash/timeoutSec, event name as positional arg, version:1 at root - Uninstall deletes the file entirely instead of leaving {} - copilotHooksInstalled() checks "bash" key - processPermissionRequest shows real Allow/Deny card for copilot agent; relay outputs {"permissionDecision":"allow|deny"} directly Muse Code: - Hook format: PascalCase event keys (was snake_case) - Add PermissionRequest hook (120 s) - Add schema_version:1 when creating a new settings file - processPermissionRequest shows real Allow/Deny card for muse agent; relay outputs {"permissionDecision":"allow|deny"} directly OpenCode plugin: - Rewritten to use CoucouPlugin = async (ctx) => ({ event: async }) API - Maps OpenCode event types to canonical Coucou names in the plugin itself - Error handlers on spawn and stdin Amp plugin: - Rewritten to use amp.on('event-name', handler) API - tool.call handler returns { action: 'allow' } (required by Amp) - Per-event handlers for SessionStart/UserPromptSubmit/PreToolUse/ PostToolUse/Stop with correct session_id forwarding - Error handlers on spawn and stdin Python relays (both GitHub and App Store versions): - normalize_event: add sessionStart, userPromptSubmitted, agentStop, notification, stop - normalize_tool_fields: add toolName->tool_name, toolArgs->tool_input, workdir->cwd (Copilot CLI fields) - PermissionRequest: copilot/muse output {"permissionDecision":"allow|deny"} instead of hookSpecificOutput; always → plain allow for copilot/muse - Normal events: add copilot to agents that output {} on stdout - Wrap main() in try/except at top level Shell wrapper: - Output {"permissionDecision":"ask"} when python3 unavailable and the call is copilot permissionRequest (fail-closed guarantee) Plugin safety: - removeOpenCodePlugin/removeAmpPlugin check "generated by Coucou" header before deleting - previewOpenCodePlugin/previewAmpPlugin and their write counterparts now use SHA-256 fingerprint to detect file changes between preview and write Docs: update AGENTS.md with correct event tables for all four agents Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(agents): normalize_event, OpenCode hooks, Amp try/finally, Copilot/Muse Always button - normalize_event: add preToolUse→PreToolUse, postToolUse→PostToolUse, permissionRequest→PermissionRequest, sessionEnd→SessionEnd (both relays) - Wrapper shell: copilot without permissionRequest now returns {} (not nothing) - OpenCode plugin: filter unknown event types, read from event.properties, use e.tool as string directly - Amp plugin: surround forward() with try/finally so tool.call always returns {action:'allow'}; use typeof e.tool === 'string' check - Move isCopilotRequest/isMuseRequest inside #if !APPSTORE guard - Add handledNote cases for agent_copilot and agent_muse - Reduce relay wait to 110s for Copilot/Muse - Update docs/SPEC.md and windows/README.md with new agents Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(agents): OpenCode separate tool hooks, README agent table - Remove tool.execute.before/after from EVENT_MAP; add as top-level plugin object properties with correct async signatures - Root README: agent list + config table with Copilot CLI, Muse Code, OpenCode (Mac-only), Amp (Mac-only) - windows/README: Mac-only plugin installer note with workaround path Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Louis-CFM
added a commit
that referenced
this pull request
Oct 6, 2026
* feat: add GitHub Copilot CLI, Muse Code, OpenCode, Amp agents (#262) - agent_copilot: writes ~/.copilot/hooks/coucou.json with camelCase Claude Code events; fail-closed — relay outputs {"permissionDecision":"ask"} on timeout so Copilot re-prompts instead of denying - agent_muse: merges into ~/.config/muse/settings.json like Gemini; relay normalises snake_case events (pre_tool_use → PreToolUse, etc.) - agent_opencode: writes ~/.config/opencode/plugins/coucou.js (JS plugin, fire-and-forget, never blocks OpenCode) - agent_amp: writes ~/.config/amp/plugins/coucou.ts (TS plugin, display only, never blocks Amp) - PillCatalog: agent_copilot #818CF8, agent_muse #38BDF8, agent_opencode #4ADE80, agent_amp #F59E0B — all githubOnly - SettingsView: installer GroupBox + trigger/confirm functions for all 4 - IslandViewContent: pill-tap → terminal, isConfigured, isHooks, hints - Python relay (both GitHub and App Store builds): normalize_event adds Muse snake_case mappings; fire-and-forget outputs {} for muse like gemini/antigravity; Copilot PermissionRequest timeout → ask JSON - docs/AGENTS.md: entries for all 4 new agents Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Weekly recap: local history store + Spotify Wrapped-style card + share image Adds a full weekly recap feature to Coucou Mac: - RecapStore: @mainactor singleton that persists session history to ~/Library/Application Support/NotchBuddy/recap.json. Records turns (pill, project, start/end, files ±, commands, questions) and permission decisions. 12-week retention. Always active, independent of iPhone sync. - WeeklyRecapCardView: notch card (.recap IslandView) with time, sessions, files and commands stats + "Share image" / "OK" buttons. - RecapShareImageView: 1080×1920 SwiftUI view rendered with ImageRenderer. Shows Coucou branding, primary time stat, secondary stats, and badges (top agent, top project, busiest day, longest session). RecapSharePanel opens an NSPanel with copy/save/share. - IslandTypes: .recap case added, ViewLayout matches .finished. - HookServer: RecapStore calls on UserPromptSubmit, PreToolUse, PostToolUse (after buildFileDiff), Stop, SessionEnd, and sendApprovalDecision. - AppState: recapEnabled + recapHideProjects (UserDefaults-backed). - SettingsView: "Weekly recap" GroupBox in General with enable toggle, privacy toggle and clear button. - AppDelegate: "Weekly recap" menu item + Monday ≥ 8am trigger after the greeting (shows once per week if there is activity). - scripts/test-weekly-recap.swift: fills recap.json with a fake week of activity for manual testing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat/more-agents: fix Copilot, Muse, OpenCode and Amp end-to-end Copilot CLI: - Hook format: camelCase event keys, bash/timeoutSec, event name as positional arg, version:1 at root - Uninstall deletes the file entirely instead of leaving {} - copilotHooksInstalled() checks "bash" key - processPermissionRequest shows real Allow/Deny card for copilot agent; relay outputs {"permissionDecision":"allow|deny"} directly Muse Code: - Hook format: PascalCase event keys (was snake_case) - Add PermissionRequest hook (120 s) - Add schema_version:1 when creating a new settings file - processPermissionRequest shows real Allow/Deny card for muse agent; relay outputs {"permissionDecision":"allow|deny"} directly OpenCode plugin: - Rewritten to use CoucouPlugin = async (ctx) => ({ event: async }) API - Maps OpenCode event types to canonical Coucou names in the plugin itself - Error handlers on spawn and stdin Amp plugin: - Rewritten to use amp.on('event-name', handler) API - tool.call handler returns { action: 'allow' } (required by Amp) - Per-event handlers for SessionStart/UserPromptSubmit/PreToolUse/ PostToolUse/Stop with correct session_id forwarding - Error handlers on spawn and stdin Python relays (both GitHub and App Store versions): - normalize_event: add sessionStart, userPromptSubmitted, agentStop, notification, stop - normalize_tool_fields: add toolName->tool_name, toolArgs->tool_input, workdir->cwd (Copilot CLI fields) - PermissionRequest: copilot/muse output {"permissionDecision":"allow|deny"} instead of hookSpecificOutput; always → plain allow for copilot/muse - Normal events: add copilot to agents that output {} on stdout - Wrap main() in try/except at top level Shell wrapper: - Output {"permissionDecision":"ask"} when python3 unavailable and the call is copilot permissionRequest (fail-closed guarantee) Plugin safety: - removeOpenCodePlugin/removeAmpPlugin check "generated by Coucou" header before deleting - previewOpenCodePlugin/previewAmpPlugin and their write counterparts now use SHA-256 fingerprint to detect file changes between preview and write Docs: update AGENTS.md with correct event tables for all four agents Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: weekly recap fixes — sessionId keying, interval merge, Monday triggers, share image - RecapStore: key drafts by sessionId (not pillId) to handle concurrent sessions; merge overlapping intervals for accurate "time coding"; Calendar(.iso8601) for Mon–Sun weeks; corrupt-file rename on load; pruneStale() drops drafts open > 2 h; clearHistory() always active; recordQuestionAnswered keyed by sessionId - HookServer: update all RecapStore call sites to pass sessionId; add stop() in StopFailure and Interrupt; post .checkMondayRecap on SessionStart + UserPromptSubmit - IslandWindowController: declare .checkMondayRecap notification name - AppDelegate: checkMondayRecap() now internal, uses .iso8601 calendar, guards against pendingApproval/pendingQuestion; add NSWorkspace didWake + .checkMondayRecap observers - WeeklyRecapView: draw Mochi via BotEngine Canvas in share image; add +/− lines stat; update footer to "Coucou · github.com/Louis-CFM/coucou" - SettingsView: remove hardcoded path, always enable "Clear history" button - test-weekly-recap.swift: remove .iso8601 date encoding (matches RecapStore default) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: Coucou in 10 languages Add Localizable.xcstrings (Xcode 15 String Catalog) with ~90 strings translated into en, zh-Hans, hi, es, ar, fr, bn, pt-BR, ru, id. - frenchStep → localizedStep; all step labels use String(localized: "step.*") - bashVerb returns use String(localized:) - PrimaryButton/SecondaryButton/AgentWho use Text(LocalizedStringKey(title)) - SearchingView.label, IntegrationCardView.statusLabel, FinishedView fallback all use String(localized:) for proper runtime lookup - sectionTitle computed var uses String(localized:) - SettingsSidebarRow uses Text(LocalizedStringKey(title)) - Language GroupBox in Settings → General: System + 10 languages, applies via AppleLanguages UserDefaults, Restart Coucou button - AppState.appLanguage property reads current AppleLanguages preference - AppDelegate menu items use NSLocalizedString - IslandWindowController: .environment(\.layoutDirection, .leftToRight) keeps notch window LTR even for Arabic - README invites community translation PRs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(i18n): localize all visible text — 10 languages, 240 keys - Add Localizable.xcstrings with 240 keys across ar, bn, es, fr, hi, id, pt-BR, ru, zh-Hans - Localize SettingsView (agents, chat, integrations, iPhone, active pills, all status messages, NSAlert) - Localize WeeklyRecapView (notch card + 1080×1920 share image) - Localize ClaudePlanCardView (title, gauge labels, countdown/subtitle strings) - Localize ShortcutLogic (displayName + islandShortcuts descriptions) - Localize ShortcutsSettingsView (GroupBox titles, reset button, conflict tags) - Add verbatim PrimaryButton/SecondaryButton inits for dynamic content (AskUserQuestion options, filenames) - Fix AppState.appLanguage to read from persistentDomain so System is default - Fix broken sentence fragments (file.ready %@, mail.with %@) into single format keys - Fix "Active pills" translations (tabs not medicine pills) - Fix "Too many hits at once." (clicking Mochi, not HTTP requests) - Restart via Process sleep+open+NSApp.terminate so HookServer port clears - project.yml: knownRegions + CFBundleLocalizations (10 codes) in NotchBuddy + CoucouAppStore - Both NotchBuddy and CoucouAppStore schemes build clean Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(i18n): add en source values to all 246 keys, fix format-specifier key names, restart logic - Add "en" source value to all 228 previously missing keys (was showing raw key in English) - Rename 5 format-specifier key names to match code usage: settings.slots-used → settings.slots-used %lld status.local.{no-models,connected,connected.plural,unreachable} + specifiers - Add 7 new keys: file.ready %@, mail.with %@, Weekly recap, Keep a history…, Stored locally…, Hide project names…, Clear history (all 10 languages) - Remove orphan key settings.startup - Fix restart logic: wait for PID to exit, use open bundleURL.path (not open -b) - Fix Claude is reading interpolation to use String(format:) with %@ key - Add defaultValue to all step.* String(localized:) calls - Patch pbxproj knownRegions with all 10 locales Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(i18n): add 29 more notch card and action button translations (10 languages) Activity, AUTO, Clear, Close, Copy, Deployments, Diff too large, Draft, Emails, Loading…, Main, No calls scheduled, No changes, Nothing here, Open, Open Codex/Cursor/Music/Settings/VS Code, Overview, Payments, Recent, Refresh, Resend, Save…, Schedule, Share…, Ask a question about it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(agents): normalize_event, OpenCode hooks, Amp try/finally, Copilot/Muse Always button - normalize_event: add preToolUse→PreToolUse, postToolUse→PostToolUse, permissionRequest→PermissionRequest, sessionEnd→SessionEnd (both relays) - Wrapper shell: copilot without permissionRequest now returns {} (not nothing) - OpenCode plugin: filter unknown event types, read from event.properties, use e.tool as string directly - Amp plugin: surround forward() with try/finally so tool.call always returns {action:'allow'}; use typeof e.tool === 'string' check - Move isCopilotRequest/isMuseRequest inside #if !APPSTORE guard - Add handledNote cases for agent_copilot and agent_muse - Reduce relay wait to 110s for Copilot/Muse - Update docs/SPEC.md and windows/README.md with new agents Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(recap): onChange reload, pruneStale 2h, Monday re-check, card lines/questions, test PNG - WeeklyRecapCardView: recalculate summary on onChange(state.view → .recap) - RecapStore.pruneStale: track lastEvent on each event; sessions with no events for 2h become completed turns instead of being dropped silently - AppDelegate Monday recap: re-check pendingApproval/pendingQuestion inside the delayed block before expanding to .recap - Notch card: show +lines/-lines and answered questions when non-zero - test-weekly-recap.swift: generate PNG of the share card Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat/languages: localize 180+ strings across 10 languages - Add 293-key Localizable.xcstrings with translations for all 10 locales (ar, bn, es, fr, hi, id, pt-BR, ru, zh-Hans) and complete en source values - Localize IslandViewContent, SettingsView: upload status, mail flow, chat placeholder, music player, GitHub sections, n8n detail, auto-close - French tutoiement (ta réponse, appuie, Demande-moi…, Recherche) and Russian ты form throughout - Plural catalog entry for "status.local.connected %lld" (one/other) - Positional args %1$@ %2$@ in status.local.unreachable for reordering - Fix restart to pass app path as $1 argument (no shell injection) - Remove options.knownRegions from project.yml (ignored by xcodegen) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(agents): OpenCode separate tool hooks, README agent table - Remove tool.execute.before/after from EVENT_MAP; add as top-level plugin object properties with correct async signatures - Root README: agent list + config table with Copilot CLI, Muse Code, OpenCode (Mac-only), Amp (Mac-only) - windows/README: Mac-only plugin installer note with workaround path Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(recap): weekKey inside async block, persist() in pruneStale, Debug menu - Record recapLastShownWeek inside asyncAfter after expand(to: .recap) so the week is only marked shown if the card actually appeared - Extract persist() helper in RecapStore; pruneStale calls persist() directly (avoid save→pruneStale recursion) - #if DEBUG menu item "Render recap image" using RecapShareImageView Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
JhoanG956
pushed a commit
to JhoanG956/coucou
that referenced
this pull request
Oct 7, 2026
… server As the Mac does since 0.1.3 (Louis-CFM#156, LocalChat.swift), plus a server of the user's own that speaks the OpenAI API (vLLM, llama.cpp…), with an optional key kept in the credential store (openai-compatible-key). - local_connect checks that a server answers and lists its chat models (embedding and rerank models are left out). An empty address means the usual one on this computer; Ollama's OLLAMA_HOST is honoured. - Addresses are validated and cleaned: http or https only, no user:password@, trailing /v1 and /api dropped, and the loopback names pinned to 127.0.0.1 (on Windows "localhost" can resolve to ::1 first while Ollama listens on IPv4 only). Requests to this computer skip any proxy. - The answer streams: each step goes to the island as a chat-delta event with the text visible so far, at most 15 times a second. <think> blocks stay hidden while open and are dropped from the finished answer; reasoning-only deltas are ignored and an error event ends the turn. - Every read is bounded: model lists and error bodies, one event line (1 MB) and the whole streamed answer (4 MB). - A dropped text file goes along inline, 24 000 characters at most, read without loading more of the file than that; images and PDFs by name only. - Settings: ollamaUrl, lmstudioUrl, customUrl (empty: not connected). Based on Louis-CFM#173 by Justin Minkmar (local_chat.rs), re-applied on main without the branches it was stacked on; ideas from Louis-CFM#262 by bagpotato94 (loopback pinning, no proxy for loopback, OLLAMA_HOST). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
|
Thank you! Local chat landed in Coucou for Windows 0.2.0 (https://github.com/Louis-CFM/coucou/releases/tag/windows-v0.2.0) through the OpenAI-compatible design from #173, which also covers LM Studio and custom servers. Your loopback handling (127.0.0.1, no_proxy, OLLAMA_HOST) was taken into it. Details in #307. Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ollama chat on Windows and Linux
Until now the local-model chat only existed in the macOS app. This adds it to the Tauri app (Windows, Linux).
What changes
windows/src-tauri/src/ollama.rs: model list (/api/tags) and multi-turn chat (/api/chat), no API key needed.<think>blocks from reasoning models are hidden.ollama pull …), timeout.provider,ollamaUrl,ollamaModel, all with defaults, so an existingsettings.jsonstill loads.Windows specifics
localhost,0.0.0.0and::1are pinned to127.0.0.1: Ollama listens on IPv4 only andlocalhostcan resolve to::1first.OLLAMA_HOSTis honoured when the URL field is empty; values without a scheme, with/apior/v1, or with a trailing slash are accepted.Not in this PR
LM Studio, Gemini and OpenAI chat remain macOS only.
Testing
cargo test: 12/12 pass, including new tests for URL normalisation and think-block stripping.npm run packsucceeds on Windows 11.Screenshots