Rename app from oAI to Confab
"oAI" reads as easily confused with OpenAI, both visually and in casual conversation. Renamed to "Confab" throughout: Xcode target/scheme/bundle ID (com.oai.Confab), Info.plist and Help Book identity, all user-facing UI text, internal Log subsystem and color identifiers, localization catalogs (6 languages, including a proper reworded/retranslated Intel-deprecation notice), Help Book HTML content, and docs (README/DEVELOPMENT/PRIVACY/SECURITY). Deliberately cosmetic-only: the on-disk data folder (~/Library/Application Support/oAI/), database/backup filenames, Keychain service identifiers, and EncryptionService's key-derivation inputs are all left untouched so existing conversations, settings, and stored API keys survive the update with zero migration and no re-entering credentials. Verified live: a real signed build successfully decrypted a stored API key and loaded an existing conversation database after the bundle ID change. Also includes a small already-completed, previously uncommitted model-release-date feature (ModelInfo/OpenRouterModels/ OpenRouterProvider/ModelInfoView) that happened to share several files with this rename. Gitignored on this branch and updated on disk but not part of this commit: CLAUDE.md, RELEASE_NOTES.md, and the build*.sh scripts.
This commit is contained in:
+7
-7
@@ -1,4 +1,4 @@
|
|||||||
# oAI — Development Guide
|
# Confab — Development Guide
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ oAI/
|
|||||||
│ └── EmailHandlerService.swift # Email AI responder
|
│ └── EmailHandlerService.swift # Email AI responder
|
||||||
│
|
│
|
||||||
└── Resources/
|
└── Resources/
|
||||||
└── oAI.help/ # macOS Help Book
|
└── Confab.help/ # macOS Help Book
|
||||||
```
|
```
|
||||||
|
|
||||||
## Key Technologies
|
## Key Technologies
|
||||||
@@ -76,16 +76,16 @@ oAI/
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clean build
|
# Clean build
|
||||||
xcodebuild clean -scheme oAI
|
xcodebuild clean -scheme Confab
|
||||||
|
|
||||||
# Debug build
|
# Debug build
|
||||||
xcodebuild -scheme oAI -configuration Debug
|
xcodebuild -scheme Confab -configuration Debug
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
xcodebuild test -scheme oAI
|
xcodebuild test -scheme Confab
|
||||||
```
|
```
|
||||||
|
|
||||||
**Output:** `~/Library/Developer/Xcode/DerivedData/oAI-*/Build/Products/Debug/oAI.app`
|
**Output:** `~/Library/Developer/Xcode/DerivedData/oAI-*/Build/Products/Debug/Confab.app`
|
||||||
|
|
||||||
In Xcode: `⌘B` build, `⌘R` run, `⌘⇧K` clean, `⌘.` stop.
|
In Xcode: `⌘B` build, `⌘R` run, `⌘⇧K` clean, `⌘.` stop.
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ XProtect 5331 flags Debug builds (bash + IMAP + file access = RAT signature matc
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
~/Library/Logs/oAI.log
|
~/Library/Logs/Confab.log
|
||||||
```
|
```
|
||||||
|
|
||||||
## Performance Notes
|
## Performance Notes
|
||||||
|
|||||||
+15
-15
@@ -2,38 +2,38 @@
|
|||||||
|
|
||||||
**Last updated:** 2026-07-27
|
**Last updated:** 2026-07-27
|
||||||
|
|
||||||
oAI is a native macOS app. This document describes what data it handles, where it goes, and what control you have over it.
|
Confab is a native macOS app. This document describes what data it handles, where it goes, and what control you have over it.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
- oAI does not collect analytics, telemetry, crash reports, or usage data of any kind. There is no tracking SDK in the app, and the developer has no visibility into how you use it.
|
- Confab does not collect analytics, telemetry, crash reports, or usage data of any kind. There is no tracking SDK in the app, and the developer has no visibility into how you use it.
|
||||||
- Everything oAI stores — conversations, settings, command history — stays in a local SQLite database on your Mac, unless you explicitly enable a sync or backup feature.
|
- Everything Confab stores — conversations, settings, command history — stays in a local SQLite database on your Mac, unless you explicitly enable a sync or backup feature.
|
||||||
- The only data that leaves your Mac is data you choose to send: messages sent to the AI provider/model you've selected, and, for optional integrations you turn on yourself (email, Anytype, Paperless-NGX, external MCP servers), whatever those specific features are configured to talk to.
|
- The only data that leaves your Mac is data you choose to send: messages sent to the AI provider/model you've selected, and, for optional integrations you turn on yourself (email, Anytype, Paperless-NGX, external MCP servers), whatever those specific features are configured to talk to.
|
||||||
- oAI is free and open source. You can read exactly what it does at **https://gitlab.pm/rune/oai-swift**.
|
- Confab is free and open source. You can read exactly what it does at **https://gitlab.pm/rune/oai-swift**.
|
||||||
|
|
||||||
## Data stored locally
|
## Data stored locally
|
||||||
|
|
||||||
oAI keeps its data in a SQLite database at `~/Library/Application Support/oAI/oai_conversations.db`:
|
Confab keeps its data in a SQLite database at `~/Library/Application Support/oAI/oai_conversations.db`:
|
||||||
- Saved conversations and messages
|
- Saved conversations and messages
|
||||||
- App settings and feature toggles
|
- App settings and feature toggles
|
||||||
- Command history (last 5,000 entries, auto-pruned)
|
- Command history (last 5,000 entries, auto-pruned)
|
||||||
- Email processing logs, if the email assistant feature is used
|
- Email processing logs, if the email assistant feature is used
|
||||||
|
|
||||||
Log files (no message content, no credentials) are written to `~/Library/Logs/oAI.log` for troubleshooting.
|
Log files (no message content, no credentials) are written to `~/Library/Logs/Confab.log` for troubleshooting.
|
||||||
|
|
||||||
None of this is sent anywhere by oAI itself. Deleting the database file (or uninstalling the app) removes it.
|
None of this is sent anywhere by Confab itself. Deleting the database file (or uninstalling the app) removes it.
|
||||||
|
|
||||||
## API keys and credentials
|
## API keys and credentials
|
||||||
|
|
||||||
- Provider API keys (OpenRouter, Anthropic, OpenAI, Google) are stored in the macOS **Keychain**, not the database, and not in plaintext anywhere on disk.
|
- Provider API keys (OpenRouter, Anthropic, OpenAI, Google) are stored in the macOS **Keychain**, not the database, and not in plaintext anywhere on disk.
|
||||||
- A small number of other credentials that can't use Keychain directly (e.g. email account password, if you set up the email assistant) are stored **encrypted at rest** in the local database, using a key derived from your Mac's hardware identifier — this key never leaves your device and isn't transmitted anywhere.
|
- A small number of other credentials that can't use Keychain directly (e.g. email account password, if you set up the email assistant) are stored **encrypted at rest** in the local database, using a key derived from your Mac's hardware identifier — this key never leaves your device and isn't transmitted anywhere.
|
||||||
- oAI never transmits your API keys or credentials to anyone other than the service they belong to (e.g. your OpenRouter key is only ever sent to OpenRouter's API).
|
- Confab never transmits your API keys or credentials to anyone other than the service they belong to (e.g. your OpenRouter key is only ever sent to OpenRouter's API).
|
||||||
|
|
||||||
## AI providers — where your messages actually go
|
## AI providers — where your messages actually go
|
||||||
|
|
||||||
oAI is a client for AI providers you choose and configure yourself: OpenRouter, Anthropic, OpenAI, Google, Ollama (self-hosted, stays local), and Apple's on-device Foundation Models (macOS 26+, never leaves your Mac). When you send a message, its content — plus whatever conversation history and system prompt context oAI includes — is sent to whichever provider and model you have selected for that conversation.
|
Confab is a client for AI providers you choose and configure yourself: OpenRouter, Anthropic, OpenAI, Google, Ollama (self-hosted, stays local), and Apple's on-device Foundation Models (macOS 26+, never leaves your Mac). When you send a message, its content — plus whatever conversation history and system prompt context Confab includes — is sent to whichever provider and model you have selected for that conversation.
|
||||||
|
|
||||||
Each provider handles that data under its own privacy policy, over which oAI has no control:
|
Each provider handles that data under its own privacy policy, over which Confab has no control:
|
||||||
- OpenRouter: https://openrouter.ai/privacy
|
- OpenRouter: https://openrouter.ai/privacy
|
||||||
- Anthropic: https://www.anthropic.com/privacy
|
- Anthropic: https://www.anthropic.com/privacy
|
||||||
- OpenAI: https://openai.com/privacy
|
- OpenAI: https://openai.com/privacy
|
||||||
@@ -50,14 +50,14 @@ The following are **off by default** and require you to explicitly enable them i
|
|||||||
- **Bash command execution** — lets the AI run shell commands on your Mac. Off by default; when on, can optionally require your approval before each command runs.
|
- **Bash command execution** — lets the AI run shell commands on your Mac. Off by default; when on, can optionally require your approval before each command runs.
|
||||||
- **MCP file access** — lets the AI read/write files in folders you explicitly allow. Includes PDF text extraction. Folder access is scoped to what you approve, nothing outside it.
|
- **MCP file access** — lets the AI read/write files in folders you explicitly allow. Includes PDF text extraction. Folder access is scoped to what you approve, nothing outside it.
|
||||||
- **Email assistant (IMAP/SMTP)** — polls a mailbox you configure and can send AI-generated replies. Your mail server credentials and the email content it processes are stored locally as described above; email content is sent to your selected AI provider to generate a response.
|
- **Email assistant (IMAP/SMTP)** — polls a mailbox you configure and can send AI-generated replies. Your mail server credentials and the email content it processes are stored locally as described above; email content is sent to your selected AI provider to generate a response.
|
||||||
- **Anytype / Paperless-NGX integrations** — connect to instances you run yourself (typically on your own network or self-hosted server). Data flows directly between oAI and your own instance.
|
- **Anytype / Paperless-NGX integrations** — connect to instances you run yourself (typically on your own network or self-hosted server). Data flows directly between Confab and your own instance.
|
||||||
- **External MCP servers** — you can connect any third-party MCP server of your choosing; oAI has no visibility into or control over what that server does with data passed to it.
|
- **External MCP servers** — you can connect any third-party MCP server of your choosing; Confab has no visibility into or control over what that server does with data passed to it.
|
||||||
- **Semantic search / embeddings** — if enabled, message text is sent to your selected embedding provider (OpenAI, OpenRouter, or Google) to generate vector embeddings, which are then stored locally.
|
- **Semantic search / embeddings** — if enabled, message text is sent to your selected embedding provider (OpenAI, OpenRouter, or Google) to generate vector embeddings, which are then stored locally.
|
||||||
- **Web search** — when online mode is enabled, your query may be sent to DuckDuckGo, Google Search, or included as `:online` context to OpenRouter, depending on configuration.
|
- **Web search** — when online mode is enabled, your query may be sent to DuckDuckGo, Google Search, or included as `:online` context to OpenRouter, depending on configuration.
|
||||||
|
|
||||||
## Crash reports
|
## Crash reports
|
||||||
|
|
||||||
oAI does not include any crash reporting or analytics SDK, and does not automatically collect or transmit crash data. If oAI crashes, macOS writes a local crash log to your own Mac (viewable in Console.app), but it is not sent to the developer automatically — Apple's automatic crash-sharing pipeline for Developer ID–distributed apps like oAI (i.e. not sold through the Mac App Store) does not route reports back to the developer. If you'd like to help fix a crash, you're welcome to attach that log when reporting an issue — see `SECURITY.md` / the contact link below for how.
|
Confab does not include any crash reporting or analytics SDK, and does not automatically collect or transmit crash data. If Confab crashes, macOS writes a local crash log to your own Mac (viewable in Console.app), but it is not sent to the developer automatically — Apple's automatic crash-sharing pipeline for Developer ID–distributed apps like Confab (i.e. not sold through the Mac App Store) does not route reports back to the developer. If you'd like to help fix a crash, you're welcome to attach that log when reporting an issue — see `SECURITY.md` / the contact link below for how.
|
||||||
|
|
||||||
## iCloud backup
|
## iCloud backup
|
||||||
|
|
||||||
@@ -73,11 +73,11 @@ Since everything is local, you're always in full control:
|
|||||||
|
|
||||||
## Children's privacy
|
## Children's privacy
|
||||||
|
|
||||||
oAI is not directed at children and does not knowingly collect data from children.
|
Confab is not directed at children and does not knowingly collect data from children.
|
||||||
|
|
||||||
## Changes to this policy
|
## Changes to this policy
|
||||||
|
|
||||||
If oAI's data handling changes in a meaningful way, this document will be updated and the date at the top revised. Given the app's local-first design, we don't expect that to happen often.
|
If Confab's data handling changes in a meaningful way, this document will be updated and the date at the top revised. Given the app's local-first design, we don't expect that to happen often.
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# oAI
|
# Confab
|
||||||
|
|
||||||
A powerful native macOS AI chat application with support for multiple providers (including on-device Apple Intelligence), MCP-powered tool access, advanced memory management, and seamless Git synchronization.
|
A powerful native macOS AI chat application with support for multiple providers (including on-device Apple Intelligence), MCP-powered tool access, advanced memory management, and seamless Git synchronization.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ A powerful native macOS AI chat application with support for multiple providers
|
|||||||
### 💬 Core Chat Capabilities
|
### 💬 Core Chat Capabilities
|
||||||
- **Streaming Responses** - Real-time token streaming for faster interactions
|
- **Streaming Responses** - Real-time token streaming for faster interactions
|
||||||
- **Conversation Management** - Save, load, export, and search conversations, organized into folders
|
- **Conversation Management** - Save, load, export, and search conversations, organized into folders
|
||||||
- **Unsaved Changes & Crash Recovery** - Standard Mac-style save prompt on New Chat/Clear/Load/Quit with unsaved messages; the in-progress conversation (and selected model) is also mirrored to disk periodically and offered back on next launch if oAI crashes or is force-quit
|
- **Unsaved Changes & Crash Recovery** - Standard Mac-style save prompt on New Chat/Clear/Load/Quit with unsaved messages; the in-progress conversation (and selected model) is also mirrored to disk periodically and offered back on next launch if Confab crashes or is force-quit
|
||||||
- **Combine Conversations** - Merge 2+ saved conversations, either by chronological concatenation or AI-assisted synthesis
|
- **Combine Conversations** - Merge 2+ saved conversations, either by chronological concatenation or AI-assisted synthesis
|
||||||
- **File Attachments** - Support for text files, images, and PDFs
|
- **File Attachments** - Support for text files, images, and PDFs
|
||||||
- **Image Generation** - Create images with supported models (DALL-E, Flux, etc.) - renders inline in chat
|
- **Image Generation** - Create images with supported models (DALL-E, Flux, etc.) - renders inline in chat
|
||||||
@@ -75,7 +75,7 @@ Seamless conversation backup and sync across devices:
|
|||||||

|

|
||||||
|
|
||||||
### 📚 Anytype Integration
|
### 📚 Anytype Integration
|
||||||
Connect oAI to your local [Anytype](https://anytype.io) knowledge base:
|
Connect Confab to your local [Anytype](https://anytype.io) knowledge base:
|
||||||
- **Search** - find objects by keyword across all spaces or within a specific one
|
- **Search** - find objects by keyword across all spaces or within a specific one
|
||||||
- **Read** - open any object and read its full markdown content
|
- **Read** - open any object and read its full markdown content
|
||||||
- **Append** - add content to the end of an existing object without touching existing text or internal links (preferred over full update)
|
- **Append** - add content to the end of an existing object without touching existing text or internal links (preferred over full update)
|
||||||
@@ -84,7 +84,7 @@ Connect oAI to your local [Anytype](https://anytype.io) knowledge base:
|
|||||||
- All data stays on your machine (local API, no cloud)
|
- All data stays on your machine (local API, no cloud)
|
||||||
|
|
||||||
### 🛰️ Jarvis Integration
|
### 🛰️ Jarvis Integration
|
||||||
Connect oAI to a self-hosted [Jarvis](https://jarvis.pm) agent-automation server:
|
Connect Confab to a self-hosted [Jarvis](https://jarvis.pm) agent-automation server:
|
||||||
- **Agent Management** - List, create, edit, enable/disable, run, and stop agents
|
- **Agent Management** - List, create, edit, enable/disable, run, and stop agents
|
||||||
- **Run History** - Expandable per-run output with status and timing
|
- **Run History** - Expandable per-run output with status and timing
|
||||||
- **Usage & Credits** - Per-agent usage stats and credits balance
|
- **Usage & Credits** - Per-agent usage stats and credits balance
|
||||||
@@ -129,17 +129,17 @@ Automated email responses powered by AI:
|
|||||||
|
|
||||||
Download the latest release from the [Releases page](https://gitlab.pm/rune/oai-swift/releases). Two builds are available:
|
Download the latest release from the [Releases page](https://gitlab.pm/rune/oai-swift/releases). Two builds are available:
|
||||||
|
|
||||||
- **oAI-x.x.x-AppleSilicon.dmg** - for Macs with an Apple Silicon chip (M1 and later)
|
- **Confab-x.x.x-AppleSilicon.dmg** - for Macs with an Apple Silicon chip (M1 and later)
|
||||||
- **oAI-x.x.x-Universal.dmg** - runs natively on both Apple Silicon and Intel Macs
|
- **Confab-x.x.x-Universal.dmg** - runs natively on both Apple Silicon and Intel Macs
|
||||||
|
|
||||||
### Installing from DMG
|
### Installing from DMG
|
||||||
|
|
||||||
1. Open the downloaded `.dmg` file
|
1. Open the downloaded `.dmg` file
|
||||||
2. Drag **oAI.app** into the **Applications** folder
|
2. Drag **Confab.app** into the **Applications** folder
|
||||||
3. Eject the DMG
|
3. Eject the DMG
|
||||||
4. Launch oAI from Applications or Spotlight
|
4. Launch Confab from Applications or Spotlight
|
||||||
|
|
||||||
Release DMGs are signed and notarized by Apple, so oAI opens normally on first launch with no Gatekeeper warning.
|
Release DMGs are signed and notarized by Apple, so Confab opens normally on first launch with no Gatekeeper warning.
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
- macOS 26.2 or later
|
- macOS 26.2 or later
|
||||||
@@ -329,16 +329,16 @@ AI-powered email auto-responder:
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
oAI is source-available under the **PolyForm Noncommercial License 1.0.0**.
|
Confab is source-available under the **PolyForm Noncommercial License 1.0.0**.
|
||||||
|
|
||||||
This means you are free to use, study, modify, and share oAI for any noncommercial purpose. Commercial use — including selling oAI or any part of it, standalone or bundled into another product or service — requires a separate commercial license.
|
This means you are free to use, study, modify, and share Confab for any noncommercial purpose. Commercial use — including selling Confab or any part of it, standalone or bundled into another product or service — requires a separate commercial license.
|
||||||
|
|
||||||
See [LICENSE](LICENSE) for the full license text, or visit [polyformproject.org/licenses/noncommercial/1.0.0](https://polyformproject.org/licenses/noncommercial/1.0.0). For commercial licensing inquiries, contact Rune Olsen via [oai.pm](https://oai.pm).
|
See [LICENSE](LICENSE) for the full license text, or visit [polyformproject.org/licenses/noncommercial/1.0.0](https://polyformproject.org/licenses/noncommercial/1.0.0). For commercial licensing inquiries, contact Rune Olsen via [oai.pm](https://oai.pm).
|
||||||
|
|
||||||
|
|
||||||
## Privacy & Security
|
## Privacy & Security
|
||||||
|
|
||||||
- [Privacy Policy](PRIVACY.md) - what oAI stores, what it sends to AI providers, and what stays local
|
- [Privacy Policy](PRIVACY.md) - what Confab stores, what it sends to AI providers, and what stays local
|
||||||
- [Security Policy](SECURITY.md) - supported versions and how to report a vulnerability
|
- [Security Policy](SECURITY.md) - supported versions and how to report a vulnerability
|
||||||
|
|
||||||
|
|
||||||
@@ -355,7 +355,7 @@ See [LICENSE](LICENSE) for the full license text, or visit [polyformproject.org/
|
|||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|
||||||
oAI can take real actions on your behalf when you enable optional features - it can run shell commands, read/write files, send emails, and create calendar events or reminders. Write actions are gated behind explicit opt-in settings and, for bash/calendar/reminders, an on-screen approval prompt before they run. Review your permission settings carefully before use. Content you send is processed by whichever AI provider and model you have selected - see [PRIVACY.md](PRIVACY.md) for details on what goes where. oAI is provided "as is" without warranty of any kind - the author accepts no responsibility for actions taken by the agent or any consequences thereof. See [LICENSE](LICENSE) for full terms.
|
Confab can take real actions on your behalf when you enable optional features - it can run shell commands, read/write files, send emails, and create calendar events or reminders. Write actions are gated behind explicit opt-in settings and, for bash/calendar/reminders, an on-screen approval prompt before they run. Review your permission settings carefully before use. Content you send is processed by whichever AI provider and model you have selected - see [PRIVACY.md](PRIVACY.md) for details on what goes where. Confab is provided "as is" without warranty of any kind - the author accepts no responsibility for actions taken by the agent or any consequences thereof. See [LICENSE](LICENSE) for full terms.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -2,23 +2,23 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Only the latest publicly released version of oAI is supported with security fixes. Please update to the latest version before reporting an issue, and confirm it still reproduces there.
|
Only the latest publicly released version of Confab is supported with security fixes. Please update to the latest version before reporting an issue, and confirm it still reproduces there.
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
If you discover a security vulnerability in oAI, please report it privately rather than opening a public GitHub issue.
|
If you discover a security vulnerability in Confab, please report it privately rather than opening a public GitHub issue.
|
||||||
|
|
||||||
To report a security concern, use the contact form at **[https://oai.pm/#contact](https://oai.pm/#contact)**.
|
To report a security concern, use the contact form at **[https://oai.pm/#contact](https://oai.pm/#contact)**.
|
||||||
|
|
||||||
Please include as much detail as possible:
|
Please include as much detail as possible:
|
||||||
- A description of the vulnerability and its potential impact
|
- A description of the vulnerability and its potential impact
|
||||||
- Steps to reproduce the issue
|
- Steps to reproduce the issue
|
||||||
- The oAI version and macOS version you're using
|
- The Confab version and macOS version you're using
|
||||||
- Any relevant logs (`~/Library/Logs/oAI.log`), with sensitive data redacted
|
- Any relevant logs (`~/Library/Logs/Confab.log`), with sensitive data redacted
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
oAI is a native macOS app that stores conversations, settings, and API keys locally (SQLite database and Keychain). Areas of particular interest for security reports include:
|
Confab is a native macOS app that stores conversations, settings, and API keys locally (SQLite database and Keychain). Areas of particular interest for security reports include:
|
||||||
- API key handling and Keychain storage
|
- API key handling and Keychain storage
|
||||||
- MCP file access permission checks
|
- MCP file access permission checks
|
||||||
- Bash execution approval flow
|
- Bash execution approval flow
|
||||||
|
|||||||
@@ -22,17 +22,17 @@
|
|||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
A550A6622F3B72EA00136F2B /* oAI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = oAI.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
A550A6622F3B72EA00136F2B /* Confab.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Confab.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
A586FF5130122589002CFF95 /* oAITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = oAITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
A586FF5130122589002CFF95 /* ConfabTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ConfabTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
911C4D0E69E11B84C61453DC /* Exceptions for "oAI" folder in "oAI" target */ = {
|
911C4D0E69E11B84C61453DC /* Exceptions for "oAI" folder in "Confab" target */ = {
|
||||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
membershipExceptions = (
|
membershipExceptions = (
|
||||||
Info.plist,
|
Info.plist,
|
||||||
);
|
);
|
||||||
target = A550A6612F3B72EA00136F2B /* oAI */;
|
target = A550A6612F3B72EA00136F2B /* Confab */;
|
||||||
};
|
};
|
||||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
A550A6642F3B72EA00136F2B /* oAI */ = {
|
A550A6642F3B72EA00136F2B /* oAI */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
exceptions = (
|
exceptions = (
|
||||||
911C4D0E69E11B84C61453DC /* Exceptions for "oAI" folder in "oAI" target */,
|
911C4D0E69E11B84C61453DC /* Exceptions for "oAI" folder in "Confab" target */,
|
||||||
);
|
);
|
||||||
path = oAI;
|
path = oAI;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -84,8 +84,8 @@
|
|||||||
A550A6632F3B72EA00136F2B /* Products */ = {
|
A550A6632F3B72EA00136F2B /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A550A6622F3B72EA00136F2B /* oAI.app */,
|
A550A6622F3B72EA00136F2B /* Confab.app */,
|
||||||
A586FF5130122589002CFF95 /* oAITests.xctest */,
|
A586FF5130122589002CFF95 /* ConfabTests.xctest */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -93,9 +93,9 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
A550A6612F3B72EA00136F2B /* oAI */ = {
|
A550A6612F3B72EA00136F2B /* Confab */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = A550A66D2F3B72EC00136F2B /* Build configuration list for PBXNativeTarget "oAI" */;
|
buildConfigurationList = A550A66D2F3B72EC00136F2B /* Build configuration list for PBXNativeTarget "Confab" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
A550A65E2F3B72EA00136F2B /* Sources */,
|
A550A65E2F3B72EA00136F2B /* Sources */,
|
||||||
A550A65F2F3B72EA00136F2B /* Frameworks */,
|
A550A65F2F3B72EA00136F2B /* Frameworks */,
|
||||||
@@ -108,18 +108,18 @@
|
|||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
A550A6642F3B72EA00136F2B /* oAI */,
|
A550A6642F3B72EA00136F2B /* oAI */,
|
||||||
);
|
);
|
||||||
name = oAI;
|
name = Confab;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
A550A6812F3B730000136F2B /* GRDB */,
|
A550A6812F3B730000136F2B /* GRDB */,
|
||||||
A52B47512F3E45BA004200E2 /* MarkdownUI */,
|
A52B47512F3E45BA004200E2 /* MarkdownUI */,
|
||||||
);
|
);
|
||||||
productName = oAI;
|
productName = Confab;
|
||||||
productReference = A550A6622F3B72EA00136F2B /* oAI.app */;
|
productReference = A550A6622F3B72EA00136F2B /* Confab.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
A586FF5030122589002CFF95 /* oAITests */ = {
|
A586FF5030122589002CFF95 /* ConfabTests */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = A586FF5930122589002CFF95 /* Build configuration list for PBXNativeTarget "oAITests" */;
|
buildConfigurationList = A586FF5930122589002CFF95 /* Build configuration list for PBXNativeTarget "ConfabTests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
A586FF4D30122589002CFF95 /* Sources */,
|
A586FF4D30122589002CFF95 /* Sources */,
|
||||||
A586FF4E30122589002CFF95 /* Frameworks */,
|
A586FF4E30122589002CFF95 /* Frameworks */,
|
||||||
@@ -133,11 +133,11 @@
|
|||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
A586FF5230122589002CFF95 /* oAITests */,
|
A586FF5230122589002CFF95 /* oAITests */,
|
||||||
);
|
);
|
||||||
name = oAITests;
|
name = ConfabTests;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
);
|
);
|
||||||
productName = oAITests;
|
productName = ConfabTests;
|
||||||
productReference = A586FF5130122589002CFF95 /* oAITests.xctest */;
|
productReference = A586FF5130122589002CFF95 /* ConfabTests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.unit-test";
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
};
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
@@ -182,8 +182,8 @@
|
|||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
A550A6612F3B72EA00136F2B /* oAI */,
|
A550A6612F3B72EA00136F2B /* Confab */,
|
||||||
A586FF5030122589002CFF95 /* oAITests */,
|
A586FF5030122589002CFF95 /* ConfabTests */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -225,7 +225,7 @@
|
|||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
A586FF5630122589002CFF95 /* PBXTargetDependency */ = {
|
A586FF5630122589002CFF95 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = A550A6612F3B72EA00136F2B /* oAI */;
|
target = A550A6612F3B72EA00136F2B /* Confab */;
|
||||||
targetProxy = A586FF5530122589002CFF95 /* PBXContainerItemProxy */;
|
targetProxy = A586FF5530122589002CFF95 /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
@@ -358,7 +358,8 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = oAI/oAI.entitlements;
|
CODE_SIGN_ENTITLEMENTS = oAI/Confab.entitlements;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
@@ -367,11 +368,12 @@
|
|||||||
ENABLE_USER_SELECTED_FILES = readonly;
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = oAI/Info.plist;
|
INFOPLIST_FILE = oAI/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Confab;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription = "oAI can read and create calendar events when you ask it to, if you enable Calendar access in Settings.";
|
INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription = "Confab can read and create calendar events when you ask it to, if you enable Calendar access in Settings.";
|
||||||
INFOPLIST_KEY_NSContactsUsageDescription = "oAI can search your contacts when you ask it to, if you enable Contacts access in Settings.";
|
INFOPLIST_KEY_NSContactsUsageDescription = "Confab can search your contacts when you ask it to, if you enable Contacts access in Settings.";
|
||||||
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "oAI can use your current location to answer questions, if you enable Location & Maps access in Settings.";
|
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Confab can use your current location to answer questions, if you enable Location & Maps access in Settings.";
|
||||||
INFOPLIST_KEY_NSRemindersFullAccessUsageDescription = "oAI can read and create reminders when you ask it to, if you enable Reminders access in Settings.";
|
INFOPLIST_KEY_NSRemindersFullAccessUsageDescription = "Confab can read and create reminders when you ask it to, if you enable Reminders access in Settings.";
|
||||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
||||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
|
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
|
||||||
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
|
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
|
||||||
@@ -387,7 +389,7 @@
|
|||||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 26.2;
|
MACOSX_DEPLOYMENT_TARGET = 26.2;
|
||||||
MARKETING_VERSION = 2.4.4;
|
MARKETING_VERSION = 2.4.4;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.oai.oAI;
|
PRODUCT_BUNDLE_IDENTIFIER = com.oai.Confab;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
@@ -408,7 +410,8 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = oAI/oAI.entitlements;
|
CODE_SIGN_ENTITLEMENTS = oAI/Confab.entitlements;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
@@ -417,11 +420,12 @@
|
|||||||
ENABLE_USER_SELECTED_FILES = readonly;
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = oAI/Info.plist;
|
INFOPLIST_FILE = oAI/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Confab;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription = "oAI can read and create calendar events when you ask it to, if you enable Calendar access in Settings.";
|
INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription = "Confab can read and create calendar events when you ask it to, if you enable Calendar access in Settings.";
|
||||||
INFOPLIST_KEY_NSContactsUsageDescription = "oAI can search your contacts when you ask it to, if you enable Contacts access in Settings.";
|
INFOPLIST_KEY_NSContactsUsageDescription = "Confab can search your contacts when you ask it to, if you enable Contacts access in Settings.";
|
||||||
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "oAI can use your current location to answer questions, if you enable Location & Maps access in Settings.";
|
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Confab can use your current location to answer questions, if you enable Location & Maps access in Settings.";
|
||||||
INFOPLIST_KEY_NSRemindersFullAccessUsageDescription = "oAI can read and create reminders when you ask it to, if you enable Reminders access in Settings.";
|
INFOPLIST_KEY_NSRemindersFullAccessUsageDescription = "Confab can read and create reminders when you ask it to, if you enable Reminders access in Settings.";
|
||||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
||||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
|
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
|
||||||
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
|
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
|
||||||
@@ -437,7 +441,7 @@
|
|||||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 26.2;
|
MACOSX_DEPLOYMENT_TARGET = 26.2;
|
||||||
MARKETING_VERSION = 2.4.4;
|
MARKETING_VERSION = 2.4.4;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.oai.oAI;
|
PRODUCT_BUNDLE_IDENTIFIER = com.oai.Confab;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
@@ -463,7 +467,7 @@
|
|||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 27.0;
|
MACOSX_DEPLOYMENT_TARGET = 27.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.oai.oAITests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.oai.ConfabTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -471,7 +475,7 @@
|
|||||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/oAI.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/oAI";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Confab.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Confab";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -485,7 +489,7 @@
|
|||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 27.0;
|
MACOSX_DEPLOYMENT_TARGET = 27.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.oai.oAITests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.oai.ConfabTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -493,7 +497,7 @@
|
|||||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/oAI.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/oAI";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Confab.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Confab";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
@@ -509,7 +513,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
A550A66D2F3B72EC00136F2B /* Build configuration list for PBXNativeTarget "oAI" */ = {
|
A550A66D2F3B72EC00136F2B /* Build configuration list for PBXNativeTarget "Confab" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
A550A66E2F3B72EC00136F2B /* Debug */,
|
A550A66E2F3B72EC00136F2B /* Debug */,
|
||||||
@@ -518,7 +522,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
A586FF5930122589002CFF95 /* Build configuration list for PBXNativeTarget "oAITests" */ = {
|
A586FF5930122589002CFF95 /* Build configuration list for PBXNativeTarget "ConfabTests" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
A586FF5730122589002CFF95 /* Debug */,
|
A586FF5730122589002CFF95 /* Debug */,
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<false/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.server</key>
|
||||||
|
<false/>
|
||||||
|
<key>com.apple.security.personal-information.calendars</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.personal-information.reminders</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.personal-information.addressbook</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.personal-information.location</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
+8
-8
@@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleHelpBookFolder</key>
|
<key>CFBundleHelpBookFolder</key>
|
||||||
<string>oAI.help</string>
|
<string>Confab.help</string>
|
||||||
<key>CFBundleHelpBookName</key>
|
<key>CFBundleHelpBookName</key>
|
||||||
<string>oAI Help</string>
|
<string>Confab Help</string>
|
||||||
<key>CFBundleLocalizations</key>
|
<key>CFBundleLocalizations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>en</string>
|
<string>en</string>
|
||||||
@@ -14,5 +14,5 @@
|
|||||||
<string>de</string>
|
<string>de</string>
|
||||||
<string>sv</string>
|
<string>sv</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
+45
-45
@@ -523,36 +523,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"• No credentials needed in oAI" : {
|
"• No credentials needed in Confab" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "• Ingen legitimationsoplysninger nødvendige i oAI"
|
"value" : "• Ingen legitimationsoplysninger nødvendige i Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "• Keine Zugangsdaten in oAI erforderlich"
|
"value" : "• Keine Zugangsdaten in Confab erforderlich"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "• Aucun identifiant requis dans oAI"
|
"value" : "• Aucun identifiant requis dans Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nb" : {
|
"nb" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "• Ingen legitimasjon nødvendig i oAI"
|
"value" : "• Ingen legitimasjon nødvendig i Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sv" : {
|
"sv" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "• Inga inloggningsuppgifter behövs i oAI"
|
"value" : "• Inga inloggningsuppgifter behövs i Confab"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1878,36 +1878,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"About oAI" : {
|
"About Confab" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Om oAI"
|
"value" : "Om Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Über oAI"
|
"value" : "Über Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "À propos d'oAI"
|
"value" : "À propos de Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nb" : {
|
"nb" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Om oAI"
|
"value" : "Om Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sv" : {
|
"sv" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Om oAI"
|
"value" : "Om Confab"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4666,36 +4666,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Controls which messages are written to ~/Library/Logs/oAI.log" : {
|
"Controls which messages are written to ~/Library/Logs/Confab.log" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Styrer hvilke beskeder der skrives til ~/Library/Logs/oAI.log"
|
"value" : "Styrer hvilke beskeder der skrives til ~/Library/Logs/Confab.log"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Steuert, welche Nachrichten in ~/Library/Logs/oAI.log geschrieben werden"
|
"value" : "Steuert, welche Nachrichten in ~/Library/Logs/Confab.log geschrieben werden"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Contrôle quels messages sont écrits dans ~/Library/Logs/oAI.log"
|
"value" : "Contrôle quels messages sont écrits dans ~/Library/Logs/Confab.log"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nb" : {
|
"nb" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Styrer hvilke meldinger som skrives til ~/Library/Logs/oAI.log"
|
"value" : "Styrer hvilke meldinger som skrives til ~/Library/Logs/Confab.log"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sv" : {
|
"sv" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Styr vilka meddelanden som skrivs till ~/Library/Logs/oAI.log"
|
"value" : "Styr vilka meddelanden som skrivs till ~/Library/Logs/Confab.log"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6795,36 +6795,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Example: oai-bot-x7k2m9p3@gmail.com" : {
|
"Example: confab-bot-x7k2m9p3@gmail.com" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Example: oai-bot-x7k2m9p3@gmail.com"
|
"value" : "Example: confab-bot-x7k2m9p3@gmail.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Example: oai-bot-x7k2m9p3@gmail.com"
|
"value" : "Example: confab-bot-x7k2m9p3@gmail.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Exemple : oai-bot-x7k2m9p3@gmail.com"
|
"value" : "Exemple : confab-bot-x7k2m9p3@gmail.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nb" : {
|
"nb" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Example: oai-bot-x7k2m9p3@gmail.com"
|
"value" : "Example: confab-bot-x7k2m9p3@gmail.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sv" : {
|
"sv" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Example: oai-bot-x7k2m9p3@gmail.com"
|
"value" : "Example: confab-bot-x7k2m9p3@gmail.com"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9805,7 +9805,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Multi-provider AI chat client" : {
|
"Multi-provider AI chat client" : {
|
||||||
"comment" : "A description of oAI.",
|
"comment" : "A description of Confab.",
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
@@ -10576,108 +10576,108 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"oAI" : {
|
"Confab" : {
|
||||||
"comment" : "The name of the app.",
|
"comment" : "The name of the app.",
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nb" : {
|
"nb" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sv" : {
|
"sv" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"oAI Help" : {
|
"Confab Help" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI-hjælp"
|
"value" : "Confab-hjælp"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI-Hilfe"
|
"value" : "Confab-Hilfe"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "Aide oAI"
|
"value" : "Aide Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nb" : {
|
"nb" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI-hjelp"
|
"value" : "Confab-hjelp"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sv" : {
|
"sv" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI-hjälp"
|
"value" : "Confab-hjälp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"oAI v2.4 is the last version to support Intel Macs and Rosetta. Starting with macOS 28, oAI will require Apple Silicon. Consider upgrading your Mac to continue receiving updates." : {
|
"Confab (formerly oAI) v2.4 was the last version to support Intel Macs and Rosetta. Starting with macOS 28, Confab will require Apple Silicon. Consider upgrading your Mac to continue receiving updates." : {
|
||||||
"comment" : "A warning that Intel Macs are no longer supported.",
|
"comment" : "A warning that Intel Macs are no longer supported.",
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI v2.4 er den sidste version, der understøtter Intel-Mac og Rosetta. Fra macOS 28 vil oAI kræve Apple Silicon. Overvej at opgradere din Mac for at fortsætte med at få opdateringer."
|
"value" : "Confab (tidligere oAI) v2.4 var den sidste version, der understøttede Intel-Mac og Rosetta. Fra macOS 28 vil Confab kræve Apple Silicon. Overvej at opgradere din Mac for at fortsætte med at få opdateringer."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI v2.4 ist die letzte Version, die Intel-Macs und Rosetta unterstützt. Ab macOS 28 benötigt oAI Apple Silicon. Erwäge ein Upgrade deines Mac, um weiterhin Updates zu erhalten."
|
"value" : "Confab (früher oAI) v2.4 war die letzte Version, die Intel-Macs und Rosetta unterstützte. Ab macOS 28 benötigt Confab Apple Silicon. Erwäge ein Upgrade deines Mac, um weiterhin Updates zu erhalten."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI v2.4 est la dernière version à prendre en charge les Mac Intel et Rosetta. À partir de macOS 28, oAI nécessitera Apple Silicon. Envisage de mettre à niveau ton Mac pour continuer à recevoir des mises à jour."
|
"value" : "Confab (anciennement oAI) v2.4 était la dernière version à prendre en charge les Mac Intel et Rosetta. À partir de macOS 28, Confab nécessitera Apple Silicon. Envisage de mettre à niveau ton Mac pour continuer à recevoir des mises à jour."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nb" : {
|
"nb" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI v2.4 er den siste versjonen som støtter Intel-Mac og Rosetta. Fra macOS 28 vil oAI kreve Apple Silicon. Vurder å oppgradere Mac-en din for å fortsette å få oppdateringer."
|
"value" : "Confab (tidligere oAI) v2.4 var den siste versjonen som støttet Intel-Mac og Rosetta. Fra macOS 28 vil Confab kreve Apple Silicon. Vurder å oppgradere Mac-en din for å fortsette å få oppdateringer."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sv" : {
|
"sv" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI v2.4 är den sista versionen som stöder Intel-Mac och Rosetta. Från macOS 28 kommer oAI att kräva Apple Silicon. Överväg att uppgradera din Mac för att fortsätta få uppdateringar."
|
"value" : "Confab (tidigare oAI) v2.4 var den sista versionen som stödde Intel-Mac och Rosetta. Från macOS 28 kommer Confab att kräva Apple Silicon. Överväg att uppgradera din Mac för att fortsätta få uppdateringar."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15616,7 +15616,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Update Available%@" : {
|
"Update Available%@" : {
|
||||||
"comment" : "A button that opens a website with information about a new version of oAI. The argument is the version number of the new version.",
|
"comment" : "A button that opens a website with information about a new version of Confab. The argument is the version number of the new version.",
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"da" : {
|
"da" : {
|
||||||
@@ -15998,7 +15998,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v%@" : {
|
"v%@" : {
|
||||||
"comment" : "A label showing the current version of oAI.",
|
"comment" : "A label showing the current version of Confab.",
|
||||||
"extractionState" : "stale",
|
"extractionState" : "stale",
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AgentSkill.swift
|
// AgentSkill.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// SKILL.md-style behavioral skills — markdown instruction files injected into the system prompt
|
// SKILL.md-style behavioral skills — markdown instruction files injected into the system prompt
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Conversation.swift
|
// Conversation.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Model for saved conversations
|
// Model for saved conversations
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// EmailLog.swift
|
// EmailLog.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Email processing log entry model
|
// Email processing log entry model
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Folder.swift
|
// Folder.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Model for grouping saved conversations
|
// Model for grouping saved conversations
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// HistoryEntry.swift
|
// HistoryEntry.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Command history entry model
|
// Command history entry model
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// JarvisModels.swift
|
// JarvisModels.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Data models for the Jarvis (oAI-Web) API integration.
|
// Data models for the Jarvis (oAI-Web) API integration.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Message.swift
|
// Message.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Core message model for chat conversations
|
// Core message model for chat conversations
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// MockData.swift
|
// MockData.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Mock data for Phase 1 testing
|
// Mock data for Phase 1 testing
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ModelCategory.swift
|
// ModelCategory.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Category tags for AI models, inferred from model name/id/description.
|
// Category tags for AI models, inferred from model name/id/description.
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ModelInfo.swift
|
// ModelInfo.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Model information and capabilities
|
// Model information and capabilities
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -33,6 +33,7 @@ struct ModelInfo: Identifiable, Codable, Hashable {
|
|||||||
var architecture: Architecture? = nil
|
var architecture: Architecture? = nil
|
||||||
var topProvider: String? = nil
|
var topProvider: String? = nil
|
||||||
var categories: [ModelCategory] = []
|
var categories: [ModelCategory] = []
|
||||||
|
var releaseDate: Date? = nil
|
||||||
|
|
||||||
struct Pricing: Codable, Hashable {
|
struct Pricing: Codable, Hashable {
|
||||||
let prompt: Double // per 1M tokens
|
let prompt: Double // per 1M tokens
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// SessionStats.swift
|
// SessionStats.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Session statistics tracking
|
// Session statistics tracking
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Settings.swift
|
// Settings.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Application settings and configuration
|
// Application settings and configuration
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Shortcut.swift
|
// Shortcut.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// User-defined slash command templates (prompt shortcuts/macros)
|
// User-defined slash command templates (prompt shortcuts/macros)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import Foundation
|
|||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// UsageStats.swift
|
// UsageStats.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// All-time usage statistics (aggregated from the messages table)
|
// All-time usage statistics (aggregated from the messages table)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AIProvider.swift
|
// AIProvider.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Protocol for AI provider implementations
|
// Protocol for AI provider implementations
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AnthropicProvider.swift
|
// AnthropicProvider.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Anthropic Messages API provider with SSE streaming and tool support
|
// Anthropic Messages API provider with SSE streaming and tool support
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AppleFoundationProvider.swift
|
// AppleFoundationProvider.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Apple Foundation Models provider (on-device Apple Intelligence)
|
// Apple Foundation Models provider (on-device Apple Intelligence)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// OllamaProvider.swift
|
// OllamaProvider.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Ollama local AI provider with JSON-lines streaming
|
// Ollama local AI provider with JSON-lines streaming
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// OpenAIProvider.swift
|
// OpenAIProvider.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// OpenAI API provider with SSE streaming and tool support
|
// OpenAI API provider with SSE streaming and tool support
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// OpenRouterModels.swift
|
// OpenRouterModels.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// OpenRouter API request and response models
|
// OpenRouter API request and response models
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -330,6 +330,7 @@ struct OpenRouterModelsResponse: Codable {
|
|||||||
let architecture: Architecture?
|
let architecture: Architecture?
|
||||||
let supportedParameters: [String]?
|
let supportedParameters: [String]?
|
||||||
let outputModalities: [String]?
|
let outputModalities: [String]?
|
||||||
|
let created: Int?
|
||||||
|
|
||||||
struct PricingData: Codable {
|
struct PricingData: Codable {
|
||||||
let prompt: String
|
let prompt: String
|
||||||
@@ -357,6 +358,7 @@ struct OpenRouterModelsResponse: Codable {
|
|||||||
case architecture
|
case architecture
|
||||||
case supportedParameters = "supported_parameters"
|
case supportedParameters = "supported_parameters"
|
||||||
case outputModalities = "output_modalities"
|
case outputModalities = "output_modalities"
|
||||||
|
case created
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// OpenRouterProvider.swift
|
// OpenRouterProvider.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// OpenRouter AI provider implementation with SSE streaming
|
// OpenRouter AI provider implementation with SSE streaming
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -106,6 +106,7 @@ class OpenRouterProvider: AIProvider {
|
|||||||
},
|
},
|
||||||
topProvider: modelData.id.components(separatedBy: "/").first
|
topProvider: modelData.id.components(separatedBy: "/").first
|
||||||
)
|
)
|
||||||
|
info.releaseDate = modelData.created.map { Date(timeIntervalSince1970: TimeInterval($0)) }
|
||||||
info.categories = ModelCategory.infer(
|
info.categories = ModelCategory.infer(
|
||||||
name: modelData.name,
|
name: modelData.name,
|
||||||
id: modelData.id,
|
id: modelData.id,
|
||||||
@@ -171,8 +172,8 @@ class OpenRouterProvider: AIProvider {
|
|||||||
urlRequest.httpMethod = "POST"
|
urlRequest.httpMethod = "POST"
|
||||||
urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
||||||
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
urlRequest.addValue("https://github.com/yourusername/oAI", forHTTPHeaderField: "HTTP-Referer")
|
urlRequest.addValue("https://github.com/yourusername/Confab", forHTTPHeaderField: "HTTP-Referer")
|
||||||
urlRequest.addValue("oAI-Swift", forHTTPHeaderField: "X-Title")
|
urlRequest.addValue("Confab-Swift", forHTTPHeaderField: "X-Title")
|
||||||
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: ["model": model, "prompt": prompt])
|
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: ["model": model, "prompt": prompt])
|
||||||
|
|
||||||
let (data, response) = try await session.data(for: urlRequest)
|
let (data, response) = try await session.data(for: urlRequest)
|
||||||
@@ -233,8 +234,8 @@ class OpenRouterProvider: AIProvider {
|
|||||||
urlRequest.httpMethod = "POST"
|
urlRequest.httpMethod = "POST"
|
||||||
urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
||||||
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
urlRequest.addValue("https://github.com/yourusername/oAI", forHTTPHeaderField: "HTTP-Referer")
|
urlRequest.addValue("https://github.com/yourusername/Confab", forHTTPHeaderField: "HTTP-Referer")
|
||||||
urlRequest.addValue("oAI-Swift", forHTTPHeaderField: "X-Title")
|
urlRequest.addValue("Confab-Swift", forHTTPHeaderField: "X-Title")
|
||||||
urlRequest.httpBody = try JSONEncoder().encode(apiRequest)
|
urlRequest.httpBody = try JSONEncoder().encode(apiRequest)
|
||||||
|
|
||||||
let (data, response) = try await session.data(for: urlRequest)
|
let (data, response) = try await session.data(for: urlRequest)
|
||||||
@@ -294,8 +295,8 @@ class OpenRouterProvider: AIProvider {
|
|||||||
urlRequest.httpMethod = "POST"
|
urlRequest.httpMethod = "POST"
|
||||||
urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
||||||
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
urlRequest.addValue("https://github.com/yourusername/oAI", forHTTPHeaderField: "HTTP-Referer")
|
urlRequest.addValue("https://github.com/yourusername/Confab", forHTTPHeaderField: "HTTP-Referer")
|
||||||
urlRequest.addValue("oAI-Swift", forHTTPHeaderField: "X-Title")
|
urlRequest.addValue("Confab-Swift", forHTTPHeaderField: "X-Title")
|
||||||
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: body)
|
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: body)
|
||||||
|
|
||||||
let (data, response) = try await session.data(for: urlRequest)
|
let (data, response) = try await session.data(for: urlRequest)
|
||||||
@@ -333,8 +334,8 @@ class OpenRouterProvider: AIProvider {
|
|||||||
urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
||||||
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
urlRequest.addValue("text/event-stream", forHTTPHeaderField: "Accept")
|
urlRequest.addValue("text/event-stream", forHTTPHeaderField: "Accept")
|
||||||
urlRequest.addValue("https://github.com/yourusername/oAI", forHTTPHeaderField: "HTTP-Referer")
|
urlRequest.addValue("https://github.com/yourusername/Confab", forHTTPHeaderField: "HTTP-Referer")
|
||||||
urlRequest.addValue("oAI-Swift", forHTTPHeaderField: "X-Title")
|
urlRequest.addValue("Confab-Swift", forHTTPHeaderField: "X-Title")
|
||||||
urlRequest.httpBody = try JSONEncoder().encode(apiRequest)
|
urlRequest.httpBody = try JSONEncoder().encode(apiRequest)
|
||||||
|
|
||||||
let (bytes, response) = try await session.bytes(for: urlRequest)
|
let (bytes, response) = try await session.bytes(for: urlRequest)
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ProviderRegistry.swift
|
// ProviderRegistry.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Registry for managing multiple AI providers
|
// Registry for managing multiple AI providers
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
+3
-3
@@ -5,11 +5,11 @@
|
|||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>en</string>
|
<string>en</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>com.rune.oAI.help</string>
|
<string>com.rune.Confab.help</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>oAI Help</string>
|
<string>Confab Help</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>BNDL</string>
|
<string>BNDL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<key>HPDBookIconPath</key>
|
<key>HPDBookIconPath</key>
|
||||||
<string>images/icon.png</string>
|
<string>images/icon.png</string>
|
||||||
<key>HPDBookTitle</key>
|
<key>HPDBookTitle</key>
|
||||||
<string>oAI Help</string>
|
<string>Confab Help</string>
|
||||||
<key>HPDBookType</key>
|
<key>HPDBookType</key>
|
||||||
<string>3</string>
|
<string>3</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
+39
-39
@@ -3,18 +3,18 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="AppleTitle" content="oAI Help">
|
<meta name="AppleTitle" content="Confab Help">
|
||||||
<meta name="AppleIcon" content="images/icon.png">
|
<meta name="AppleIcon" content="images/icon.png">
|
||||||
<meta name="description" content="oAI - AI Chat Assistant for macOS">
|
<meta name="description" content="Confab - AI Chat Assistant for macOS">
|
||||||
<meta name="keywords" content="oAI, AI, chat, assistant, OpenAI, Anthropic, Claude, GPT, commands, help">
|
<meta name="keywords" content="Confab, AI, chat, assistant, OpenAI, Anthropic, Claude, GPT, commands, help">
|
||||||
<title>oAI Help</title>
|
<title>Confab Help</title>
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<header>
|
<header>
|
||||||
<img src="images/icon.png" alt="oAI Icon" class="app-icon">
|
<img src="images/icon.png" alt="Confab Icon" class="app-icon">
|
||||||
<h1>oAI Help</h1>
|
<h1>Confab Help</h1>
|
||||||
<p class="subtitle">AI Chat Assistant for macOS</p>
|
<p class="subtitle">AI Chat Assistant for macOS</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<!-- Getting Started -->
|
<!-- Getting Started -->
|
||||||
<section id="getting-started">
|
<section id="getting-started">
|
||||||
<h2>Getting Started</h2>
|
<h2>Getting Started</h2>
|
||||||
<p>oAI is a powerful AI chat assistant that connects to multiple AI providers including OpenAI, Anthropic, OpenRouter, and local models via Ollama. The app is available in English, Norwegian Bokmål, Swedish, Danish, German, and French — it follows your macOS language preference automatically.</p>
|
<p>Confab is a powerful AI chat assistant that connects to multiple AI providers including OpenAI, Anthropic, OpenRouter, and local models via Ollama. The app is available in English, Norwegian Bokmål, Swedish, Danish, German, and French — it follows your macOS language preference automatically.</p>
|
||||||
|
|
||||||
<div class="steps">
|
<div class="steps">
|
||||||
<h3>Quick Start</h3>
|
<h3>Quick Start</h3>
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
<!-- Providers -->
|
<!-- Providers -->
|
||||||
<section id="providers">
|
<section id="providers">
|
||||||
<h2>AI Providers & API Keys</h2>
|
<h2>AI Providers & API Keys</h2>
|
||||||
<p>oAI supports multiple AI providers. You'll need an API key from at least one provider to use the app.</p>
|
<p>Confab supports multiple AI providers. You'll need an API key from at least one provider to use the app.</p>
|
||||||
|
|
||||||
<h3>Supported Providers</h3>
|
<h3>Supported Providers</h3>
|
||||||
<ul class="provider-list">
|
<ul class="provider-list">
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
<p>Use <kbd>↑</kbd> / <kbd>↓</kbd> to move through the list, <kbd>Return</kbd> to select the highlighted model.</p>
|
<p>Use <kbd>↑</kbd> / <kbd>↓</kbd> to move through the list, <kbd>Return</kbd> to select the highlighted model.</p>
|
||||||
|
|
||||||
<h3>Default Model</h3>
|
<h3>Default Model</h3>
|
||||||
<p>Set a model that oAI always opens with in <strong>Settings → General → Model Settings → Default Model</strong>. Click <strong>Choose…</strong> to pick from the full model list, or <strong>Clear</strong> to remove the default. Switching models during a chat session does <em>not</em> change your saved default — it only changes the current session.</p>
|
<p>Set a model that Confab always opens with in <strong>Settings → General → Model Settings → Default Model</strong>. Click <strong>Choose…</strong> to pick from the full model list, or <strong>Clear</strong> to remove the default. Switching models during a chat session does <em>not</em> change your saved default — it only changes the current session.</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Sending Messages -->
|
<!-- Sending Messages -->
|
||||||
@@ -310,7 +310,7 @@
|
|||||||
<!-- Memory -->
|
<!-- Memory -->
|
||||||
<section id="memory">
|
<section id="memory">
|
||||||
<h2>Memory & Context</h2>
|
<h2>Memory & Context</h2>
|
||||||
<p>oAI features an enhanced memory and context system with intelligent message selection, semantic search, and automatic summarization.</p>
|
<p>Confab features an enhanced memory and context system with intelligent message selection, semantic search, and automatic summarization.</p>
|
||||||
|
|
||||||
<h3>Basic Memory Control</h3>
|
<h3>Basic Memory Control</h3>
|
||||||
<p>Control whether the AI remembers previous messages:</p>
|
<p>Control whether the AI remembers previous messages:</p>
|
||||||
@@ -322,7 +322,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>Smart Context Selection</h3>
|
<h3>Smart Context Selection</h3>
|
||||||
<p>When enabled, oAI intelligently selects which messages to send instead of sending all history. This reduces token usage by 50-80% while maintaining context quality.</p>
|
<p>When enabled, Confab intelligently selects which messages to send instead of sending all history. This reduces token usage by 50-80% while maintaining context quality.</p>
|
||||||
|
|
||||||
<h4>How It Works</h4>
|
<h4>How It Works</h4>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -380,7 +380,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>Progressive Summarization</h3>
|
<h3>Progressive Summarization</h3>
|
||||||
<p>For very long conversations, oAI automatically summarizes older messages to save tokens while preserving context.</p>
|
<p>For very long conversations, Confab automatically summarizes older messages to save tokens while preserving context.</p>
|
||||||
|
|
||||||
<h4>How It Works</h4>
|
<h4>How It Works</h4>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -517,7 +517,7 @@
|
|||||||
<p class="note">The Save dialog includes a folder picker — choose an existing folder or pick <strong>New Folder…</strong> to create one on the spot.</p>
|
<p class="note">The Save dialog includes a folder picker — choose an existing folder or pick <strong>New Folder…</strong> to create one on the spot.</p>
|
||||||
|
|
||||||
<h3 id="unsaved-changes">Unsaved Changes & Crash Recovery</h3>
|
<h3 id="unsaved-changes">Unsaved Changes & Crash Recovery</h3>
|
||||||
<p>oAI tracks unsaved changes like a standard Mac document. Starting a New Chat, clearing the chat, loading a different conversation, or quitting the app while there are unsaved messages shows the standard save prompt:</p>
|
<p>Confab tracks unsaved changes like a standard Mac document. Starting a New Chat, clearing the chat, loading a different conversation, or quitting the app while there are unsaved messages shows the standard save prompt:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Save</strong> — saves the conversation (prompting for a name and folder if it hasn't been saved yet), then proceeds</li>
|
<li><strong>Save</strong> — saves the conversation (prompting for a name and folder if it hasn't been saved yet), then proceeds</li>
|
||||||
<li><strong>Don't Save</strong> (<kbd>⌘D</kbd> in the prompt) — discards the changes and proceeds</li>
|
<li><strong>Don't Save</strong> (<kbd>⌘D</kbd> in the prompt) — discards the changes and proceeds</li>
|
||||||
@@ -525,7 +525,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tip">
|
<div class="tip">
|
||||||
<strong>💡 Crash Recovery:</strong> While you're chatting, oAI periodically mirrors the in-progress conversation to disk (every 10 seconds by default — adjustable or turned off in Settings → General). If oAI crashes or is force-quit, the next launch offers to restore the conversation you were working on, including the model you had selected. This mirror is invisible and separate from your saved conversations — it's cleared automatically as soon as you save, discard, or restore it.
|
<strong>💡 Crash Recovery:</strong> While you're chatting, Confab periodically mirrors the in-progress conversation to disk (every 10 seconds by default — adjustable or turned off in Settings → General). If Confab crashes or is force-quit, the next launch offers to restore the conversation you were working on, including the model you had selected. This mirror is invisible and separate from your saved conversations — it's cleared automatically as soon as you save, discard, or restore it.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>Renaming Conversations</h3>
|
<h3>Renaming Conversations</h3>
|
||||||
@@ -618,7 +618,7 @@
|
|||||||
<li>Click <strong>Clone Repository</strong> to initialize</li>
|
<li>Click <strong>Clone Repository</strong> to initialize</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<p>Saving to Git is explicit rather than automatic — see <a href="#unsaved-changes">Unsaved Changes & Crash Recovery</a> for how oAI tracks and prompts you to save. Every explicit save (<kbd>⌘S</kbd>, Save Chat As…, or the unsaved-changes prompt) triggers a background sync (export + commit + push) automatically when Git Sync is configured.</p>
|
<p>Saving to Git is explicit rather than automatic — see <a href="#unsaved-changes">Unsaved Changes & Crash Recovery</a> for how Confab tracks and prompts you to save. Every explicit save (<kbd>⌘S</kbd>, Save Chat As…, or the unsaved-changes prompt) triggers a background sync (export + commit + push) automatically when Git Sync is configured.</p>
|
||||||
|
|
||||||
<div class="warning">
|
<div class="warning">
|
||||||
<strong>⚠️ Multi-Machine Warning:</strong> Syncing on multiple machines simultaneously can cause merge conflicts. Pull before you start working on a different machine.
|
<strong>⚠️ Multi-Machine Warning:</strong> Syncing on multiple machines simultaneously can cause merge conflicts. Pull before you start working on a different machine.
|
||||||
@@ -645,7 +645,7 @@
|
|||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h3>Sync Status Indicators</h3>
|
<h3>Sync Status Indicators</h3>
|
||||||
<p>oAI shows sync status in two places:</p>
|
<p>Confab shows sync status in two places:</p>
|
||||||
|
|
||||||
<h4>Header Indicator (Green/Orange/Red Pill)</h4>
|
<h4>Header Indicator (Green/Orange/Red Pill)</h4>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -713,7 +713,7 @@ The weather is sunny today!
|
|||||||
<h3>Restoring on a New Machine</h3>
|
<h3>Restoring on a New Machine</h3>
|
||||||
<p>To restore your conversations on a new Mac:</p>
|
<p>To restore your conversations on a new Mac:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Install oAI on the new machine</li>
|
<li>Install Confab on the new machine</li>
|
||||||
<li>Open Settings → Sync tab</li>
|
<li>Open Settings → Sync tab</li>
|
||||||
<li>Enter your repository URL and credentials</li>
|
<li>Enter your repository URL and credentials</li>
|
||||||
<li>Click <strong>Clone Repository</strong></li>
|
<li>Click <strong>Clone Repository</strong></li>
|
||||||
@@ -726,9 +726,9 @@ The weather is sunny today!
|
|||||||
<h4>SSH Key (Recommended)</h4>
|
<h4>SSH Key (Recommended)</h4>
|
||||||
<p>Most secure option. Generate an SSH key and add it to your Git service:</p>
|
<p>Most secure option. Generate an SSH key and add it to your Git service:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Generate key: <code>ssh-keygen -t ed25519 -C "oai@yourmac"</code></li>
|
<li>Generate key: <code>ssh-keygen -t ed25519 -C "confab@yourmac"</code></li>
|
||||||
<li>Add to git service (GitHub Settings → SSH Keys)</li>
|
<li>Add to git service (GitHub Settings → SSH Keys)</li>
|
||||||
<li>Use SSH URL in oAI: <code>git@github.com:username/repo.git</code></li>
|
<li>Use SSH URL in Confab: <code>git@github.com:username/repo.git</code></li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<h4>Access Token</h4>
|
<h4>Access Token</h4>
|
||||||
@@ -748,7 +748,7 @@ The weather is sunny today!
|
|||||||
<li><strong>Enable Auto-Sync on One Machine</strong> - Avoid conflicts by syncing automatically on your primary Mac only</li>
|
<li><strong>Enable Auto-Sync on One Machine</strong> - Avoid conflicts by syncing automatically on your primary Mac only</li>
|
||||||
<li><strong>Manual Sync on Others</strong> - Use Pull/Push buttons on secondary machines</li>
|
<li><strong>Manual Sync on Others</strong> - Use Pull/Push buttons on secondary machines</li>
|
||||||
<li><strong>Regular Backups</strong> - Git history preserves all versions of your conversations</li>
|
<li><strong>Regular Backups</strong> - Git history preserves all versions of your conversations</li>
|
||||||
<li><strong>Don't Edit Manually</strong> - The README warns against manual edits; always use oAI's sync features</li>
|
<li><strong>Don't Edit Manually</strong> - The README warns against manual edits; always use Confab's sync features</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>Troubleshooting</h3>
|
<h3>Troubleshooting</h3>
|
||||||
@@ -776,7 +776,7 @@ The weather is sunny today!
|
|||||||
<!-- Email Handler -->
|
<!-- Email Handler -->
|
||||||
<section id="email-handler">
|
<section id="email-handler">
|
||||||
<h2>Email Handler (AI Assistant)</h2>
|
<h2>Email Handler (AI Assistant)</h2>
|
||||||
<p>Turn oAI into an AI-powered email auto-responder. Monitor an inbox and automatically reply to emails with intelligent, context-aware responses.</p>
|
<p>Turn Confab into an AI-powered email auto-responder. Monitor an inbox and automatically reply to emails with intelligent, context-aware responses.</p>
|
||||||
|
|
||||||
<div class="tip">
|
<div class="tip">
|
||||||
<strong>💡 Use Cases:</strong> Customer support automation, personal assistant emails, automated FAQ responses, email-based task management.
|
<strong>💡 Use Cases:</strong> Customer support automation, personal assistant emails, automated FAQ responses, email-based task management.
|
||||||
@@ -784,7 +784,7 @@ The weather is sunny today!
|
|||||||
|
|
||||||
<h3>How It Works</h3>
|
<h3>How It Works</h3>
|
||||||
<ol>
|
<ol>
|
||||||
<li><strong>IMAP Monitoring</strong> - oAI polls your inbox every 30 seconds for new emails</li>
|
<li><strong>IMAP Monitoring</strong> - Confab polls your inbox every 30 seconds for new emails</li>
|
||||||
<li><strong>Subject Filter</strong> - Only emails with your identifier (e.g., <code>[Jarvis]</code>) are processed</li>
|
<li><strong>Subject Filter</strong> - Only emails with your identifier (e.g., <code>[Jarvis]</code>) are processed</li>
|
||||||
<li><strong>AI Processing</strong> - Email content is sent to your configured AI model</li>
|
<li><strong>AI Processing</strong> - Email content is sent to your configured AI model</li>
|
||||||
<li><strong>Auto-Reply</strong> - AI-generated response is sent via SMTP</li>
|
<li><strong>Auto-Reply</strong> - AI-generated response is sent via SMTP</li>
|
||||||
@@ -812,7 +812,7 @@ The weather is sunny today!
|
|||||||
<li>Click <strong>Test Connection</strong> to verify settings</li>
|
<li>Click <strong>Test Connection</strong> to verify settings</li>
|
||||||
<li>Set <strong>Subject Identifier</strong> (e.g., <code>[Jarvis]</code>)</li>
|
<li>Set <strong>Subject Identifier</strong> (e.g., <code>[Jarvis]</code>)</li>
|
||||||
<li>Select <strong>AI Provider</strong> and <strong>Model</strong> for responses</li>
|
<li>Select <strong>AI Provider</strong> and <strong>Model</strong> for responses</li>
|
||||||
<li>Save settings and restart oAI</li>
|
<li>Save settings and restart Confab</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<div class="note">
|
<div class="note">
|
||||||
@@ -927,8 +927,8 @@ The weather is sunny today!
|
|||||||
<li>Verify subject identifier matches exactly (case-sensitive)</li>
|
<li>Verify subject identifier matches exactly (case-sensitive)</li>
|
||||||
<li>Check email is in INBOX (not Spam/Junk)</li>
|
<li>Check email is in INBOX (not Spam/Junk)</li>
|
||||||
<li>Ensure email handler is enabled in Settings</li>
|
<li>Ensure email handler is enabled in Settings</li>
|
||||||
<li>Restart oAI to reinitialize monitoring</li>
|
<li>Restart Confab to reinitialize monitoring</li>
|
||||||
<li>Check logs: <code>~/Library/Logs/oAI.log</code></li>
|
<li>Check logs: <code>~/Library/Logs/Confab.log</code></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h4>Connection Errors</h4>
|
<h4>Connection Errors</h4>
|
||||||
@@ -943,7 +943,7 @@ The weather is sunny today!
|
|||||||
<h4>SMTP TLS Errors</h4>
|
<h4>SMTP TLS Errors</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Use port 465 (direct TLS) instead of 587 (STARTTLS)</li>
|
<li>Use port 465 (direct TLS) instead of 587 (STARTTLS)</li>
|
||||||
<li>Port 465 is more reliable with oAI's implementation</li>
|
<li>Port 465 is more reliable with Confab's implementation</li>
|
||||||
<li>If only 587 available, contact support</li>
|
<li>If only 587 available, contact support</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -959,7 +959,7 @@ The weather is sunny today!
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Check Email Log for duplicate entries</li>
|
<li>Check Email Log for duplicate entries</li>
|
||||||
<li>Emails should be marked as read after processing</li>
|
<li>Emails should be marked as read after processing</li>
|
||||||
<li>Restart oAI if duplicates persist</li>
|
<li>Restart Confab if duplicates persist</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>Best Practices</h3>
|
<h3>Best Practices</h3>
|
||||||
@@ -1290,7 +1290,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
<!-- iCloud Backup -->
|
<!-- iCloud Backup -->
|
||||||
<section id="icloud-backup">
|
<section id="icloud-backup">
|
||||||
<h2>iCloud Backup</h2>
|
<h2>iCloud Backup</h2>
|
||||||
<p>Back up and restore all your oAI settings with one click. Backups are saved to iCloud Drive so they're available on any Mac where you're signed in.</p>
|
<p>Back up and restore all your Confab settings with one click. Backups are saved to iCloud Drive so they're available on any Mac where you're signed in.</p>
|
||||||
|
|
||||||
<div class="note">
|
<div class="note">
|
||||||
<strong>What is included:</strong> All settings and preferences — providers, model defaults, MCP configuration, appearance, advanced options, shortcuts, skills, and more.<br><br>
|
<strong>What is included:</strong> All settings and preferences — providers, model defaults, MCP configuration, appearance, advanced options, shortcuts, skills, and more.<br><br>
|
||||||
@@ -1315,7 +1315,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<div class="tip">
|
<div class="tip">
|
||||||
<strong>💡 New Mac Setup:</strong> Back up on your old Mac, sign in to iCloud on your new Mac, open oAI, restore from the backup file — and all your settings are restored in seconds. You only need to re-enter API keys.
|
<strong>💡 New Mac Setup:</strong> Back up on your old Mac, sign in to iCloud on your new Mac, open Confab, restore from the backup file — and all your settings are restored in seconds. You only need to re-enter API keys.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>Backup Format</h3>
|
<h3>Backup Format</h3>
|
||||||
@@ -1325,7 +1325,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
<!-- Reasoning / Thinking Tokens -->
|
<!-- Reasoning / Thinking Tokens -->
|
||||||
<section id="reasoning">
|
<section id="reasoning">
|
||||||
<h2>Reasoning / Thinking Tokens</h2>
|
<h2>Reasoning / Thinking Tokens</h2>
|
||||||
<p>Some AI models can "think out loud" before giving their final answer — reasoning through the problem step by step. oAI streams this thinking content live and displays it in a collapsible block above the response.</p>
|
<p>Some AI models can "think out loud" before giving their final answer — reasoning through the problem step by step. Confab streams this thinking content live and displays it in a collapsible block above the response.</p>
|
||||||
|
|
||||||
<h3>Supported Models</h3>
|
<h3>Supported Models</h3>
|
||||||
<p>Reasoning is available on models that support extended thinking, including:</p>
|
<p>Reasoning is available on models that support extended thinking, including:</p>
|
||||||
@@ -1382,7 +1382,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
<!-- Anytype Integration -->
|
<!-- Anytype Integration -->
|
||||||
<section id="anytype">
|
<section id="anytype">
|
||||||
<h2>Anytype Integration</h2>
|
<h2>Anytype Integration</h2>
|
||||||
<p>oAI can connect to your local <a href="https://anytype.io" target="_blank">Anytype</a> desktop app, giving the AI read and write access to your personal knowledge base. All data stays on your machine — the API is local-only.</p>
|
<p>Confab can connect to your local <a href="https://anytype.io" target="_blank">Anytype</a> desktop app, giving the AI read and write access to your personal knowledge base. All data stays on your machine — the API is local-only.</p>
|
||||||
|
|
||||||
<h3>Requirements</h3>
|
<h3>Requirements</h3>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -1392,7 +1392,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
|
|
||||||
<h3>Setup</h3>
|
<h3>Setup</h3>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Open oAI Settings → Anytype tab</li>
|
<li>Open Confab Settings → Anytype tab</li>
|
||||||
<li>Enable the toggle</li>
|
<li>Enable the toggle</li>
|
||||||
<li>Enter your API key (leave the URL as the default unless your setup is unusual)</li>
|
<li>Enter your API key (leave the URL as the default unless your setup is unusual)</li>
|
||||||
<li>Click <strong>Test Connection</strong> — a success message will show how many spaces were found</li>
|
<li>Click <strong>Test Connection</strong> — a success message will show how many spaces were found</li>
|
||||||
@@ -1450,7 +1450,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
<p>Toggle a server off/on or delete it entirely with the trash icon. Crashed servers automatically restart up to 3 times with increasing delay (5s, 15s, 30s) before giving up.</p>
|
<p>Toggle a server off/on or delete it entirely with the trash icon. Crashed servers automatically restart up to 3 times with increasing delay (5s, 15s, 30s) before giving up.</p>
|
||||||
|
|
||||||
<div class="note">
|
<div class="note">
|
||||||
<strong>Note:</strong> Tool names from every external server are prefixed with that server's slug (derived from its Name) so they never collide with oAI's built-in tools or each other.
|
<strong>Note:</strong> Tool names from every external server are prefixed with that server's slug (derived from its Name) so they never collide with Confab's built-in tools or each other.
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -1578,7 +1578,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
<section id="settings">
|
<section id="settings">
|
||||||
<h2>Settings</h2>
|
<h2>Settings</h2>
|
||||||
<p>Customize oAI to your preferences. Press <kbd>⌘,</kbd> to open Settings.</p>
|
<p>Customize Confab to your preferences. Press <kbd>⌘,</kbd> to open Settings.</p>
|
||||||
|
|
||||||
<h3>General Tab</h3>
|
<h3>General Tab</h3>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -1669,7 +1669,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>Paperless Tab <span style="font-size: 0.75em; background: #f90; color: #fff; border-radius: 4px; padding: 1px 5px; vertical-align: middle;">Beta</span></h3>
|
<h3>Paperless Tab <span style="font-size: 0.75em; background: #f90; color: #fff; border-radius: 4px; padding: 1px 5px; vertical-align: middle;">Beta</span></h3>
|
||||||
<p>Connect oAI to a self-hosted <a href="https://docs.paperless-ngx.com" target="_blank">Paperless-NGX</a> instance so the AI can search and read your document archive.</p>
|
<p>Connect Confab to a self-hosted <a href="https://docs.paperless-ngx.com" target="_blank">Paperless-NGX</a> instance so the AI can search and read your document archive.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>URL</strong> — Base URL of your Paperless instance (e.g. <code>https://paperless.yourdomain.com</code>)</li>
|
<li><strong>URL</strong> — Base URL of your Paperless instance (e.g. <code>https://paperless.yourdomain.com</code>)</li>
|
||||||
<li><strong>API Token</strong> — Found in Paperless → Settings → API Tokens</li>
|
<li><strong>API Token</strong> — Found in Paperless → Settings → API Tokens</li>
|
||||||
@@ -1710,7 +1710,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>Anytype Tab</h3>
|
<h3>Anytype Tab</h3>
|
||||||
<p>Connect oAI to your local <a href="https://anytype.io" target="_blank">Anytype</a> desktop app so the AI can search, read, and add content to your knowledge base.</p>
|
<p>Connect Confab to your local <a href="https://anytype.io" target="_blank">Anytype</a> desktop app so the AI can search, read, and add content to your knowledge base.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Enable Anytype</strong> — toggle to activate the integration</li>
|
<li><strong>Enable Anytype</strong> — toggle to activate the integration</li>
|
||||||
<li><strong>API URL</strong> — local Anytype API endpoint (default: <code>http://127.0.0.1:31009</code>)</li>
|
<li><strong>API URL</strong> — local Anytype API endpoint (default: <code>http://127.0.0.1:31009</code>)</li>
|
||||||
@@ -1751,7 +1751,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>Default System Prompt</h3>
|
<h3>Default System Prompt</h3>
|
||||||
<p>oAI includes a carefully crafted default system prompt that emphasizes:</p>
|
<p>Confab includes a carefully crafted default system prompt that emphasizes:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Accuracy First</strong> - Never invent information or make assumptions</li>
|
<li><strong>Accuracy First</strong> - Never invent information or make assumptions</li>
|
||||||
<li><strong>Ask for Clarification</strong> - Request details when requests are ambiguous</li>
|
<li><strong>Ask for Clarification</strong> - Request details when requests are ambiguous</li>
|
||||||
@@ -1773,7 +1773,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>How Prompts Are Combined</h3>
|
<h3>How Prompts Are Combined</h3>
|
||||||
<p>When you send a message, oAI constructs the complete system prompt like this:</p>
|
<p>When you send a message, Confab constructs the complete system prompt like this:</p>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<p><strong>Complete System Prompt =</strong></p>
|
<p><strong>Complete System Prompt =</strong></p>
|
||||||
@@ -1812,7 +1812,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p>© 2026 oAI - Rune Olsen. For support or feedback, visit <a href="https://gitlab.pm/rune/oai-swift">gitlab.pm</a> or <a href="mailto:support@fubar.pm?subject=oAI Support&body=What can I help you with?">Contact Us</a>.</p>
|
<p>© 2026 Confab - Rune Olsen. For support or feedback, visit <a href="https://gitlab.pm/rune/oai-swift">gitlab.pm</a> or <a href="mailto:support@fubar.pm?subject=Confab Support&body=What can I help you with?">Contact Us</a>.</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* oAI Help Stylesheet - Apple Human Interface Guidelines */
|
/* Confab Help Stylesheet - Apple Human Interface Guidelines */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--primary-color: #007AFF;
|
--primary-color: #007AFF;
|
||||||
@@ -1,31 +1,31 @@
|
|||||||
# oAI Help Book
|
# Confab Help Book
|
||||||
|
|
||||||
This folder contains the Apple Help Book for oAI.
|
This folder contains the Apple Help Book for Confab.
|
||||||
|
|
||||||
## Adding to Xcode Project
|
## Adding to Xcode Project
|
||||||
|
|
||||||
1. **Add the help folder to your project:**
|
1. **Add the help folder to your project:**
|
||||||
- In Xcode, right-click on the `Resources` folder in the Project Navigator
|
- In Xcode, right-click on the `Resources` folder in the Project Navigator
|
||||||
- Select "Add Files to 'oAI'..."
|
- Select "Add Files to 'Confab'..."
|
||||||
- Select the `oAI.help` folder
|
- Select the `Confab.help` folder
|
||||||
- **Important:** Check "Create folder references" (NOT "Create groups")
|
- **Important:** Check "Create folder references" (NOT "Create groups")
|
||||||
- Click "Add"
|
- Click "Add"
|
||||||
|
|
||||||
2. **Configure the help book in build settings:**
|
2. **Configure the help book in build settings:**
|
||||||
- Select your oAI target in Xcode
|
- Select your Confab target in Xcode
|
||||||
- Go to the "Info" tab
|
- Go to the "Info" tab
|
||||||
- Add a new key: `CFBundleHelpBookName` with value: `oAI Help`
|
- Add a new key: `CFBundleHelpBookName` with value: `Confab Help`
|
||||||
- Add another key: `CFBundleHelpBookFolder` with value: `oAI.help`
|
- Add another key: `CFBundleHelpBookFolder` with value: `Confab.help`
|
||||||
|
|
||||||
3. **Build and test:**
|
3. **Build and test:**
|
||||||
- Build the app (⌘B)
|
- Build the app (⌘B)
|
||||||
- Run the app (⌘R)
|
- Run the app (⌘R)
|
||||||
- Press ⌘? or select Help → oAI Help to open the help
|
- Press ⌘? or select Help → Confab Help to open the help
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
oAI.help/
|
Confab.help/
|
||||||
├── Contents/
|
├── Contents/
|
||||||
│ ├── Info.plist # Help book metadata
|
│ ├── Info.plist # Help book metadata
|
||||||
│ └── Resources/
|
│ └── Resources/
|
||||||
@@ -37,7 +37,7 @@ oAI.help/
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- ✅ Comprehensive coverage of all oAI features
|
- ✅ Comprehensive coverage of all Confab features
|
||||||
- ✅ Searchable via macOS Help menu search
|
- ✅ Searchable via macOS Help menu search
|
||||||
- ✅ Dark mode support
|
- ✅ Dark mode support
|
||||||
- ✅ Organized by topic with table of contents
|
- ✅ Organized by topic with table of contents
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AgentSkillFilesService.swift
|
// AgentSkillFilesService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Manages per-skill file directories in Application Support/oAI/skills/<uuid>/
|
// Manages per-skill file directories in Application Support/oAI/skills/<uuid>/
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AnthropicOAuthService.swift
|
// AnthropicOAuthService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// OAuth 2.0 PKCE flow for Anthropic Pro/Max subscription login
|
// OAuth 2.0 PKCE flow for Anthropic Pro/Max subscription login
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AnytypeMCPService.swift
|
// AnytypeMCPService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Anytype MCP integration via local HTTP API at http://127.0.0.1:31009
|
// Anytype MCP integration via local HTTP API at http://127.0.0.1:31009
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -29,7 +29,7 @@ class AnytypeMCPService {
|
|||||||
static let shared = AnytypeMCPService()
|
static let shared = AnytypeMCPService()
|
||||||
|
|
||||||
private let settings = SettingsService.shared
|
private let settings = SettingsService.shared
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "mcp")
|
private let log = Logger(subsystem: Log.subsystem, category: "mcp")
|
||||||
private let apiVersion = "2025-11-08"
|
private let apiVersion = "2025-11-08"
|
||||||
private let timeout: TimeInterval = 10
|
private let timeout: TimeInterval = 10
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// BackupService.swift
|
// BackupService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// iCloud Drive backup of non-encrypted settings (Option C, v1)
|
// iCloud Drive backup of non-encrypted settings (Option C, v1)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -49,7 +49,7 @@ struct FavoritesPayload: Codable {
|
|||||||
final class BackupService {
|
final class BackupService {
|
||||||
static let shared = BackupService()
|
static let shared = BackupService()
|
||||||
|
|
||||||
private let log = Logger(subsystem: "oAI", category: "backup")
|
private let log = Logger(subsystem: Log.subsystem, category: "backup")
|
||||||
|
|
||||||
/// Whether iCloud Drive is available on this machine
|
/// Whether iCloud Drive is available on this machine
|
||||||
var iCloudAvailable: Bool = false
|
var iCloudAvailable: Bool = false
|
||||||
@@ -332,7 +332,7 @@ enum BackupError: LocalizedError {
|
|||||||
case .invalidFormat(let detail):
|
case .invalidFormat(let detail):
|
||||||
return "The backup file is not valid: \(detail)"
|
return "The backup file is not valid: \(detail)"
|
||||||
case .unsupportedVersion(let v):
|
case .unsupportedVersion(let v):
|
||||||
return "Backup version \(v) is not supported by this version of oAI."
|
return "Backup version \(v) is not supported by this version of Confab."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ContactsService.swift
|
// ContactsService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Read-only Contacts integration: search and "my card" lookup
|
// Read-only Contacts integration: search and "my card" lookup
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// ContextSelectionService.swift
|
// ContextSelectionService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Smart context selection for AI conversations
|
// Smart context selection for AI conversations
|
||||||
// Selects relevant messages instead of sending entire history
|
// Selects relevant messages instead of sending entire history
|
||||||
@@ -8,11 +8,11 @@
|
|||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ConversationExportService.swift
|
// ConversationExportService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Shared conversation export: Markdown, HTML, and PDF
|
// Shared conversation export: Markdown, HTML, and PDF
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ConversationMergeService.swift
|
// ConversationMergeService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Combine multiple saved conversations into one (simple concatenation or AI-assisted merge)
|
// Combine multiple saved conversations into one (simple concatenation or AI-assisted merge)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// DatabaseService.swift
|
// DatabaseService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// SQLite persistence layer for conversations using GRDB
|
// SQLite persistence layer for conversations using GRDB
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// DraftRecoveryService.swift
|
// DraftRecoveryService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Crash-recovery draft for the in-progress conversation — a lightweight,
|
// Crash-recovery draft for the in-progress conversation — a lightweight,
|
||||||
// invisible mirror of the current chat, distinct from named saved conversations.
|
// invisible mirror of the current chat, distinct from named saved conversations.
|
||||||
@@ -8,11 +8,11 @@
|
|||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// EmailHandlerService.swift
|
// EmailHandlerService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// AI-powered email auto-responder service
|
// AI-powered email auto-responder service
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -32,7 +32,7 @@ final class EmailHandlerService {
|
|||||||
private let emailService = EmailService.shared
|
private let emailService = EmailService.shared
|
||||||
private let emailLog = EmailLogService.shared
|
private let emailLog = EmailLogService.shared
|
||||||
private let mcp = MCPService.shared
|
private let mcp = MCPService.shared
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "email-handler")
|
private let log = Logger(subsystem: Log.subsystem, category: "email-handler")
|
||||||
|
|
||||||
// Rate limiting
|
// Rate limiting
|
||||||
private var emailsProcessedThisHour: Int = 0
|
private var emailsProcessedThisHour: Int = 0
|
||||||
@@ -403,7 +403,7 @@ final class EmailHandlerService {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<p>🤖 This response was generated by AI using oAI Email Handler</p>
|
<p>🤖 This response was generated by AI using Confab Email Handler</p>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// EmailLogService.swift
|
// EmailLogService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Service for managing email handler activity logs
|
// Service for managing email handler activity logs
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -29,7 +29,7 @@ final class EmailLogService {
|
|||||||
static let shared = EmailLogService()
|
static let shared = EmailLogService()
|
||||||
|
|
||||||
private let db = DatabaseService.shared
|
private let db = DatabaseService.shared
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "email-log")
|
private let log = Logger(subsystem: Log.subsystem, category: "email-log")
|
||||||
|
|
||||||
private init() {}
|
private init() {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// EmailService.swift
|
// EmailService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// IMAP IDLE email monitoring service for AI email handler
|
// IMAP IDLE email monitoring service for AI email handler
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -71,7 +71,7 @@ final class EmailService {
|
|||||||
static let shared = EmailService()
|
static let shared = EmailService()
|
||||||
|
|
||||||
private let settings = SettingsService.shared
|
private let settings = SettingsService.shared
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "email")
|
private let log = Logger(subsystem: Log.subsystem, category: "email")
|
||||||
|
|
||||||
// IMAP IDLE state
|
// IMAP IDLE state
|
||||||
private var isConnected = false
|
private var isConnected = false
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// EmbeddingService.swift
|
// EmbeddingService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Embedding generation and semantic search
|
// Embedding generation and semantic search
|
||||||
// Supports multiple providers: OpenAI, OpenRouter, Google
|
// Supports multiple providers: OpenAI, OpenRouter, Google
|
||||||
@@ -8,11 +8,11 @@
|
|||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -205,7 +205,7 @@ final class EmbeddingService {
|
|||||||
request.httpMethod = "POST"
|
request.httpMethod = "POST"
|
||||||
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
|
||||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
request.setValue("https://github.com/yourusername/oAI", forHTTPHeaderField: "HTTP-Referer")
|
request.setValue("https://github.com/yourusername/Confab", forHTTPHeaderField: "HTTP-Referer")
|
||||||
|
|
||||||
let body: [String: Any] = [
|
let body: [String: Any] = [
|
||||||
"input": text,
|
"input": text,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// EncryptionService.swift
|
// EncryptionService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Secure encryption for sensitive data (API keys)
|
// Secure encryption for sensitive data (API keys)
|
||||||
// Uses CryptoKit with machine-specific key derivation
|
// Uses CryptoKit with machine-specific key derivation
|
||||||
@@ -8,11 +8,11 @@
|
|||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -72,7 +72,10 @@ class EncryptionService {
|
|||||||
/// Derive encryption key from machine-specific data
|
/// Derive encryption key from machine-specific data
|
||||||
private static func deriveEncryptionKey() -> SymmetricKey {
|
private static func deriveEncryptionKey() -> SymmetricKey {
|
||||||
let machineUUID = getMachineUUID()
|
let machineUUID = getMachineUUID()
|
||||||
let bundleID = Bundle.main.bundleIdentifier ?? "com.oai.oAI"
|
// Pinned, not read from Bundle.main.bundleIdentifier: the app's bundle ID changed
|
||||||
|
// (oAI -> Confab rename) but this key material must not, or every already-encrypted
|
||||||
|
// setting (provider API keys, sync/email credentials) becomes undecryptable.
|
||||||
|
let bundleID = "com.oai.oAI"
|
||||||
let salt = "oAI-secure-storage-v1"
|
let salt = "oAI-secure-storage-v1"
|
||||||
let keyMaterial = "\(machineUUID)-\(bundleID)-\(salt)"
|
let keyMaterial = "\(machineUUID)-\(bundleID)-\(salt)"
|
||||||
let hash = SHA256.hash(data: Data(keyMaterial.utf8))
|
let hash = SHA256.hash(data: Data(keyMaterial.utf8))
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// EventKitService.swift
|
// EventKitService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Calendar and Reminders integration via EventKit
|
// Calendar and Reminders integration via EventKit
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ final class ExternalMCPClient {
|
|||||||
let _: MCPInitializeResult = try await timedRequest(seconds: 15, method: "initialize", params: [
|
let _: MCPInitializeResult = try await timedRequest(seconds: 15, method: "initialize", params: [
|
||||||
"protocolVersion": "2024-11-05",
|
"protocolVersion": "2024-11-05",
|
||||||
"capabilities": [:] as [String: Any],
|
"capabilities": [:] as [String: Any],
|
||||||
"clientInfo": ["name": "oAI", "version": "1.0"] as [String: Any]
|
"clientInfo": ["name": "Confab", "version": "1.0"] as [String: Any]
|
||||||
])
|
])
|
||||||
try sendNotification(method: "notifications/initialized")
|
try sendNotification(method: "notifications/initialized")
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import Foundation
|
|||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -24,7 +24,7 @@ class GitSyncService {
|
|||||||
|
|
||||||
private let settings = SettingsService.shared
|
private let settings = SettingsService.shared
|
||||||
private let db = DatabaseService.shared
|
private let db = DatabaseService.shared
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "sync")
|
private let log = Logger(subsystem: Log.subsystem, category: "sync")
|
||||||
|
|
||||||
private(set) var syncStatus = SyncStatus()
|
private(set) var syncStatus = SyncStatus()
|
||||||
private(set) var isSyncing = false
|
private(set) var isSyncing = false
|
||||||
@@ -90,7 +90,7 @@ class GitSyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Push local changes to remote
|
/// Push local changes to remote
|
||||||
func push(message: String = "Sync from oAI") async throws {
|
func push(message: String = "Sync from Confab") async throws {
|
||||||
try ensureCloned()
|
try ensureCloned()
|
||||||
|
|
||||||
let localPath = expandPath(settings.syncLocalPath)
|
let localPath = expandPath(settings.syncLocalPath)
|
||||||
@@ -314,20 +314,20 @@ class GitSyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let readme = """
|
let readme = """
|
||||||
# oAI Conversation Sync
|
# Confab Conversation Sync
|
||||||
|
|
||||||
This repository contains your oAI conversations in markdown format.
|
This repository contains your Confab conversations in markdown format.
|
||||||
|
|
||||||
## ⚠️ WARNING - DO NOT MANUALLY EDIT
|
## ⚠️ WARNING - DO NOT MANUALLY EDIT
|
||||||
|
|
||||||
**This repository is automatically managed by oAI.**
|
**This repository is automatically managed by Confab.**
|
||||||
|
|
||||||
- ❌ **DO NOT manually edit** these files
|
- ❌ **DO NOT manually edit** these files
|
||||||
- ❌ **DO NOT add** files to this repository
|
- ❌ **DO NOT add** files to this repository
|
||||||
- ❌ **DO NOT delete** files from this repository
|
- ❌ **DO NOT delete** files from this repository
|
||||||
- ❌ **DO NOT merge conflicts** manually (let oAI handle it)
|
- ❌ **DO NOT merge conflicts** manually (let Confab handle it)
|
||||||
|
|
||||||
**Why?** oAI rebuilds its internal database from these files. Manual edits will be:
|
**Why?** Confab rebuilds its internal database from these files. Manual edits will be:
|
||||||
- Overwritten on next sync
|
- Overwritten on next sync
|
||||||
- May cause data corruption
|
- May cause data corruption
|
||||||
- May prevent proper import/restore
|
- May prevent proper import/restore
|
||||||
@@ -335,13 +335,13 @@ class GitSyncService {
|
|||||||
## How It Works
|
## How It Works
|
||||||
|
|
||||||
### Export (Automatic)
|
### Export (Automatic)
|
||||||
- oAI saves conversations to its local database
|
- Confab saves conversations to its local database
|
||||||
- Auto-sync exports conversations to `conversations/*.md`
|
- Auto-sync exports conversations to `conversations/*.md`
|
||||||
- Files are committed and pushed to this git repository
|
- Files are committed and pushed to this git repository
|
||||||
|
|
||||||
### Import (On New Machine)
|
### Import (On New Machine)
|
||||||
- Clone this repository on a new machine
|
- Clone this repository on a new machine
|
||||||
- oAI imports markdown files into its database
|
- Confab imports markdown files into its database
|
||||||
- Your conversation history is restored
|
- Your conversation history is restored
|
||||||
|
|
||||||
### Sync Across Machines
|
### Sync Across Machines
|
||||||
@@ -399,28 +399,28 @@ class GitSyncService {
|
|||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
**Problem:** Files not syncing?
|
**Problem:** Files not syncing?
|
||||||
- Check Settings → Sync in oAI
|
- Check Settings → Sync in Confab
|
||||||
- Verify git credentials are correct
|
- Verify git credentials are correct
|
||||||
- Check network connection
|
- Check network connection
|
||||||
|
|
||||||
**Problem:** Conflicts after editing?
|
**Problem:** Conflicts after editing?
|
||||||
- Restore from git: `git reset --hard origin/main`
|
- Restore from git: `git reset --hard origin/main`
|
||||||
- Re-export from oAI: Manual Sync → Export All → Push
|
- Re-export from Confab: Manual Sync → Export All → Push
|
||||||
|
|
||||||
**Problem:** Lost conversations?
|
**Problem:** Lost conversations?
|
||||||
- Conversations are in your local oAI database
|
- Conversations are in your local Confab database
|
||||||
- Export manually: Settings → Sync → Export All
|
- Export manually: Settings → Sync → Export All
|
||||||
- Check git history for deleted files
|
- Check git history for deleted files
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
For help with oAI, see:
|
For help with Confab, see:
|
||||||
- Settings → Help in oAI app
|
- Settings → Help in Confab app
|
||||||
- GitHub issues (if open source)
|
- GitHub issues (if open source)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Generated by oAI v1.0**
|
**Generated by Confab v1.0**
|
||||||
**Last updated:** \(ISO8601DateFormatter().string(from: Date()))
|
**Last updated:** \(ISO8601DateFormatter().string(from: Date()))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -504,7 +504,7 @@ class GitSyncService {
|
|||||||
try await exportAllConversations()
|
try await exportAllConversations()
|
||||||
|
|
||||||
// Push to git
|
// Push to git
|
||||||
try await push(message: "Auto-sync from oAI")
|
try await push(message: "Auto-sync from Confab")
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// IMAPClient.swift
|
// IMAPClient.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Swift-native IMAP client for email monitoring
|
// Swift-native IMAP client for email monitoring
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -26,7 +26,7 @@ import Network
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
class IMAPClient {
|
class IMAPClient {
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "imap")
|
private let log = Logger(subsystem: Log.subsystem, category: "imap")
|
||||||
|
|
||||||
private var connection: NWConnection?
|
private var connection: NWConnection?
|
||||||
private var host: String
|
private var host: String
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// JarvisService.swift
|
// JarvisService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// HTTP client for the Jarvis (oAI-Web) REST API.
|
// HTTP client for the Jarvis (oAI-Web) REST API.
|
||||||
// Auth: Authorization: Bearer <api-key>
|
// Auth: Authorization: Bearer <api-key>
|
||||||
@@ -15,7 +15,7 @@ final class JarvisService: Sendable {
|
|||||||
static let shared = JarvisService()
|
static let shared = JarvisService()
|
||||||
private init() {}
|
private init() {}
|
||||||
|
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "jarvis")
|
private let log = Logger(subsystem: Log.subsystem, category: "jarvis")
|
||||||
|
|
||||||
private var baseURL: String { SettingsService.shared.jarvisURL }
|
private var baseURL: String { SettingsService.shared.jarvisURL }
|
||||||
private var apiKey: String? { SettingsService.shared.jarvisAPIKey }
|
private var apiKey: String? { SettingsService.shared.jarvisAPIKey }
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// LocationMapsService.swift
|
// LocationMapsService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Read-only Location and Maps integration via CoreLocation and MapKit
|
// Read-only Location and Maps integration via CoreLocation and MapKit
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// MCPService.swift
|
// MCPService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// MCP (Model Context Protocol) service for filesystem tool execution
|
// MCP (Model Context Protocol) service for filesystem tool execution
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -100,7 +100,7 @@ class MCPService {
|
|||||||
// Always allow the system temp directory — external MCP servers and tools write
|
// Always allow the system temp directory — external MCP servers and tools write
|
||||||
// intermediate data there (e.g. Safari MCP page-content files, generated images).
|
// intermediate data there (e.g. Safari MCP page-content files, generated images).
|
||||||
// Check both NSTemporaryDirectory() (per-user Darwin temp dir) and /tmp (what this
|
// Check both NSTemporaryDirectory() (per-user Darwin temp dir) and /tmp (what this
|
||||||
// codebase's own temp files actually use, e.g. ChatViewModel's /tmp/oai_generated_*
|
// codebase's own temp files actually use, e.g. ChatViewModel's /tmp/confab_generated_*
|
||||||
// and ExternalMCPClient's /tmp/oai_mcp_* — they resolve to different directories.
|
// and ExternalMCPClient's /tmp/oai_mcp_* — they resolve to different directories.
|
||||||
let tmpCandidates = [
|
let tmpCandidates = [
|
||||||
(NSTemporaryDirectory() as NSString).standardizingPath,
|
(NSTemporaryDirectory() as NSString).standardizingPath,
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// PaperlessService.swift
|
// PaperlessService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Paperless-NGX integration: search, read, and upload documents via REST API
|
// Paperless-NGX integration: search, read, and upload documents via REST API
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -29,7 +29,7 @@ class PaperlessService {
|
|||||||
static let shared = PaperlessService()
|
static let shared = PaperlessService()
|
||||||
|
|
||||||
private let settings = SettingsService.shared
|
private let settings = SettingsService.shared
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "mcp")
|
private let log = Logger(subsystem: Log.subsystem, category: "mcp")
|
||||||
private let readTimeout: TimeInterval = 15
|
private let readTimeout: TimeInterval = 15
|
||||||
private let uploadTimeout: TimeInterval = 60
|
private let uploadTimeout: TimeInterval = 60
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// SMTPClient.swift
|
// SMTPClient.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Swift-native SMTP client for sending emails
|
// Swift-native SMTP client for sending emails
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -26,7 +26,7 @@ import Network
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
class SMTPClient {
|
class SMTPClient {
|
||||||
private let log = Logger(subsystem: "com.oai.oAI", category: "smtp")
|
private let log = Logger(subsystem: Log.subsystem, category: "smtp")
|
||||||
|
|
||||||
private var connection: NWConnection?
|
private var connection: NWConnection?
|
||||||
private var host: String
|
private var host: String
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// SettingsService.swift
|
// SettingsService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Settings persistence: SQLite for preferences, Keychain for API keys
|
// Settings persistence: SQLite for preferences, Keychain for API keys
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ThinkingVerbs.swift
|
// ThinkingVerbs.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Fun random verbs for AI thinking/processing states
|
// Fun random verbs for AI thinking/processing states
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// UpdateCheckService.swift
|
// UpdateCheckService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Checks for new releases on GitLab and surfaces an update badge in the footer
|
// Checks for new releases on GitLab and surfaces an update badge in the footer
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// WebSearchService.swift
|
// WebSearchService.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// DuckDuckGo web search for non-OpenRouter providers
|
// DuckDuckGo web search for non-OpenRouter providers
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Color+Extensions.swift
|
// Color+Extensions.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Color scheme matching Python TUI dark theme
|
// Color scheme matching Python TUI dark theme
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -26,30 +26,30 @@ import SwiftUI
|
|||||||
extension Color {
|
extension Color {
|
||||||
// MARK: - oAI Color Palette (Matching Python TUI)
|
// MARK: - oAI Color Palette (Matching Python TUI)
|
||||||
|
|
||||||
static let oaiBackground = Color(hex: "#1e1e1e") // Main background
|
static let confabBackground = Color(hex: "#1e1e1e") // Main background
|
||||||
static let oaiSurface = Color(hex: "#2d2d2d") // Cards, surfaces
|
static let confabSurface = Color(hex: "#2d2d2d") // Cards, surfaces
|
||||||
static let oaiPrimary = Color(hex: "#cccccc") // Primary text
|
static let confabPrimary = Color(hex: "#cccccc") // Primary text
|
||||||
static let oaiSecondary = Color(hex: "#888888") // Secondary text
|
static let confabSecondary = Color(hex: "#888888") // Secondary text
|
||||||
static let oaiAccent = Color(hex: "#0a7aca") // Blue accent (assistant)
|
static let confabAccent = Color(hex: "#0a7aca") // Blue accent (assistant)
|
||||||
static let oaiSuccess = Color(hex: "#90ee90") // Green (user messages)
|
static let confabSuccess = Color(hex: "#90ee90") // Green (user messages)
|
||||||
static let oaiError = Color(hex: "#ff6b6b") // Red (errors)
|
static let confabError = Color(hex: "#ff6b6b") // Red (errors)
|
||||||
static let oaiWarning = Color(hex: "#ffaa00") // Orange (warnings)
|
static let confabWarning = Color(hex: "#ffaa00") // Orange (warnings)
|
||||||
static let oaiBorder = Color(hex: "#555555") // Borders, dividers
|
static let confabBorder = Color(hex: "#555555") // Borders, dividers
|
||||||
|
|
||||||
// MARK: - Message Role Colors
|
// MARK: - Message Role Colors
|
||||||
|
|
||||||
static func messageColor(for role: MessageRole) -> Color {
|
static func messageColor(for role: MessageRole) -> Color {
|
||||||
switch role {
|
switch role {
|
||||||
case .user: return .oaiSuccess
|
case .user: return .confabSuccess
|
||||||
case .assistant: return .oaiAccent
|
case .assistant: return .confabAccent
|
||||||
case .system: return .oaiSecondary
|
case .system: return .confabSecondary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func messageBackground(for role: MessageRole) -> Color {
|
static func messageBackground(for role: MessageRole) -> Color {
|
||||||
switch role {
|
switch role {
|
||||||
case .user: return .oaiSurface
|
case .user: return .confabSurface
|
||||||
case .assistant: return .oaiBackground
|
case .assistant: return .confabBackground
|
||||||
case .system: return Color(hex: "#2a2a2a")
|
case .system: return Color(hex: "#2a2a2a")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// String+Extensions.swift
|
// String+Extensions.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// String utility extensions
|
// String utility extensions
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// View+Extensions.swift
|
// View+Extensions.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// SwiftUI view helpers and modifiers
|
// SwiftUI view helpers and modifiers
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -57,33 +57,33 @@ extension View {
|
|||||||
|
|
||||||
// MARK: - Common Styling
|
// MARK: - Common Styling
|
||||||
|
|
||||||
func oaiCardStyle() -> some View {
|
func confabCardStyle() -> some View {
|
||||||
self
|
self
|
||||||
.background(Color.oaiSurface)
|
.background(Color.confabSurface)
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
.overlay(
|
.overlay(
|
||||||
RoundedRectangle(cornerRadius: 8)
|
RoundedRectangle(cornerRadius: 8)
|
||||||
.stroke(Color.oaiBorder, lineWidth: 1)
|
.stroke(Color.confabBorder, lineWidth: 1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func oaiButton() -> some View {
|
func confabButton() -> some View {
|
||||||
self
|
self
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.background(Color.oaiSurface)
|
.background(Color.confabSurface)
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func oaiTextField() -> some View {
|
func confabTextField() -> some View {
|
||||||
self
|
self
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.background(Color.oaiBackground)
|
.background(Color.confabBackground)
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
.overlay(
|
.overlay(
|
||||||
RoundedRectangle(cornerRadius: 6)
|
RoundedRectangle(cornerRadius: 6)
|
||||||
.stroke(Color.oaiBorder, lineWidth: 1)
|
.stroke(Color.confabBorder, lineWidth: 1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Logging.swift
|
// Logging.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Dual logging: os.Logger (unified log) + file (~Library/Logs/oAI.log)
|
// Dual logging: os.Logger (unified log) + file (~Library/Logs/oAI.log)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -82,7 +82,7 @@ final class FileLogger: @unchecked Sendable {
|
|||||||
private init() {
|
private init() {
|
||||||
let logsDir = FileManager.default.homeDirectoryForCurrentUser
|
let logsDir = FileManager.default.homeDirectoryForCurrentUser
|
||||||
.appendingPathComponent("Library/Logs")
|
.appendingPathComponent("Library/Logs")
|
||||||
let logFile = logsDir.appendingPathComponent("oAI.log")
|
let logFile = logsDir.appendingPathComponent("Confab.log")
|
||||||
|
|
||||||
// Ensure file exists
|
// Ensure file exists
|
||||||
if !FileManager.default.fileExists(atPath: logFile.path) {
|
if !FileManager.default.fileExists(atPath: logFile.path) {
|
||||||
@@ -142,7 +142,7 @@ struct AppLogger: Sendable {
|
|||||||
// MARK: - Log Namespace
|
// MARK: - Log Namespace
|
||||||
|
|
||||||
enum Log {
|
enum Log {
|
||||||
private nonisolated static let subsystem = "com.oai.oAI"
|
nonisolated static let subsystem = "com.oai.Confab"
|
||||||
|
|
||||||
nonisolated static let api = AppLogger(subsystem: subsystem, category: "api")
|
nonisolated static let api = AppLogger(subsystem: subsystem, category: "api")
|
||||||
nonisolated static let db = AppLogger(subsystem: subsystem, category: "database")
|
nonisolated static let db = AppLogger(subsystem: subsystem, category: "database")
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// SyntaxHighlighter.swift
|
// SyntaxHighlighter.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Keyword-based syntax highlighting using AttributedString
|
// Keyword-based syntax highlighting using AttributedString
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ChatViewModel.swift
|
// ChatViewModel.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Main chat view model
|
// Main chat view model
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -1563,7 +1563,7 @@ Don't narrate future actions ("Let me...") - just use the tools.
|
|||||||
didContinueAfterImages = true
|
didContinueAfterImages = true
|
||||||
let timestamp = Int(Date().timeIntervalSince1970)
|
let timestamp = Int(Date().timeIntervalSince1970)
|
||||||
let tempPaths: [String] = finalImages.enumerated().compactMap { i, imgData in
|
let tempPaths: [String] = finalImages.enumerated().compactMap { i, imgData in
|
||||||
let path = "/tmp/oai_generated_\(timestamp)_\(i).png"
|
let path = "/tmp/confab_generated_\(timestamp)_\(i).png"
|
||||||
let ok = FileManager.default.createFile(atPath: path, contents: imgData)
|
let ok = FileManager.default.createFile(atPath: path, contents: imgData)
|
||||||
Log.ui.debug("Saved generated image to temp: \(path) ok=\(ok)")
|
Log.ui.debug("Saved generated image to temp: \(path) ok=\(ok)")
|
||||||
return ok ? path : nil
|
return ok ? path : nil
|
||||||
@@ -2138,7 +2138,7 @@ Don't narrate future actions ("Let me...") - just use the tools.
|
|||||||
let alert = NSAlert()
|
let alert = NSAlert()
|
||||||
alert.alertStyle = .informational
|
alert.alertStyle = .informational
|
||||||
alert.messageText = "Restore unsaved conversation?"
|
alert.messageText = "Restore unsaved conversation?"
|
||||||
alert.informativeText = "oAI didn't close properly last time. Would you like to restore the conversation you were working on?"
|
alert.informativeText = "Confab didn't close properly last time. Would you like to restore the conversation you were working on?"
|
||||||
alert.addButton(withTitle: "Restore")
|
alert.addButton(withTitle: "Restore")
|
||||||
alert.addButton(withTitle: "Discard")
|
alert.addButton(withTitle: "Discard")
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ChatView.swift
|
// ChatView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Main chat interface
|
// Main chat interface
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -64,7 +64,7 @@ struct ChatView: View {
|
|||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
.background(Color.oaiBackground)
|
.background(Color.confabBackground)
|
||||||
.onChange(of: viewModel.messages.count) {
|
.onChange(of: viewModel.messages.count) {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
proxy.scrollTo("bottom", anchor: .bottom)
|
proxy.scrollTo("bottom", anchor: .bottom)
|
||||||
@@ -101,7 +101,7 @@ struct ChatView: View {
|
|||||||
mcpEnabled: viewModel.mcpEnabled
|
mcpEnabled: viewModel.mcpEnabled
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.background(Color.oaiBackground)
|
.background(Color.confabBackground)
|
||||||
.sheet(isPresented: $viewModel.showShortcuts) {
|
.sheet(isPresented: $viewModel.showShortcuts) {
|
||||||
ShortcutsView()
|
ShortcutsView()
|
||||||
}
|
}
|
||||||
@@ -142,12 +142,12 @@ struct ProcessingIndicator: View {
|
|||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
Text(thinkingText)
|
Text(thinkingText)
|
||||||
.font(.system(size: 14, weight: .medium))
|
.font(.system(size: 14, weight: .medium))
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
|
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
ForEach(0..<3) { index in
|
ForEach(0..<3) { index in
|
||||||
Circle()
|
Circle()
|
||||||
.fill(Color.oaiSecondary)
|
.fill(Color.confabSecondary)
|
||||||
.frame(width: 6, height: 6)
|
.frame(width: 6, height: 6)
|
||||||
.scaleEffect(animating ? 1.0 : 0.5)
|
.scaleEffect(animating ? 1.0 : 0.5)
|
||||||
.animation(
|
.animation(
|
||||||
@@ -161,7 +161,7 @@ struct ProcessingIndicator: View {
|
|||||||
}
|
}
|
||||||
.padding(.horizontal, 16)
|
.padding(.horizontal, 16)
|
||||||
.padding(.vertical, 12)
|
.padding(.vertical, 12)
|
||||||
.background(Color.oaiSecondary.opacity(0.05))
|
.background(Color.confabSecondary.opacity(0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
animating = true
|
animating = true
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ContentView.swift
|
// ContentView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Root navigation container — NavigationSplitView with collapsible sidebar
|
// Root navigation container — NavigationSplitView with collapsible sidebar
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -134,7 +134,7 @@ struct ContentView: View {
|
|||||||
UserDefaults.standard.set(true, forKey: "hasShownIntelWarning")
|
UserDefaults.standard.set(true, forKey: "hasShownIntelWarning")
|
||||||
}
|
}
|
||||||
} message: {
|
} message: {
|
||||||
Text("oAI v2.4 is the last version to support Intel Macs and Rosetta. Starting with macOS 28, oAI will require Apple Silicon. Consider upgrading your Mac to continue receiving updates.")
|
Text("Confab (formerly oAI) v2.4 was the last version to support Intel Macs and Rosetta. Starting with macOS 28, Confab will require Apple Silicon. Consider upgrading your Mac to continue receiving updates.")
|
||||||
}
|
}
|
||||||
.alert("Software Update", isPresented: Binding(
|
.alert("Software Update", isPresented: Binding(
|
||||||
get: { updateService.manualCheckMessage != nil },
|
get: { updateService.manualCheckMessage != nil },
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// FooterView.swift
|
// FooterView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Footer bar with session summary
|
// Footer bar with session summary
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -102,7 +102,7 @@ struct FooterView: View {
|
|||||||
.background(.ultraThinMaterial)
|
.background(.ultraThinMaterial)
|
||||||
.overlay(
|
.overlay(
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(Color.oaiBorder.opacity(0.5))
|
.fill(Color.confabBorder.opacity(0.5))
|
||||||
.frame(height: 1),
|
.frame(height: 1),
|
||||||
alignment: .top
|
alignment: .top
|
||||||
)
|
)
|
||||||
@@ -153,7 +153,7 @@ struct SaveIndicator: View {
|
|||||||
.foregroundColor(color)
|
.foregroundColor(color)
|
||||||
Text(label)
|
Text(label)
|
||||||
.font(.system(size: guiSize - 2))
|
.font(.system(size: guiSize - 2))
|
||||||
.foregroundColor(isUnsaved ? .secondary : .oaiPrimary)
|
.foregroundColor(isUnsaved ? .secondary : .confabPrimary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
@@ -175,15 +175,15 @@ struct FooterItem: View {
|
|||||||
HStack(spacing: 6) {
|
HStack(spacing: 6) {
|
||||||
Image(systemName: icon)
|
Image(systemName: icon)
|
||||||
.font(.system(size: guiSize - 2))
|
.font(.system(size: guiSize - 2))
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
|
|
||||||
Text(label)
|
Text(label)
|
||||||
.font(.system(size: guiSize - 2))
|
.font(.system(size: guiSize - 2))
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
|
|
||||||
Text(value)
|
Text(value)
|
||||||
.font(.system(size: guiSize - 2, weight: .medium))
|
.font(.system(size: guiSize - 2, weight: .medium))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,5 +279,5 @@ struct UpdateBadge: View {
|
|||||||
FooterView(stats: stats, conversationName: "My Project", hasUnsavedChanges: true)
|
FooterView(stats: stats, conversationName: "My Project", hasUnsavedChanges: true)
|
||||||
FooterView(stats: stats, conversationName: "My Project", hasUnsavedChanges: false)
|
FooterView(stats: stats, conversationName: "My Project", hasUnsavedChanges: false)
|
||||||
}
|
}
|
||||||
.background(Color.oaiBackground)
|
.background(Color.confabBackground)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// HeaderView.swift
|
// HeaderView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Slim header — provider, model name, star only.
|
// Slim header — provider, model name, star only.
|
||||||
// Status pills and stats live in SidebarView and FooterView respectively.
|
// Status pills and stats live in SidebarView and FooterView respectively.
|
||||||
@@ -8,11 +8,11 @@
|
|||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -53,7 +53,7 @@ struct HeaderView: View {
|
|||||||
.background(.ultraThinMaterial)
|
.background(.ultraThinMaterial)
|
||||||
.overlay(
|
.overlay(
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(Color.oaiBorder.opacity(0.5))
|
.fill(Color.confabBorder.opacity(0.5))
|
||||||
.frame(height: 1),
|
.frame(height: 1),
|
||||||
alignment: .bottom
|
alignment: .bottom
|
||||||
)
|
)
|
||||||
@@ -73,7 +73,7 @@ struct HeaderView: View {
|
|||||||
}
|
}
|
||||||
Text(name)
|
Text(name)
|
||||||
.font(.system(size: settings.guiTextSize - 1, weight: .medium))
|
.font(.system(size: settings.guiTextSize - 1, weight: .medium))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.frame(maxWidth: 300)
|
.frame(maxWidth: 300)
|
||||||
}
|
}
|
||||||
@@ -128,29 +128,29 @@ struct HeaderView: View {
|
|||||||
HStack(spacing: 6) {
|
HStack(spacing: 6) {
|
||||||
Text(model.name)
|
Text(model.name)
|
||||||
.font(.system(size: settings.guiTextSize, weight: .medium))
|
.font(.system(size: settings.guiTextSize, weight: .medium))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
HStack(spacing: 3) {
|
HStack(spacing: 3) {
|
||||||
if model.capabilities.vision {
|
if model.capabilities.vision {
|
||||||
Image(systemName: "eye").font(.system(size: 9)).foregroundColor(.oaiSecondary)
|
Image(systemName: "eye").font(.system(size: 9)).foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
if model.capabilities.tools {
|
if model.capabilities.tools {
|
||||||
Image(systemName: "wrench").font(.system(size: 9)).foregroundColor(.oaiSecondary)
|
Image(systemName: "wrench").font(.system(size: 9)).foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
if model.capabilities.online {
|
if model.capabilities.online {
|
||||||
Image(systemName: "globe").font(.system(size: 9)).foregroundColor(.oaiSecondary)
|
Image(systemName: "globe").font(.system(size: 9)).foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
if model.capabilities.imageGeneration {
|
if model.capabilities.imageGeneration {
|
||||||
Image(systemName: "paintbrush").font(.system(size: 9)).foregroundColor(.oaiSecondary)
|
Image(systemName: "paintbrush").font(.system(size: 9)).foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Image(systemName: "chevron.down").font(.caption2).foregroundColor(.oaiSecondary)
|
Image(systemName: "chevron.down").font(.caption2).foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Text("No model selected")
|
Text("No model selected")
|
||||||
.font(.system(size: settings.guiTextSize))
|
.font(.system(size: settings.guiTextSize))
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
Image(systemName: "chevron.down").font(.caption2).foregroundColor(.oaiSecondary)
|
Image(systemName: "chevron.down").font(.caption2).foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ struct HeaderView: View {
|
|||||||
Button(action: { settings.toggleFavoriteModel(model.id) }) {
|
Button(action: { settings.toggleFavoriteModel(model.id) }) {
|
||||||
Image(systemName: isFav ? "star.fill" : "star")
|
Image(systemName: isFav ? "star.fill" : "star")
|
||||||
.font(.system(size: settings.guiTextSize - 3))
|
.font(.system(size: settings.guiTextSize - 3))
|
||||||
.foregroundColor(isFav ? .yellow : .oaiSecondary)
|
.foregroundColor(isFav ? .yellow : .confabSecondary)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.help(isFav ? "Remove from favorites" : "Add to favorites")
|
.help(isFav ? "Remove from favorites" : "Add to favorites")
|
||||||
@@ -187,7 +187,7 @@ struct StatusPill: View {
|
|||||||
.frame(width: 6, height: 6)
|
.frame(width: 6, height: 6)
|
||||||
Text(label)
|
Text(label)
|
||||||
.font(.system(size: 10, weight: .medium))
|
.font(.system(size: 10, weight: .medium))
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 6)
|
.padding(.horizontal, 6)
|
||||||
.padding(.vertical, 2)
|
.padding(.vertical, 2)
|
||||||
@@ -230,7 +230,7 @@ struct SyncStatusPill: View {
|
|||||||
.frame(width: 6, height: 6)
|
.frame(width: 6, height: 6)
|
||||||
Text(syncLabel)
|
Text(syncLabel)
|
||||||
.font(.system(size: 10, weight: .medium))
|
.font(.system(size: 10, weight: .medium))
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 6)
|
.padding(.horizontal, 6)
|
||||||
.padding(.vertical, 2)
|
.padding(.vertical, 2)
|
||||||
@@ -265,5 +265,5 @@ struct SyncStatusPill: View {
|
|||||||
)
|
)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.background(Color.oaiBackground)
|
.background(Color.confabBackground)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// InputBar.swift
|
// InputBar.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Message input bar with resizable height and online toggle
|
// Message input bar with resizable height and online toggle
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -86,7 +86,7 @@ struct InputBar: View {
|
|||||||
if text.isEmpty {
|
if text.isEmpty {
|
||||||
Text("Type a message or / for commands...")
|
Text("Type a message or / for commands...")
|
||||||
.font(.system(size: settings.inputTextSize))
|
.font(.system(size: settings.inputTextSize))
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
.padding(.top, 10)
|
.padding(.top, 10)
|
||||||
.allowsHitTesting(false)
|
.allowsHitTesting(false)
|
||||||
@@ -96,7 +96,7 @@ struct InputBar: View {
|
|||||||
NativeTextEditor(
|
NativeTextEditor(
|
||||||
text: $text,
|
text: $text,
|
||||||
font: .systemFont(ofSize: settings.inputTextSize),
|
font: .systemFont(ofSize: settings.inputTextSize),
|
||||||
textColor: NSColor(Color.oaiPrimary),
|
textColor: NSColor(Color.confabPrimary),
|
||||||
isFocused: isInputFocused,
|
isFocused: isInputFocused,
|
||||||
onReturn: {
|
onReturn: {
|
||||||
if showCommandDropdown {
|
if showCommandDropdown {
|
||||||
@@ -157,11 +157,11 @@ struct InputBar: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(height: inputHeight)
|
.frame(height: inputHeight)
|
||||||
.background(Color.oaiSurface)
|
.background(Color.confabSurface)
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
.overlay(
|
.overlay(
|
||||||
RoundedRectangle(cornerRadius: 8)
|
RoundedRectangle(cornerRadius: 8)
|
||||||
.stroke(isInputFocused ? Color.oaiAccent : Color.oaiBorder, lineWidth: 1)
|
.stroke(isInputFocused ? Color.confabAccent : Color.confabBorder, lineWidth: 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Send / stop + attach buttons
|
// Send / stop + attach buttons
|
||||||
@@ -170,7 +170,7 @@ struct InputBar: View {
|
|||||||
Button(action: pickFile) {
|
Button(action: pickFile) {
|
||||||
Image(systemName: "paperclip")
|
Image(systemName: "paperclip")
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
.foregroundColor(.oaiPrimary.opacity(0.7))
|
.foregroundColor(.confabPrimary.opacity(0.7))
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.help("Attach file")
|
.help("Attach file")
|
||||||
@@ -180,7 +180,7 @@ struct InputBar: View {
|
|||||||
Button(action: onCancel) {
|
Button(action: onCancel) {
|
||||||
Image(systemName: "stop.circle.fill")
|
Image(systemName: "stop.circle.fill")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(.oaiError.opacity(0.9))
|
.foregroundColor(.confabError.opacity(0.9))
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.help("Stop generation")
|
.help("Stop generation")
|
||||||
@@ -188,7 +188,7 @@ struct InputBar: View {
|
|||||||
Button(action: onSend) {
|
Button(action: onSend) {
|
||||||
Image(systemName: "arrow.up.circle.fill")
|
Image(systemName: "arrow.up.circle.fill")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(text.isEmpty ? .oaiPrimary.opacity(0.4) : .oaiAccent.opacity(0.9))
|
.foregroundColor(text.isEmpty ? .confabPrimary.opacity(0.4) : .confabAccent.opacity(0.9))
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.disabled(text.isEmpty)
|
.disabled(text.isEmpty)
|
||||||
@@ -198,7 +198,7 @@ struct InputBar: View {
|
|||||||
.frame(width: 40)
|
.frame(width: 40)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.oaiSurface)
|
.background(Color.confabSurface)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
isInputFocused = true
|
isInputFocused = true
|
||||||
@@ -330,22 +330,22 @@ struct CommandSuggestionsView: View {
|
|||||||
VStack(alignment: .leading, spacing: 2) {
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
Text(suggestion.command)
|
Text(suggestion.command)
|
||||||
.font(.body)
|
.font(.body)
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
Text(suggestion.description)
|
Text(suggestion.description)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.background(index == selectedIndex ? Color.oaiAccent.opacity(0.2) : Color.oaiSurface)
|
.background(index == selectedIndex ? Color.confabAccent.opacity(0.2) : Color.confabSurface)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.id(suggestion.command)
|
.id(suggestion.command)
|
||||||
|
|
||||||
if index < suggestions.count - 1 {
|
if index < suggestions.count - 1 {
|
||||||
Divider().background(Color.oaiBorder)
|
Divider().background(Color.confabBorder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -356,9 +356,9 @@ struct CommandSuggestionsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.background(Color.oaiSurface)
|
.background(Color.confabSurface)
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
.overlay(RoundedRectangle(cornerRadius: 8).stroke(Color.oaiBorder, lineWidth: 1))
|
.overlay(RoundedRectangle(cornerRadius: 8).stroke(Color.confabBorder, lineWidth: 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,5 +374,5 @@ struct CommandSuggestionsView: View {
|
|||||||
onToggleOnline: {}
|
onToggleOnline: {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.background(Color.oaiBackground)
|
.background(Color.confabBackground)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// MarkdownContentView.swift
|
// MarkdownContentView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Renders markdown content with syntax-highlighted code blocks
|
// Renders markdown content with syntax-highlighted code blocks
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -196,12 +196,12 @@ struct TableView: View {
|
|||||||
if index < data.headers.count {
|
if index < data.headers.count {
|
||||||
Text(data.headers[index].trimmingCharacters(in: .whitespaces))
|
Text(data.headers[index].trimmingCharacters(in: .whitespaces))
|
||||||
.font(.system(size: fontSize, weight: .semibold))
|
.font(.system(size: fontSize, weight: .semibold))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.frame(maxWidth: .infinity, alignment: alignmentFor(
|
.frame(maxWidth: .infinity, alignment: alignmentFor(
|
||||||
index < data.alignments.count ? data.alignments[index] : .leading
|
index < data.alignments.count ? data.alignments[index] : .leading
|
||||||
))
|
))
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.background(Color.oaiSecondary.opacity(0.1))
|
.background(Color.confabSecondary.opacity(0.1))
|
||||||
|
|
||||||
if index < data.headers.count - 1 {
|
if index < data.headers.count - 1 {
|
||||||
Divider()
|
Divider()
|
||||||
@@ -211,7 +211,7 @@ struct TableView: View {
|
|||||||
}
|
}
|
||||||
.overlay(
|
.overlay(
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.stroke(Color.oaiSecondary.opacity(0.3), lineWidth: 1)
|
.stroke(Color.confabSecondary.opacity(0.3), lineWidth: 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
@@ -224,7 +224,7 @@ struct TableView: View {
|
|||||||
|
|
||||||
Text(cellContent.trimmingCharacters(in: .whitespaces))
|
Text(cellContent.trimmingCharacters(in: .whitespaces))
|
||||||
.font(.system(size: fontSize))
|
.font(.system(size: fontSize))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.frame(maxWidth: .infinity, alignment: alignmentFor(alignment))
|
.frame(maxWidth: .infinity, alignment: alignmentFor(alignment))
|
||||||
.padding(8)
|
.padding(8)
|
||||||
|
|
||||||
@@ -233,10 +233,10 @@ struct TableView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.background(rowIndex % 2 == 0 ? Color.clear : Color.oaiSecondary.opacity(0.05))
|
.background(rowIndex % 2 == 0 ? Color.clear : Color.confabSecondary.opacity(0.05))
|
||||||
.overlay(
|
.overlay(
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.stroke(Color.oaiSecondary.opacity(0.3), lineWidth: 1)
|
.stroke(Color.confabSecondary.opacity(0.3), lineWidth: 1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ struct TableView: View {
|
|||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
.overlay(
|
.overlay(
|
||||||
RoundedRectangle(cornerRadius: 8)
|
RoundedRectangle(cornerRadius: 8)
|
||||||
.strokeBorder(Color.oaiSecondary.opacity(0.3), lineWidth: 1)
|
.strokeBorder(Color.confabSecondary.opacity(0.3), lineWidth: 1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// MessageRow.swift
|
// MessageRow.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Individual message display
|
// Individual message display
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -76,7 +76,7 @@ struct MessageRow: View {
|
|||||||
Button(action: toggleStar) {
|
Button(action: toggleStar) {
|
||||||
Image(systemName: isStarred ? "star.fill" : "star")
|
Image(systemName: isStarred ? "star.fill" : "star")
|
||||||
.font(.system(size: 11))
|
.font(.system(size: 11))
|
||||||
.foregroundColor(isStarred ? .yellow : .oaiSecondary)
|
.foregroundColor(isStarred ? .yellow : .confabSecondary)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
@@ -94,7 +94,7 @@ struct MessageRow: View {
|
|||||||
.font(.system(size: 11))
|
.font(.system(size: 11))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.foregroundColor(showCopied ? .green : .oaiSecondary)
|
.foregroundColor(showCopied ? .green : .confabSecondary)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
@@ -103,7 +103,7 @@ struct MessageRow: View {
|
|||||||
|
|
||||||
Text(message.timestamp, style: .time)
|
Text(message.timestamp, style: .time)
|
||||||
.font(.caption2)
|
.font(.caption2)
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thinking / reasoning block (collapsible)
|
// Thinking / reasoning block (collapsible)
|
||||||
@@ -146,7 +146,7 @@ struct MessageRow: View {
|
|||||||
.font(.caption)
|
.font(.caption)
|
||||||
Text(attachments[index].path)
|
Text(attachments[index].path)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ struct MessageRow: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.font(.caption2)
|
.font(.caption2)
|
||||||
.foregroundColor(.oaiSecondary)
|
.foregroundColor(.confabSecondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
@@ -400,18 +400,18 @@ struct MessageRow: View {
|
|||||||
if isErrorMessage {
|
if isErrorMessage {
|
||||||
HStack(alignment: .top, spacing: 8) {
|
HStack(alignment: .top, spacing: 8) {
|
||||||
Image(systemName: "exclamationmark.triangle.fill")
|
Image(systemName: "exclamationmark.triangle.fill")
|
||||||
.foregroundColor(.oaiError)
|
.foregroundColor(.confabError)
|
||||||
.font(.system(size: settings.dialogTextSize))
|
.font(.system(size: settings.dialogTextSize))
|
||||||
Text(message.content)
|
Text(message.content)
|
||||||
.font(.system(size: settings.dialogTextSize))
|
.font(.system(size: settings.dialogTextSize))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.textSelection(.enabled)
|
.textSelection(.enabled)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Text(message.content)
|
Text(message.content)
|
||||||
.font(.system(size: settings.dialogTextSize))
|
.font(.system(size: settings.dialogTextSize))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.textSelection(.enabled)
|
.textSelection(.enabled)
|
||||||
}
|
}
|
||||||
@@ -419,7 +419,7 @@ struct MessageRow: View {
|
|||||||
// User messages: preserve line breaks as-is (plain text, not markdown)
|
// User messages: preserve line breaks as-is (plain text, not markdown)
|
||||||
Text(message.content)
|
Text(message.content)
|
||||||
.font(.system(size: settings.dialogTextSize))
|
.font(.system(size: settings.dialogTextSize))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.lineSpacing(4)
|
.lineSpacing(4)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.textSelection(.enabled)
|
.textSelection(.enabled)
|
||||||
@@ -434,7 +434,7 @@ struct MessageRow: View {
|
|||||||
|
|
||||||
private var messageBorderColor: Color {
|
private var messageBorderColor: Color {
|
||||||
if isErrorMessage {
|
if isErrorMessage {
|
||||||
return .oaiError.opacity(0.5)
|
return .confabError.opacity(0.5)
|
||||||
}
|
}
|
||||||
return Color.messageColor(for: message.role).opacity(0.3)
|
return Color.messageColor(for: message.role).opacity(0.3)
|
||||||
}
|
}
|
||||||
@@ -571,5 +571,5 @@ struct GeneratedImagesView: View {
|
|||||||
MessageRow(message: Message.mockSystem)
|
MessageRow(message: Message.mockSystem)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.oaiBackground)
|
.background(Color.confabBackground)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// SidebarView.swift
|
// SidebarView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Collapsible sidebar: new chat, conversation list, status pills
|
// Collapsible sidebar: new chat, conversation list, status pills
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -53,7 +53,7 @@ struct SidebarView: View {
|
|||||||
Text("New Chat")
|
Text("New Chat")
|
||||||
.font(.system(size: 14, weight: .medium))
|
.font(.system(size: 14, weight: .medium))
|
||||||
}
|
}
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
@@ -63,7 +63,7 @@ struct SidebarView: View {
|
|||||||
Button(action: { createFolderPrompt() }) {
|
Button(action: { createFolderPrompt() }) {
|
||||||
Image(systemName: "folder.badge.plus")
|
Image(systemName: "folder.badge.plus")
|
||||||
.font(.system(size: 14))
|
.font(.system(size: 14))
|
||||||
.foregroundColor(.oaiPrimary)
|
.foregroundColor(.confabPrimary)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
@@ -236,7 +236,7 @@ struct SidebarView: View {
|
|||||||
}
|
}
|
||||||
.listRowBackground(
|
.listRowBackground(
|
||||||
chatViewModel.currentConversationName == conversation.name
|
chatViewModel.currentConversationName == conversation.name
|
||||||
? Color.oaiAccent.opacity(0.15)
|
? Color.confabAccent.opacity(0.15)
|
||||||
: Color.clear
|
: Color.clear
|
||||||
)
|
)
|
||||||
.draggable(conversation.id.uuidString) {
|
.draggable(conversation.id.uuidString) {
|
||||||
@@ -245,7 +245,7 @@ struct SidebarView: View {
|
|||||||
.foregroundStyle(.white)
|
.foregroundStyle(.white)
|
||||||
.padding(.horizontal, 10)
|
.padding(.horizontal, 10)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.background(Color.oaiAccent, in: RoundedRectangle(cornerRadius: 6))
|
.background(Color.confabAccent, in: RoundedRectangle(cornerRadius: 6))
|
||||||
}
|
}
|
||||||
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||||
Button(role: .destructive) {
|
Button(role: .destructive) {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// SyncStatusIndicator.swift
|
// SyncStatusIndicator.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Git sync status indicator (bottom-right corner)
|
// Git sync status indicator (bottom-right corner)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AboutView.swift
|
// AboutView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// About modal with app icon and version info
|
// About modal with app icon and version info
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -45,7 +45,7 @@ struct AboutView: View {
|
|||||||
.clipShape(RoundedRectangle(cornerRadius: 24))
|
.clipShape(RoundedRectangle(cornerRadius: 24))
|
||||||
.shadow(color: .cyan.opacity(0.3), radius: 12)
|
.shadow(color: .cyan.opacity(0.3), radius: 12)
|
||||||
|
|
||||||
Text("oAI")
|
Text("Confab")
|
||||||
.font(.system(size: 28, weight: .bold))
|
.font(.system(size: 28, weight: .bold))
|
||||||
|
|
||||||
Text("Version \(appVersion) (\(buildNumber))")
|
Text("Version \(appVersion) (\(buildNumber))")
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AgentSkillEditorSheet.swift
|
// AgentSkillEditorSheet.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Create or edit a SKILL.md-style agent skill, with optional support files
|
// Create or edit a SKILL.md-style agent skill, with optional support files
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// AgentSkillsView.swift
|
// AgentSkillsView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Modal for managing SKILL.md-style agent skills (opened via /skills command)
|
// Modal for managing SKILL.md-style agent skills (opened via /skills command)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// BashApprovalSheet.swift
|
// BashApprovalSheet.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Approval UI for AI-requested bash commands
|
// Approval UI for AI-requested bash commands
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// CombineConversationsSheet.swift
|
// CombineConversationsSheet.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Combine 2+ saved conversations into one, optionally using AI to merge content
|
// Combine 2+ saved conversations into one, optionally using AI to merge content
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ConversationListView.swift
|
// ConversationListView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Saved conversations list
|
// Saved conversations list
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -345,7 +345,7 @@ struct ConversationListView: View {
|
|||||||
}
|
}
|
||||||
.listRowBackground(
|
.listRowBackground(
|
||||||
!isSelecting && index == selectedIndex
|
!isSelecting && index == selectedIndex
|
||||||
? Color.oaiAccent.opacity(0.15)
|
? Color.confabAccent.opacity(0.15)
|
||||||
: Color.clear
|
: Color.clear
|
||||||
)
|
)
|
||||||
.id(conversation.id)
|
.id(conversation.id)
|
||||||
@@ -355,7 +355,7 @@ struct ConversationListView: View {
|
|||||||
.foregroundStyle(.white)
|
.foregroundStyle(.white)
|
||||||
.padding(.horizontal, 10)
|
.padding(.horizontal, 10)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.background(Color.oaiAccent, in: RoundedRectangle(cornerRadius: 6))
|
.background(Color.confabAccent, in: RoundedRectangle(cornerRadius: 6))
|
||||||
}
|
}
|
||||||
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||||
Button(role: .destructive) {
|
Button(role: .destructive) {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// CreditsView.swift
|
// CreditsView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Account credits and balance
|
// Account credits and balance
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// EmailLogView.swift
|
// EmailLogView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Email handler activity log viewer
|
// Email handler activity log viewer
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// HelpView.swift
|
// HelpView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Help and commands reference with expandable detail and search
|
// Help and commands reference with expandable detail and search
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// HistoryView.swift
|
// HistoryView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Command history viewer with search
|
// Command history viewer with search
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -149,7 +149,7 @@ struct HistoryView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(minWidth: 600, minHeight: 400)
|
.frame(minWidth: 600, minHeight: 400)
|
||||||
.background(Color.oaiBackground)
|
.background(Color.confabBackground)
|
||||||
.task {
|
.task {
|
||||||
loadHistory()
|
loadHistory()
|
||||||
isListFocused = true
|
isListFocused = true
|
||||||
@@ -191,7 +191,7 @@ struct HistoryRow: View {
|
|||||||
}
|
}
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.padding(.horizontal, 4)
|
.padding(.horizontal, 4)
|
||||||
.listRowBackground(isSelected ? Color.oaiAccent.opacity(0.2) : Color.clear)
|
.listRowBackground(isSelected ? Color.confabAccent.opacity(0.2) : Color.clear)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// JarvisView.swift
|
// JarvisView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Main modal for managing Jarvis (oAI-Web) agents and usage.
|
// Main modal for managing Jarvis (oAI-Web) agents and usage.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ModelInfoView.swift
|
// ModelInfoView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Rich model information modal
|
// Rich model information modal
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -69,6 +69,9 @@ struct ModelInfoView: View {
|
|||||||
if let provider = model.topProvider {
|
if let provider = model.topProvider {
|
||||||
infoRow("Provider", provider)
|
infoRow("Provider", provider)
|
||||||
}
|
}
|
||||||
|
if let releaseDate = model.releaseDate {
|
||||||
|
infoRow("Released", releaseDate.formatted(date: .abbreviated, time: .omitted))
|
||||||
|
}
|
||||||
if let desc = model.description {
|
if let desc = model.description {
|
||||||
VStack(alignment: .leading, spacing: 6) {
|
VStack(alignment: .leading, spacing: 6) {
|
||||||
Text("Description")
|
Text("Description")
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ModelSelectorView.swift
|
// ModelSelectorView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Model selection screen
|
// Model selection screen
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// PersonalDataApprovalSheet.swift
|
// PersonalDataApprovalSheet.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Approval UI for AI-requested Calendar/Reminders write actions
|
// Approval UI for AI-requested Calendar/Reminders write actions
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// SettingsView.swift
|
// SettingsView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Settings and configuration screen
|
// Settings and configuration screen
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -514,7 +514,7 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Text("Controls which messages are written to ~/Library/Logs/oAI.log")
|
Text("Controls which messages are written to ~/Library/Logs/Confab.log")
|
||||||
.font(.system(size: 13))
|
.font(.system(size: 13))
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
@@ -1605,7 +1605,7 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
|
|||||||
.font(.system(size: 13))
|
.font(.system(size: 13))
|
||||||
Text("• Add public key to your git provider")
|
Text("• Add public key to your git provider")
|
||||||
.font(.system(size: 13))
|
.font(.system(size: 13))
|
||||||
Text("• No credentials needed in oAI")
|
Text("• No credentials needed in Confab")
|
||||||
.font(.system(size: 13))
|
.font(.system(size: 13))
|
||||||
}
|
}
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
@@ -1822,7 +1822,7 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
|
|||||||
.font(.system(size: settingsService.guiTextSize))
|
.font(.system(size: settingsService.guiTextSize))
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
Text("Example: oai-bot-x7k2m9p3@gmail.com")
|
Text("Example: confab-bot-x7k2m9p3@gmail.com")
|
||||||
.font(.system(size: settingsService.guiTextSize - 1, design: .monospaced))
|
.font(.system(size: settingsService.guiTextSize - 1, design: .monospaced))
|
||||||
.foregroundColor(.blue)
|
.foregroundColor(.blue)
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
@@ -2483,7 +2483,7 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
|
|||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
Text("Jarvis is oAI-Web, a self-hosted companion server that lets oAI sync and connect remotely.")
|
Text("Jarvis is oAI-Web, a self-hosted companion server that lets Confab sync and connect remotely.")
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
Link("→ Jarvis / oAI-Web on Gitea", destination: URL(string: "https://gitlab.pm/rune/oai-web")!)
|
Link("→ Jarvis / oAI-Web on Gitea", destination: URL(string: "https://gitlab.pm/rune/oai-web")!)
|
||||||
}
|
}
|
||||||
@@ -2585,7 +2585,7 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
|
|||||||
.frame(width: 220)
|
.frame(width: 220)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Text("When enabled, oAI backs up automatically in the background (checked at launch and hourly while running) — no need to press \"Back Up Now\" yourself.")
|
Text("When enabled, Confab backs up automatically in the background (checked at launch and hourly while running) — no need to press \"Back Up Now\" yourself.")
|
||||||
.font(.system(size: 13))
|
.font(.system(size: 13))
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
@@ -2706,7 +2706,7 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
|
|||||||
defer { url.stopAccessingSecurityScopedResource() }
|
defer { url.stopAccessingSecurityScopedResource() }
|
||||||
try await backupService.importSettings(from: url)
|
try await backupService.importSettings(from: url)
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
backupMessage = "Settings restored. Re-enter your API keys to resume using oAI."
|
backupMessage = "Settings restored. Re-enter your API keys to resume using Confab."
|
||||||
backupMessageIsError = false
|
backupMessageIsError = false
|
||||||
isImporting = false
|
isImporting = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ShortcutEditorSheet.swift
|
// ShortcutEditorSheet.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Create or edit a user-defined shortcut (prompt template)
|
// Create or edit a user-defined shortcut (prompt template)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// ShortcutsView.swift
|
// ShortcutsView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Modal for managing user-defined shortcuts (opened via /shortcuts command)
|
// Modal for managing user-defined shortcuts (opened via /shortcuts command)
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// StatsView.swift
|
// StatsView.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Session statistics screen
|
// Session statistics screen
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -8,31 +8,31 @@
|
|||||||
"da" : {
|
"da" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "new",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nb" : {
|
"nb" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sv" : {
|
"sv" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "oAI"
|
"value" : "Confab"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "new",
|
||||||
"value" : "oAI can read and create calendar events when you ask it to, if you enable Calendar access in Settings."
|
"value" : "Confab can read and create calendar events when you ask it to, if you enable Calendar access in Settings."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "new",
|
||||||
"value" : "oAI can search your contacts when you ask it to, if you enable Contacts access in Settings."
|
"value" : "Confab can search your contacts when you ask it to, if you enable Contacts access in Settings."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "new",
|
||||||
"value" : "oAI can use your current location to answer questions, if you enable Location & Maps access in Settings."
|
"value" : "Confab can use your current location to answer questions, if you enable Location & Maps access in Settings."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "new",
|
||||||
"value" : "oAI can read and create reminders when you ask it to, if you enable Reminders access in Settings."
|
"value" : "Confab can read and create reminders when you ask it to, if you enable Reminders access in Settings."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// oAIApp.swift
|
// oAIApp.swift
|
||||||
// oAI
|
// Confab
|
||||||
//
|
//
|
||||||
// Main app entry point
|
// Main app entry point
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||||
// Copyright (C) 2026 Rune Olsen
|
// Copyright (C) 2026 Rune Olsen
|
||||||
//
|
//
|
||||||
// This file is part of oAI.
|
// This file is part of Confab.
|
||||||
//
|
//
|
||||||
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
|
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||||
// You may use, study, modify, and share it for any noncommercial
|
// You may use, study, modify, and share it for any noncommercial
|
||||||
// purpose. Commercial use — including selling oAI or any part of
|
// purpose. Commercial use — including selling Confab or any part of
|
||||||
// it, standalone or bundled into another product or service —
|
// it, standalone or bundled into another product or service —
|
||||||
// requires a separate commercial license from the copyright holder.
|
// requires a separate commercial license from the copyright holder.
|
||||||
//
|
//
|
||||||
@@ -117,7 +117,7 @@ struct oAIApp: App {
|
|||||||
.commands {
|
.commands {
|
||||||
// ── Apple menu ────────────────────────────────────────────────
|
// ── Apple menu ────────────────────────────────────────────────
|
||||||
CommandGroup(replacing: .appInfo) {
|
CommandGroup(replacing: .appInfo) {
|
||||||
Button("About oAI") { showAbout = true }
|
Button("About Confab") { showAbout = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandGroup(replacing: .appSettings) {
|
CommandGroup(replacing: .appSettings) {
|
||||||
@@ -206,7 +206,7 @@ struct oAIApp: App {
|
|||||||
|
|
||||||
// ── Help menu ─────────────────────────────────────────────────
|
// ── Help menu ─────────────────────────────────────────────────
|
||||||
CommandGroup(replacing: .help) {
|
CommandGroup(replacing: .help) {
|
||||||
Button("oAI Help") { openHelp() }
|
Button("Confab Help") { openHelp() }
|
||||||
.keyboardShortcut("?", modifiers: .command)
|
.keyboardShortcut("?", modifiers: .command)
|
||||||
Divider()
|
Divider()
|
||||||
Button(UpdateCheckService.shared.isCheckingManually ? "Checking…" : "Check for Updates…") {
|
Button(UpdateCheckService.shared.isCheckingManually ? "Checking…" : "Check for Updates…") {
|
||||||
@@ -224,7 +224,7 @@ struct oAIApp: App {
|
|||||||
// through NSHelpManager/Help Viewer — see CLAUDE.md's macOS 27 beta note for why
|
// through NSHelpManager/Help Viewer — see CLAUDE.md's macOS 27 beta note for why
|
||||||
// (Apple's Tips.app replacement for Help Viewer can't resolve anchors on this beta).
|
// (Apple's Tips.app replacement for Help Viewer can't resolve anchors on this beta).
|
||||||
// Revisit once macOS 27 reaches RC.
|
// Revisit once macOS 27 reaches RC.
|
||||||
if let helpBookURL = Bundle.main.url(forResource: "oAI.help", withExtension: nil) {
|
if let helpBookURL = Bundle.main.url(forResource: "Confab.help", withExtension: nil) {
|
||||||
NSWorkspace.shared.open(helpBookURL.appendingPathComponent("Contents/Resources/en.lproj/index.html"))
|
NSWorkspace.shared.open(helpBookURL.appendingPathComponent("Contents/Resources/en.lproj/index.html"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import Testing
|
import Testing
|
||||||
import Foundation
|
import Foundation
|
||||||
@testable import oAI
|
@testable import Confab
|
||||||
|
|
||||||
@Suite("ChatResponse / Usage decoding")
|
@Suite("ChatResponse / Usage decoding")
|
||||||
struct AIProviderTests {
|
struct AIProviderTests {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user