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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@
prompt.md
*.asc
plan.md
update.sh

3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This change

## [Unreleased]

### Added (upstream PR #510 sync)
- `:client-name` option for `create-session` and `resume-session` — identifies the application using the SDK, included in the User-Agent header for API requests. Forwarded as `clientName` on the wire (upstream PR #510).

### Changed (upstream PR #509 sync)
- **BREAKING**: Deny all permissions by default — `requestPermission` is now always `true` on the wire, and permission requests are denied when no `:on-permission-request` handler is configured. Previously, omitting the handler meant the CLI never asked for permission. To restore the old behavior, pass `:on-permission-request copilot/approve-all` in your session config.

Expand Down
1 change: 1 addition & 0 deletions doc/reference/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ Create a client and session together, ensuring both are cleaned up on exit.
| Key | Type | Description |
|-----|------|-------------|
| `:session-id` | string | Custom session ID (optional) |
| `:client-name` | string | Client name to identify the application (included in User-Agent header) |
| `:model` | string | Model to use (`"gpt-5.2"`, `"claude-sonnet-4.5"`, etc.) |
| `:tools` | vector | Custom tools exposed to the CLI |
| `:system-message` | map | System message customization (see below) |
Expand Down
4 changes: 4 additions & 0 deletions src/github/copilot_sdk/client.clj
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,7 @@
(util/clj->wire is))]
(cond-> {}
(:session-id config) (assoc :session-id (:session-id config))
(:client-name config) (assoc :client-name (:client-name config))
(:model config) (assoc :model (:model config))
wire-tools (assoc :tools wire-tools)
wire-sys-msg (assoc :system-message wire-sys-msg)
Expand Down Expand Up @@ -998,6 +999,7 @@
wire-infinite-sessions (when-let [is (:infinite-sessions config)]
(util/clj->wire is))]
(cond-> {:session-id session-id}
(:client-name config) (assoc :client-name (:client-name config))
(:model config) (assoc :model (:model config))
wire-tools (assoc :tools wire-tools)
wire-sys-msg (assoc :system-message wire-sys-msg)
Expand Down Expand Up @@ -1037,6 +1039,7 @@

Config options:
- :session-id - Custom session ID
- :client-name - Client name to identify the application (included in User-Agent header)
- :model - Model to use (e.g., \"gpt-5.2\")
- :tools - Vector of tool definitions
- :system-message - System message config
Expand Down Expand Up @@ -1081,6 +1084,7 @@
"Resume an existing session by ID.

Config options (parity with create-session, upstream PR #376):
- :client-name - Client name to identify the application (included in User-Agent header)
- :model - Change the model for the resumed session
- :tools - Tools exposed to the CLI server
- :system-message - System message configuration {:mode :content}
Expand Down
10 changes: 6 additions & 4 deletions src/github/copilot_sdk/specs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,10 @@
;; Disable resume flag
(s/def ::disable-resume? boolean?)

(s/def ::client-name ::non-blank-string)

(def session-config-keys
#{:session-id :model :tools :system-message
#{:session-id :client-name :model :tools :system-message
:available-tools :excluded-tools :provider
:on-permission-request :streaming? :mcp-servers
:custom-agents :config-dir :skill-directories
Expand All @@ -206,7 +208,7 @@

(s/def ::session-config
(closed-keys
(s/keys :opt-un [::session-id ::model ::tools ::system-message
(s/keys :opt-un [::session-id ::client-name ::model ::tools ::system-message
::available-tools ::excluded-tools ::provider
::on-permission-request ::streaming? ::mcp-servers
::custom-agents ::config-dir ::skill-directories
Expand All @@ -216,15 +218,15 @@
session-config-keys))

(def ^:private resume-session-config-keys
#{:model :tools :system-message :available-tools :excluded-tools
#{:client-name :model :tools :system-message :available-tools :excluded-tools
:provider :streaming? :on-permission-request
:mcp-servers :custom-agents :config-dir :skill-directories
:disabled-skills :infinite-sessions :reasoning-effort
:on-user-input-request :hooks :working-directory :disable-resume?})

(s/def ::resume-session-config
(closed-keys
(s/keys :opt-un [::model ::tools ::system-message ::available-tools ::excluded-tools
(s/keys :opt-un [::client-name ::model ::tools ::system-message ::available-tools ::excluded-tools
::provider ::streaming? ::on-permission-request
::mcp-servers ::custom-agents ::config-dir ::skill-directories
::disabled-skills ::infinite-sessions ::reasoning-effort
Expand Down
29 changes: 29 additions & 0 deletions test/github/copilot_sdk/integration_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,35 @@
(is (= "direct" (:envValueMode create-params)))
(is (= "direct" (:envValueMode resume-params))))))

(deftest test-client-name-forwarded-on-wire
(testing "clientName is forwarded in session.create when set (upstream PR #510)"
(let [seen (atom {})
_ (mock/set-request-hook! *mock-server* (fn [method params]
(when (#{"session.create"} method)
(swap! seen assoc method params))))
_ (sdk/create-session *test-client* {:client-name "my-app"})
create-params (get @seen "session.create")]
(is (= "my-app" (:clientName create-params)))))

(testing "clientName is forwarded in session.resume when set (upstream PR #510)"
(let [seen (atom {})
session-id (sdk/session-id (sdk/create-session *test-client* {}))
_ (mock/set-request-hook! *mock-server* (fn [method params]
(when (#{"session.resume"} method)
(swap! seen assoc method params))))
_ (sdk/resume-session *test-client* session-id {:client-name "my-app"})
resume-params (get @seen "session.resume")]
(is (= "my-app" (:clientName resume-params)))))

(testing "clientName is omitted from wire when not set"
(let [seen (atom {})
_ (mock/set-request-hook! *mock-server* (fn [method params]
(when (#{"session.create"} method)
(swap! seen assoc method params))))
_ (sdk/create-session *test-client* {:model "gpt-5.2"})
create-params (get @seen "session.create")]
(is (not (contains? create-params :clientName))))))

;; -----------------------------------------------------------------------------
;; Permission Tests (upstream PR #509: deny-by-default)
;; -----------------------------------------------------------------------------
Expand Down