Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. This change

## [Unreleased]

### Changed (upstream PR #554 sync)
- **BREAKING**: `:on-permission-request` is now **required** when calling `create-session`, `resume-session`, `<create-session`, and `<resume-session`. Calls without a handler throw `ExceptionInfo` with a descriptive message. This matches upstream Node.js SDK where `onPermissionRequest` is required in `SessionConfig` and `ResumeSessionConfig` (upstream PR #554).
- `create-session` and `<create-session` no longer accept a 0-arity (no config) form — a config map with `:on-permission-request` must always be provided.
- `resume-session` and `<resume-session` no longer accept a 2-arity (no config) form — a config map with `:on-permission-request` must always be provided.
- All examples, tests, and documentation updated to always pass `:on-permission-request`.

### Added (upstream PR #555 sync)
- `:custom-tool` permission kind — `::permission-kind` spec now includes `:custom-tool`, matching the upstream `PermissionRequest.kind` union type. Permission handlers will receive `{:permission-kind :custom-tool ...}` for SDK-registered custom tool invocations (upstream PR #555).

### Added (upstream PR #544 sync)
- `:copilot/session.task_complete` event type added to `::event-type` spec (from upstream generated session event types).

### Added (documentation)
- Microsoft Foundry Local BYOK provider guide in `doc/auth/byok.md`: quick start example, installation instructions, and connection troubleshooting (upstream PR #461).

Expand Down
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ The simplest way to use the SDK is with the `query` helper:
;; => "4"

;; With model selection
(h/query "Explain monads in one sentence" :session {:model "claude-sonnet-4.5"})
(h/query "Explain monads in one sentence" :session {:on-permission-request copilot/approve-all :model "claude-sonnet-4.5"})

;; With a system prompt
(h/query "What is Clojure?" :session {:system-prompt "You are a helpful assistant. Be concise."})
(h/query "What is Clojure?" :session {:on-permission-request copilot/approve-all :system-prompt "You are a helpful assistant. Be concise."})
```

### More Control
Expand All @@ -62,7 +62,8 @@ For multi-turn conversations, pass a session instance to `query`:
```clojure
(require '[github.copilot-sdk :as copilot])

(copilot/with-client-session [session {:model "claude-haiku-4.5"}]
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "claude-haiku-4.5"}]
;; Session maintains context between queries
(println (h/query "What is the capital of France?" :session session))
(println (h/query "What is its population?" :session session)))
Expand All @@ -71,7 +72,8 @@ For multi-turn conversations, pass a session instance to `query`:
Or use the full API for maximum flexibility:

```clojure
(copilot/with-client-session [session {:model "claude-haiku-4.5"}]
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "claude-haiku-4.5"}]
(println (-> (copilot/send-and-wait! session {:prompt "What is the capital of France?"})
(get-in [:data :content]))))
```
Expand All @@ -86,7 +88,7 @@ Use `<send!` with core.async for non-blocking operations:

(copilot/with-client [client {}]
;; Launch multiple requests in parallel
(let [sessions (repeatedly 3 #(copilot/create-session client {}))
(let [sessions (repeatedly 3 #(copilot/create-session client {:on-permission-request copilot/approve-all}))
channels (map #(copilot/<send! %1 {:prompt %2})
sessions
["Capital of France?" "Capital of Japan?" "Capital of Brazil?"])]
Expand Down Expand Up @@ -226,7 +228,8 @@ await client.stop();
(str "Hello, " name "!"))}))

(def session (copilot/create-session client
{:model "claude-haiku-4.5"
{:on-permission-request copilot/approve-all
:model "claude-haiku-4.5"
:tools [greet-tool]}))

(let [ch (chan 100)]
Expand Down
24 changes: 15 additions & 9 deletions doc/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ For more control, use the explicit client/session API:
```clojure
(require '[github.copilot-sdk :as copilot])

(copilot/with-client-session [session {:model "gpt-5.2"}]
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "gpt-5.2"}]
(let [response (copilot/send-and-wait! session {:prompt "What is 2 + 2?"})]
(println (get-in response [:data :content]))))
```
Expand Down Expand Up @@ -91,7 +92,7 @@ Right now, you wait for the complete response before seeing anything. Let's make
(defmethod handle-event :copilot/session.idle [_]
(println))

(run! handle-event (h/query-seq! "Tell me a short joke" :session {:streaming? true}))
(run! handle-event (h/query-seq! "Tell me a short joke" :session {:on-permission-request copilot/approve-all :streaming? true}))
```

### Using core.async Channels
Expand All @@ -100,7 +101,8 @@ Right now, you wait for the complete response before seeing anything. Let's make
(require '[clojure.core.async :refer [chan tap go-loop <!]])
(require '[github.copilot-sdk :as copilot])

(copilot/with-client-session [session {:model "gpt-5.2" :streaming? true}]
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "gpt-5.2" :streaming? true}]
(let [ch (chan 256)
done (promise)]
(tap (copilot/events session) ch)
Expand Down Expand Up @@ -133,7 +135,8 @@ Use `<create-session` and `<send!` for fully non-blocking operations inside `go`
(copilot/with-client [client]
(let [result-ch
(go
(let [session (<! (copilot/<create-session client {:model "gpt-5.2"}))]
(let [session (<! (copilot/<create-session client {:on-permission-request copilot/approve-all
:model "gpt-5.2"}))]
(when (instance? Throwable session)
(throw session))
(let [answer (<! (copilot/<send! session {:prompt "Capital of France?"}))]
Expand Down Expand Up @@ -178,7 +181,8 @@ Now for the powerful part. Let's give Copilot the ability to call your code by d
(copilot/result-success
(str city ": " temp "°F and " condition))))}))

(copilot/with-client-session [session {:model "gpt-5.2"
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "gpt-5.2"
:tools [get-weather]}]
(println (h/query "What's the weather like in Seattle and Tokyo?"
:session session)))
Expand Down Expand Up @@ -206,7 +210,8 @@ Let's put it all together into an interactive assistant:
(copilot/result-success
(str city ": " temp "°F and " condition))))}))

(copilot/with-client-session [session {:model "gpt-5.2"
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "gpt-5.2"
:streaming? true
:tools [get-weather]}]
(println "🌤️ Weather Assistant (type 'exit' to quit)")
Expand Down Expand Up @@ -260,8 +265,8 @@ you provide an `:on-permission-request` handler.
Use `approve-all` to permit everything:

```clojure
(copilot/with-client-session [session {:model "gpt-5.2"
:on-permission-request copilot/approve-all}]
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "gpt-5.2"}]
...)
```

Expand All @@ -272,7 +277,8 @@ Or write a custom handler for fine-grained control. See [Permission Handling](./
Pass `:client-name` to identify your application in API requests (included in the User-Agent header):

```clojure
(copilot/with-client-session [session {:model "gpt-5.2"
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "gpt-5.2"
:client-name "my-weather-app"}]
...)
```
Expand Down
Loading