Skip to content

Commit f995b90

Browse files
committed
add(ci): github actions, mintfile, and makefile with mint run
1 parent 8bb0ed2 commit f995b90

5 files changed

Lines changed: 117 additions & 9 deletions

File tree

.github/workflows/ci.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths-ignore: ['**.md']
7+
pull_request:
8+
paths-ignore: ['**.md']
9+
10+
permissions:
11+
contents: read
12+
13+
concurrency:
14+
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
lint:
19+
runs-on: macos-26
20+
timeout-minutes: 20
21+
steps:
22+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
23+
with:
24+
persist-credentials: false
25+
- name: Install Mint
26+
run: brew install mint
27+
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
28+
with:
29+
path: ~/.mint
30+
key: mint-${{ hashFiles('Mintfile') }}
31+
restore-keys: mint-
32+
- name: Bootstrap tools
33+
run: mint bootstrap
34+
- name: SwiftFormat
35+
run: mint run swiftformat --lint .
36+
- name: SwiftLint
37+
run: mint run swiftlint --strict
38+
39+
test-macos:
40+
runs-on: macos-26
41+
timeout-minutes: 30
42+
steps:
43+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
44+
with:
45+
persist-credentials: false
46+
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
47+
with:
48+
path: .build
49+
key: macos-spm-${{ hashFiles('Package.resolved', 'Package.swift') }}
50+
restore-keys: macos-spm-
51+
- name: Run tests
52+
run: swift test --parallel -Xswiftc -warnings-as-errors
53+
54+
check:
55+
if: always()
56+
needs: [lint, test-macos]
57+
runs-on: ubuntu-latest
58+
timeout-minutes: 5
59+
steps:
60+
- name: Verify all jobs passed
61+
run: |
62+
if [[ "${{ needs.lint.result }}" != "success" || \
63+
"${{ needs.test-macos.result }}" != "success" ]]; then
64+
echo "Required jobs failed:"
65+
echo " lint: ${{ needs.lint.result }}"
66+
echo " test-macos: ${{ needs.test-macos.result }}"
67+
exit 1
68+
fi

Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
.PHONY: build test lint format check clean
1+
.PHONY: build test lint format check clean bootstrap
2+
3+
bootstrap:
4+
brew install mint
5+
mint bootstrap
26

37
build:
48
swift build
@@ -7,10 +11,10 @@ test:
711
swift test
812

913
lint:
10-
swiftlint
14+
mint run swiftlint --strict
1115

1216
format:
13-
swiftformat .
17+
mint run swiftformat .
1418

1519
check: format lint test
1620

Mintfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
nicklockwood/SwiftFormat@0.60.1
2+
realm/SwiftLint@0.63.0

