Skip to content
Closed
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: 1 addition & 1 deletion claude-for-msft-365-install/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "claude-for-msft-365-install",
"description": "Provision direct cloud access (Vertex AI, Bedrock, or LLM gateway) for the Claude Office add-in. Generates the customized add-in manifest, walks through Azure admin consent, and writes per-user config via Microsoft Graph extension attributes.",
"version": "0.1.6",
"version": "0.1.7",
"author": {
"name": "Anthropic",
"email": "support@anthropic.com"
Expand Down
13 changes: 13 additions & 0 deletions claude-for-msft-365-install/commands/bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,19 @@ layer.
"disabled_features": ["skills.authoring"]
```

### `available_models`

A JSON array of the model ids the 3P picker offers this user, replacing the
built-in catalog. Same semantics as the [manifest key](manifest.md#model-picker);
bootstrap is the per-user layer, and the highest-precedence channel, so
rotations here propagate without re-login.

```json
"available_models": ["claude-opus-4-5", {"id": "<id-your-gateway-serves>", "label": "<picker label>"}]
```

Entries are ids, or `{ "id", "label" }` objects to control the picker label.

### `bootstrap_expires_at`

Epoch timestamp (seconds or milliseconds — auto-detected) for when this
Expand Down
41 changes: 41 additions & 0 deletions claude-for-msft-365-install/commands/manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,47 @@ Unknown slugs are ignored (forward-compatible). Setting it here applies one
policy org-wide; per-user policy belongs in [bootstrap](bootstrap.md#disabled_features)
(JSON array) or extension attrs (comma-separated).

## Model picker

On 3P deployments the picker is built from a model catalog baked into the
add-in. `available_models` replaces that catalog with your own list:

```bash
available_models='claude-opus-4-5,<id-your-gateway-serves>'
```

Set it and the picker offers exactly those ids, in that order — the first is
the default your users land on. Leave it unset and the built-in catalog
applies. There is no separate "hide this one" key: to drop a model, leave it
out of the list. Accepts a comma list or a JSON array
(`'["claude-opus-4-5"]'`).

Matching is case-insensitive, and a canonical id also covers the provider
forms of the same model — `claude-opus-4-5` selects
`us.anthropic.claude-opus-4-5-20251101-v1:0` and `claude-opus-4-5@20251101`
too. An id the catalog doesn't know is offered as you wrote it, which is how
you reach a model your gateway serves that this build predates — so a typo
shows up in the picker and fails on use rather than being silently dropped.
A list that matches nothing offerable is ignored entirely: an empty picker
isn't recoverable in the UI.

On the JSON form, an entry may also be `{"id": ..., "label": ...}` to control
what the picker shows — useful when your gateway ids are internal names:

```bash
available_models='[{"id":"prod-claude-sonnet-4-6","label":"Sonnet 4.6 (Prod)"}]'
```

The comma form carries bare ids only.

Note this pins you to the list. New models we ship won't appear until you add
them — which is usually what you want, since your gateway has to provision
each model anyway.

In **Outlook** the list may only narrow, never extend: the mail safety gate
pins that surface to a vetted model, so ids outside the built-in catalog are
never offered there.

## Version

M365 Admin Center caches by `<Id>` + `<Version>` — re-upload with the same
Expand Down
1 change: 1 addition & 0 deletions claude-for-msft-365-install/commands/update-user-attrs.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ over manifest params, so whatever's here wins. All values are 256 chars max.
| `google_client_id` `google_client_secret` | Different OAuth client per team (uncommon) |
| `aws_role_arn` `aws_region` | Different Bedrock roles by team |
| `otlp_endpoint` `otlp_headers` `otlp_resource_attributes` | Route telemetry to a team-specific OTEL collector / tag spans with team-level resource attributes |
| `available_models` | Different teams see different models in the 3P picker (comma-separated ids; see [manifest](manifest.md#model-picker)) |

## One user

Expand Down
10 changes: 10 additions & 0 deletions claude-for-msft-365-install/scripts/build-manifest.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const URL_SLOTS = [/(<SourceLocation\s+DefaultValue=")([^"]+)(")/g, /(id="Taskpa
// (your infra may look different). `secret` keys warn louder: the manifest is an
// org-wide file and its URL can land in deploy logs; per-user secrets typically go
// in Azure extension attributes instead.
// A JSON array (["a","b"]) or a comma list (a,b) of model ids.
const MODEL_ID_LIST = /^(\[.*\]|[\w.:@-]+(\s*,\s*[\w.:@-]+)*)$/;

const KEYS = {
gcp_project_id: { pattern: /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/, hint: "GCP project ID" },
gcp_region: { pattern: /./, hint: "GCP region, e.g. us-east5 or global" },
Expand Down Expand Up @@ -85,6 +88,13 @@ const KEYS = {
pattern: /^[\w.]+(,[\w.]+)*$/,
hint: "comma-separated feature slugs to lock for users, e.g. skills.authoring",
},
// Model ids carry . : @ - (us.anthropic.claude-opus-4-5-20251101-v1:0,
// claude-opus-4-5@20251101), so this can't reuse disabled_features' slug pattern.
// Accepts a JSON array or a comma list; the add-in preserves id case.
available_models: {
pattern: MODEL_ID_LIST,
hint: 'the models the picker offers, replacing the built-in catalog, e.g. claude-opus-4-5 or ["claude-opus-4-5"] — 3P gateway/Bedrock/Vertex only',
},
};

const NEEDS_ENTRA = ["aws_role_arn", "graph_client_id", "entra_scope", "gateway_auth_source"];
Expand Down
Loading