-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathllms.txt
More file actions
108 lines (73 loc) · 12.1 KB
/
Copy pathllms.txt
File metadata and controls
108 lines (73 loc) · 12.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# CodingPlanKit
> Umbrella Swift package for iOS 17+ / macOS 14+ apps that work with AI coding-plan accounts. The user signs in with OAuth 2.0 + PKCE, credentials are persisted in the system Keychain, and plan-bound API clients let the app charge the user's plan instead of an API key — no per-token billing. The package is structured as an umbrella with one product per concern (auth, codex, more later).
The repository ships **two SPM products** from one package (`CodingPlanKit`):
- `CodingPlanAuth` — pure auth (OAuth + PKCE + Keychain). Depends only on [SwiftWebServer](https://github.com/atom2ueki/SwiftWebServer).
- `CodingPlanCodex` — plan-bound API clients for the ChatGPT backend (Codex chat with text + image streaming, usage / rate limits, cloud tasks, environments, models, ARC safety monitor). Depends on `CodingPlanAuth`.
Adopters pick either or both. The split is deliberate: a consumer who only needs OAuth shouldn't have to take the API plumbing along.
Architecture is **Hexagonal / Ports & Adapters + Strategy**. Domain protocols live in `Sources/CodingPlanAuth/Core/` (`AuthProvider`, `LoginSession`, `TokenStorage`, `HTTPClient`); concrete adapters live in `Infrastructure/` (HTTP, OAuth, Keychain, callback server) and `Providers/` (OpenAI today). `AuthService` is the actor-based registry that keys `AuthProvider` strategies by id and orchestrates login/refresh/logout. `OAuth2PKCEFlow` is a reusable engine that handles PKCE generation, the local callback server, the authorization URL, the auth-code exchange, and token refresh — so a new provider is essentially `OAuthConfig` + an `OAuth2TokenResponseParser` conformance.
Swift 6 strict concurrency is enabled; `ExistentialAny` and `InferIsolatedConformances` are turned on as upcoming features.
## Auth core (`CodingPlanAuth`)
- [Sources/CodingPlanAuth/Core/AuthProvider.swift](./Sources/CodingPlanAuth/Core/AuthProvider.swift): `AuthProvider` and `LoginSession` protocols — every provider's contract.
- [Sources/CodingPlanAuth/Core/Credentials.swift](./Sources/CodingPlanAuth/Core/Credentials.swift): `Credentials` value type holding access/refresh/id tokens plus account metadata pulled from JWT claims.
- [Sources/CodingPlanAuth/Core/TokenStorage.swift](./Sources/CodingPlanAuth/Core/TokenStorage.swift): `TokenStorage` protocol — pluggable persistence.
- [Sources/CodingPlanAuth/Core/TokenType.swift](./Sources/CodingPlanAuth/Core/TokenType.swift): `TokenType` extensible string-typed value (`.bearer`).
- [Sources/CodingPlanAuth/Core/AuthError.swift](./Sources/CodingPlanAuth/Core/AuthError.swift): `AuthError` typed errors with `LocalizedError` conformance; `tokenExchangeFailed(statusCode:message:)` carries the HTTP status.
- [Sources/CodingPlanAuth/Application/AuthService.swift](./Sources/CodingPlanAuth/Application/AuthService.swift): the actor registry. Registers providers, refreshes tokens transparently, persists via the injected `TokenStorage`.
## Presentation (SwiftUI / AppKit)
- [Sources/CodingPlanAuth/Presentation/AuthState.swift](./Sources/CodingPlanAuth/Presentation/AuthState.swift): `@Observable @MainActor` view-model glue scoped to one provider id.
- [Sources/CodingPlanAuth/Presentation/BrowserAuthSession.swift](./Sources/CodingPlanAuth/Presentation/BrowserAuthSession.swift): `ASWebAuthenticationSession` wrapper with `async`/`await` semantics and a custom-scheme callback path.
## OAuth 2.0 + PKCE engine
- [Sources/CodingPlanAuth/Infrastructure/OAuth/OAuth2PKCEFlow.swift](./Sources/CodingPlanAuth/Infrastructure/OAuth/OAuth2PKCEFlow.swift): the reusable flow — `beginLogin()` and `refresh(credentials:)`. Switchable refresh body encoding (`.formURLEncoded` or `.json` for OpenAI).
- [Sources/CodingPlanAuth/Infrastructure/OAuth/OAuth2LoginSession.swift](./Sources/CodingPlanAuth/Infrastructure/OAuth/OAuth2LoginSession.swift): the generic `LoginSession` actor returned by the engine.
- [Sources/CodingPlanAuth/Infrastructure/OAuth/OAuth2TokenResponseParser.swift](./Sources/CodingPlanAuth/Infrastructure/OAuth/OAuth2TokenResponseParser.swift): protocol providers conform to for their JWT claim shape.
- [Sources/CodingPlanAuth/Infrastructure/OAuth/OAuthConfig.swift](./Sources/CodingPlanAuth/Infrastructure/OAuth/OAuthConfig.swift): provider-agnostic OAuth endpoint + scope config.
- [Sources/CodingPlanAuth/Infrastructure/OAuth/PKCE.swift](./Sources/CodingPlanAuth/Infrastructure/OAuth/PKCE.swift): S256 PKCE generator.
- [Sources/CodingPlanAuth/Infrastructure/OAuth/OAuth2Helpers.swift](./Sources/CodingPlanAuth/Infrastructure/OAuth/OAuth2Helpers.swift): `randomState`, `formURLEncoded`.
- [Sources/CodingPlanAuth/Infrastructure/Server/LocalCallbackServer.swift](./Sources/CodingPlanAuth/Infrastructure/Server/LocalCallbackServer.swift): localhost HTTP server that intercepts the OAuth redirect.
## HTTP and storage
- [Sources/CodingPlanAuth/Infrastructure/HTTP/HTTPClient.swift](./Sources/CodingPlanAuth/Infrastructure/HTTP/HTTPClient.swift): `HTTPClient` protocol + `URLSessionHTTPClient` + `HTTPMethod` / `HTTPRequest` / `HTTPResponse`. Buffered only — streaming lives in `CodingPlanCodex` directly on `URLSession.bytes(for:)`.
- [Sources/CodingPlanAuth/Infrastructure/Storage/KeychainTokenStorage.swift](./Sources/CodingPlanAuth/Infrastructure/Storage/KeychainTokenStorage.swift): default `TokenStorage` adapter. `init(servicePrefix:accessGroup:)` is throwing — defaults service prefix to `Bundle.main.bundleIdentifier`, throws `AuthError.storageError` when both `servicePrefix` and the bundle id are nil so CLI / test contexts can't silently end up sharing a global keychain service name. Optional `accessGroup:` parameter for sharing credentials across an app + extension via Keychain Access Group.
## OpenAI provider (auth)
- [Sources/CodingPlanAuth/Providers/OpenAI/Auth/OpenAIAuthProvider.swift](./Sources/CodingPlanAuth/Providers/OpenAI/Auth/OpenAIAuthProvider.swift): ~50-line adapter wrapping `OAuth2PKCEFlow`.
- [Sources/CodingPlanAuth/Providers/OpenAI/Auth/OpenAIOAuthConfig.swift](./Sources/CodingPlanAuth/Providers/OpenAI/Auth/OpenAIOAuthConfig.swift): client id, endpoints, scopes matching the official Codex CLI flow.
- [Sources/CodingPlanAuth/Providers/OpenAI/Auth/OpenAITokenResponseParser.swift](./Sources/CodingPlanAuth/Providers/OpenAI/Auth/OpenAITokenResponseParser.swift): parses `chatgpt_account_id`, `chatgpt_plan_type`, and email out of the access / id token JWT claims.
## Plan-bound API clients (`CodingPlanCodex`)
### Codex chat (text + multi-modal)
- [Sources/CodingPlanCodex/Clients/OpenAICodexClient.swift](./Sources/CodingPlanCodex/Clients/OpenAICodexClient.swift): three response APIs against `/codex/responses`:
- `createTextResponse(prompt:instructions:model:credentials:)` — buffered `OpenAICodexResponse`.
- `streamTextResponse(prompt:instructions:model:credentials:)` — `AsyncThrowingStream<String>` of SSE text deltas via `URLSession.bytes(for:)`.
- `streamResponse(prompt:instructions:model:credentials:tools:)` — `AsyncThrowingStream<CodexStreamPart>` covering text deltas plus the `image_generation` tool's lifecycle events (started / generating / keepalive / partial / completed).
Plus `compactResponse(body:credentials:)` and `summarizeMemories(body:credentials:)` for the agent loop.
- [Sources/CodingPlanCodex/Core/CodexStreamPart.swift](./Sources/CodingPlanCodex/Core/CodexStreamPart.swift): `CodexStreamPart` (`.textDelta` / `.imageEvent`), `CodexImageEvent`, and `CodexImage` (decoded PNG bytes).
- [Sources/CodingPlanCodex/Core/CodexTool.swift](./Sources/CodingPlanCodex/Core/CodexTool.swift): `CodexTool.imageGeneration(outputFormat:partialImages:)` and `.imageGenerationPNG` convenience.
### Usage / billing
- [Sources/CodingPlanCodex/Clients/OpenAICodexUsageClient.swift](./Sources/CodingPlanCodex/Clients/OpenAICodexUsageClient.swift): `fetchRateLimits(credentials:)` returns the plan's primary + secondary rolling windows and credit balance (`CodexRateLimitsResponse`). Also `sendAddCreditsNudgeEmail(creditType:credentials:)` for the "low credits" / "usage limit reached" reminder email.
### Cloud tasks + environments + models + safety
- [Sources/CodingPlanCodex/Clients/OpenAICodexEnvironmentsClient.swift](./Sources/CodingPlanCodex/Clients/OpenAICodexEnvironmentsClient.swift): `listEnvironments(...)` (all and per-repo) and `fetchConfigRequirements(...)` for the workspace-managed setup file.
- [Sources/CodingPlanCodex/Clients/OpenAICodexModelsClient.swift](./Sources/CodingPlanCodex/Clients/OpenAICodexModelsClient.swift): `listModels(clientVersion:credentials:)` against `/codex/models`. The backend gates by SemVer client version — pass a recent Codex CLI version (~`0.150.0`), not the host app's version.
- [Sources/CodingPlanCodex/Clients/OpenAICodexTasksClient.swift](./Sources/CodingPlanCodex/Clients/OpenAICodexTasksClient.swift): `listTasks` (paginated), `getTask`, `getSiblingTurns`, `createTask`. Rich shapes are passed through as `JSONValue`.
- [Sources/CodingPlanCodex/Clients/OpenAICodexSafetyClient.swift](./Sources/CodingPlanCodex/Clients/OpenAICodexSafetyClient.swift): ARC monitor `evaluate(body:auth:)`. `auth` is dual-mode — plan credentials or a static `CODEX_ARC_MONITOR_TOKEN` Bearer.
### Shared
- [Sources/CodingPlanCodex/Clients/OpenAIBackend.swift](./Sources/CodingPlanCodex/Clients/OpenAIBackend.swift): shared `chatgpt.com/backend-api` base URL + `codex_cli_rs` originator constants.
- [Sources/CodingPlanCodex/Core/CodexError.swift](./Sources/CodingPlanCodex/Core/CodexError.swift): structured errors: `.missingAccountId`, `.backendError(statusCode: Int?, message: String)` (status nil for SSE-event failures with HTTP 200), `.invalidResponse`.
- [Sources/CodingPlanCodex/Core/JSONValue.swift](./Sources/CodingPlanCodex/Core/JSONValue.swift): `Sendable + Codable + Equatable` JSON passthrough used by the deeper / volatile endpoint shapes (`compactResponse`, tasks, safety body). Carries a `decode<T: Decodable>` convenience for callers who want to project to their own model.
## Tests
- [Tests/CodingPlanAuthTests/](./Tests/CodingPlanAuthTests): unit tests for the OAuth flow, PKCE, callback server (real ports), token storage, OpenAI auth provider. `MockHTTPClient` injects buffered HTTP responses.
- [Tests/CodingPlanCodexTests/](./Tests/CodingPlanCodexTests): tests for every Codex client (chat, usage, environments, models, tasks, safety, compact / memories nudge).
## Build, packaging, CI
- [Package.swift](./Package.swift): `swift-tools-version: 6.1`, two products, two test targets, `ExistentialAny` and `InferIsolatedConformances` upcoming features enabled.
- [.github/workflows/swift.yml](./.github/workflows/swift.yml): macOS SwiftPM build (`-warnings-as-errors`) + parallel tests, iOS Simulator build matrix for both products, DocC archive build, SwiftPM cache, concurrency cancellation, pinned Xcode.
- [.github/dependabot.yml](./.github/dependabot.yml): weekly SwiftPM + GitHub Actions update PRs.
## Adding a new provider
The auth side of a new provider (Anthropic, Google, etc.) requires three small pieces and no changes to `Core/` or the registry:
1. A `XxxOAuthConfig` static factory returning an `OAuthConfig` (client id, endpoints, scopes).
2. A `XxxTokenResponseParser: OAuth2TokenResponseParser` that parses the provider's JWT claim shape into `Credentials`.
3. A thin `XxxAuthProvider: AuthProvider` actor that constructs an `OAuth2PKCEFlow` with those two and delegates `beginLogin()` / `refresh(credentials:)` to it.
Plan-bound API clients (the analog of `CodingPlanCodex` for that provider) are a separate concern and should ship in their own SPM target / product so adopters who only want auth don't take them along.
## Optional
- [README.md](./README.md): user-facing overview, install snippet, SwiftUI quick start, skill installation step.
- [CodingPlanAuth DocC catalog](./Sources/CodingPlanAuth/Documentation.docc/CodingPlanAuth.md)
- [CodingPlanCodex DocC catalog](./Sources/CodingPlanCodex/Documentation.docc/CodingPlanCodex.md)
- [skills/coding-plan-kit/SKILL.md](./skills/coding-plan-kit/SKILL.md): a Claude Code skill so adopters' code agents can integrate the SDK without reading the source.
- [.claude-plugin/plugin.json](./.claude-plugin/plugin.json) and [.claude-plugin/marketplace.json](./.claude-plugin/marketplace.json): plugin manifest + marketplace entry for the same skill.
- [LICENSE](./LICENSE): MIT.