README.md

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
- [Per-Request Customization](#per-request-customization)
5353
- [LLM Providers](#llm-providers)
5454
- [Anthropic Messages API](#anthropic-messages-api)
55+
- [Google Gemini](#google-gemini)
5556
- [OpenAI Responses API](#openai-responses-api)
5657
- [ChatGPT Subscription (OAuth)](#chatgpt-subscription-oauth)
5758
- [Proxy Mode](#proxy-mode)
@@ -459,10 +460,10 @@ let client = OpenAIClient(
459460
reasoningConfig: .high
460461
)
461462

462-
// Via OpenAI Responses API (native reasoning with GPT-5.2)
463+
// Via OpenAI Responses API (native reasoning with GPT-5.4)
463464
let client = ResponsesAPIClient(
464465
apiKey: apiKey,
465-
model: "gpt-5.2",
466+
model: "gpt-5.4",
466467
baseURL: ResponsesAPIClient.openAIBaseURL,
467468
reasoningConfig: .medium
468469
)
@@ -1303,14 +1304,31 @@ The header closure is evaluated per request, enabling dynamic values.
13031304

13041305
</details>
13051306

1307+
### Google Gemini
1308+
1309+
`GeminiClient` speaks the [Gemini REST API](https://ai.google.dev/api/generate-content) natively — thinking, tool calling, structured output, and streaming.
1310+
1311+
```swift
1312+
let client = GeminiClient(
1313+
apiKey: ProcessInfo.processInfo.environment["GEMINI_API_KEY"]!,
1314+
model: "gemini-3.1-pro-preview",
1315+
reasoningConfig: .high
1316+
)
1317+
1318+
let agent = Agent<EmptyContext>(client: client, tools: [myTool])
1319+
let result = try await agent.run(userMessage: "Analyze this data", context: EmptyContext())
1320+
```
1321+
1322+
Works with any Gemini model — 2.5 Flash, 2.5 Pro, 3 Flash, 3.1 Pro, 3.1 Flash-Lite, and the `customtools` variant. Thinking budget and effort levels map to Gemini's native `thinkingConfig`.
1323+
13061324
### OpenAI Responses API
13071325

13081326
`ResponsesAPIClient` speaks OpenAI's [Responses API](https://platform.openai.com/docs/api-reference/responses) — a newer endpoint with native support for reasoning models, server-side conversation state, and structured tool calling.
13091327

13101328
```swift
13111329
let client = ResponsesAPIClient(
13121330
apiKey: ProcessInfo.processInfo.environment["OPENAI_API_KEY"]!,
1313-
model: "gpt-5.2",
1331+
model: "gpt-5.4",
13141332
baseURL: ResponsesAPIClient.openAIBaseURL,
13151333
reasoningConfig: .medium
13161334
)
@@ -1341,7 +1359,7 @@ let auth = try JSONDecoder().decode(CodexAuth.self, from: authData)
13411359

13421360
// 2. Create client pointing at ChatGPT backend
13431361
let client = ResponsesAPIClient(
1344-
model: "gpt-5.2",
1362+
model: "gpt-5.4",
13451363
maxOutputTokens: nil, // not supported on this endpoint
13461364
baseURL: ResponsesAPIClient.chatGPTBaseURL,
13471365
additionalHeaders: {
@@ -1369,7 +1387,7 @@ The ChatGPT backend enforces specific constraints:
13691387
| `max_output_tokens` | Not supported — set `maxOutputTokens: nil` |
13701388
| `instructions` | Required — always provide a system prompt |
13711389

1372-
Reasoning models (GPT-5.2, GPT-5.2-codex) work fully, including interleaved thinking with opaque reasoning block echo-back across tool-calling turns.
1390+
Reasoning models (GPT-5.4, GPT-5.3-Codex) work fully, including interleaved thinking with opaque reasoning block echo-back across tool-calling turns.
13731391

13741392
### Proxy Mode
13751393

@@ -1472,8 +1490,9 @@ The client bridges `AnyTool` definitions to Apple's `Tool` protocol at runtime v
14721490
|------|-------------|
14731491
| `LLMClient` | Protocol for LLM implementations |
14741492
| `AnthropicClient` | Anthropic Messages API client (Claude Sonnet, Opus, Haiku) |
1493+
| `GeminiClient` | Google Gemini API client (2.5 Flash/Pro, 3 Flash, 3.1 Pro/Flash-Lite) |
14751494
| `OpenAIClient` | Chat Completions client (OpenAI, OpenRouter, Groq, etc.) |
1476-
| `ResponsesAPIClient` | OpenAI Responses API client (GPT-5.2, GPT-5.2-codex) |
1495+
| `ResponsesAPIClient` | OpenAI Responses API client (GPT-5.4, GPT-5.3-Codex) |
14771496
| `MLXClient` | On-device inference via MLX on Apple Silicon (Qwen 3.5, Liquid LFM2.5, etc.) |
14781497
| `FoundationModelsClient` | On-device inference via Apple Foundation Models (iOS 26+ / macOS 26+) |
14791498
| `ThinkTagParser` | Streaming `<think>` tag parser with configurable delimiters |

Tests/.swiftlint.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
parent_config: ../.swiftlint.yml
2+
3+
disabled_rules:
4+
- trailing_comma
5+
- function_default_parameter_at_end
6+
- no_empty_block
7+
- identical_operands
8+
9+
file_length:
10+
warning: 1000
11+
error: 1500
12+
13+
type_body_length:
14+
warning: 400
15+
error: 600

0 commit comments

Comments
 (0)