diff --git a/sidecar/scripts/prepare-node-binary.mjs b/sidecar/scripts/prepare-node-binary.mjs index 9c45cbc..a59f935 100644 --- a/sidecar/scripts/prepare-node-binary.mjs +++ b/sidecar/scripts/prepare-node-binary.mjs @@ -109,13 +109,21 @@ function main() { copyFileSync(sysNode, dest); } - // Strip whatever signature came from Node Foundation; Tauri will re-sign - // with our Developer ID at bundle time. + // Strip Node Foundation's signature, then ad-hoc sign so the binary can + // actually execute. Background: on macOS 14.4+ (and 15+ more strictly), + // `amfid` SIGKILLs unsigned arm64 Mach-O binaries the moment they exec. + // The original Node Foundation signature would work for execution but + // doesn't match our final .app's signing chain, so production builds + // need it stripped. Replacing it with an ad-hoc signature (`--sign -`) + // is the only way to have the binary be both executable *now* (for + // `tauri dev`) and clean-slate for tauri-action's later `codesign + // --force` re-sign with the Developer ID cert. try { execSync(`codesign --remove-signature "${dest}"`, { stdio: "ignore" }); } catch { // already unsigned — fine } + execSync(`codesign --sign - --force --timestamp=none "${dest}"`, { stdio: "ignore" }); execSync(`chmod +x "${dest}"`); const size = (statSync(dest).size / 1024 / 1024).toFixed(1); diff --git a/src/renderer/components/SettingsPanel.tsx b/src/renderer/components/SettingsPanel.tsx index 4158374..c6e14e0 100644 --- a/src/renderer/components/SettingsPanel.tsx +++ b/src/renderer/components/SettingsPanel.tsx @@ -1325,142 +1325,8 @@ export function SettingsPanel({ onClose, initialTab }: SettingsPanelProps) { )} - {/* AI Models */} -
-
-

AI Models

-

- Choose which Claude model to use for each feature. Haiku is fastest and - cheapest, Opus is most capable. -

-
-
- {[ - { - key: "analysis" as const, - label: "Email Analysis", - description: "Triaging which emails need replies", - }, - { - key: "drafts" as const, - label: "Draft Generation", - description: "Writing reply drafts", - }, - { - key: "refinement" as const, - label: "Draft Refinement", - description: "Improving drafts based on feedback", - }, - { - key: "calendaring" as const, - label: "Scheduling Detection", - description: "Identifying calendar-related emails", - }, - { - key: "archiveReady" as const, - label: "Archive-Ready Analysis", - description: "Detecting completed conversations", - }, - { - key: "senderLookup" as const, - label: "Sender Lookup", - description: "Web search for sender info", - anthropicOnly: true, - }, - { - key: "agentDrafter" as const, - label: "Agent Drafter", - description: "Background auto-draft generation", - }, - { - key: "agentChat" as const, - label: "Agent Chat", - description: "Interactive agent sidebar conversations", - }, - ].map(({ key, label, description, ...rest }) => { - // Mirror the Agents tab picker shape: full Anthropic - // model list + OpenRouter free models, auto-save on - // change. anthropicOnly features (Sender Lookup uses - // Anthropic web_search; no OpenRouter equivalent) keep - // the Anthropic-only chip and hide the OpenRouter - // optgroup. The sidecar's resolveModelFor() accepts - // both legacy tier names ("haiku") and concrete model - // ids ("claude-haiku-4-5-…", "deepseek/…:free"), so - // either value space round-trips correctly. - const anthropicOnly = - "anthropicOnly" in rest ? rest.anthropicOnly : false; - const isNonClaude = - anthropicOnly && !modelConfig[key].startsWith("claude-"); - return ( -
-
-

- {label} - {anthropicOnly && ( - - Anthropic-only - - )} -

-

- {description} -

- {isNonClaude && ( -

- Configured model is not a Claude model — this feature will fail - until a Claude model is selected. -

- )} -
- -
- ); - })} -
-

- Picking a non-Anthropic model routes that feature through OpenRouter — make - sure an OpenRouter API key is configured in Agent Tools → AI Models, otherwise - the call will surface a clear “OpenRouter API key required” error. - Sender Lookup is the exception: it uses Anthropic’s web_search tool, - which has no OpenRouter equivalent, so the picker only offers Claude models - for that feature. -

-
+ {/* AI Models lives in Agent Tools → AI Models now — single + source of truth, directly under the Anthropic auth section. */} {/* Updates */}
@@ -2292,6 +2158,11 @@ export function SettingsPanel({ onClose, initialTab }: SettingsPanelProps) { description: "Iterating on a draft from your feedback (falls back to Draft Generation)", }, + { + key: "calendaring" as const, + label: "Scheduling Detection", + description: "Identifying calendar-related emails", + }, { key: "summary" as const, label: "Thread Summary", @@ -2308,6 +2179,16 @@ export function SettingsPanel({ onClose, initialTab }: SettingsPanelProps) { description: "Web-search-backed sender profiles", anthropicOnly: true, }, + { + key: "agentDrafter" as const, + label: "Agent Drafter", + description: "Background auto-draft generation", + }, + { + key: "agentChat" as const, + label: "Agent Chat", + description: "Interactive agent sidebar conversations", + }, ] as const ).map(({ key, label, description, ...rest }) => { const anthropicOnly = "anthropicOnly" in rest ? rest.anthropicOnly : false;