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
5 changes: 5 additions & 0 deletions .changeset/slack-destination-update-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@outlit/cli": patch
---

Tighten destination update commands to the Slack-channel public contract.
2 changes: 1 addition & 1 deletion docs/ai-integrations/mcp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ API-key authenticated MCP clients can also inspect and manage selected agent and
| `outlit_destination_list` | List configured automation destinations with masked configuration |
| `outlit_destination_get` | Get one configured automation destination with masked configuration |
| `outlit_destination_create` | Create one Slack channel destination; can set it as default |
| `outlit_destination_update` | Update one automation destination; can set a Slack destination as default |
| `outlit_destination_update` | Update one Slack channel automation destination; can set it as default |
| `outlit_destination_enable` | Enable one configured automation destination |
| `outlit_destination_disable` | Disable one configured automation destination |
| `outlit_destination_archive` | Archive one configured automation destination |
Expand Down
12 changes: 6 additions & 6 deletions docs/ai-integrations/platform-actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,16 @@ This workflow lets the agent discover available templates, understand supported
| `POST /api/agents/{id}/enable` | Enable one configured agent |
| `POST /api/agents/{id}/disable` | Disable one configured agent |
| `POST /api/agents/{id}/rename` | Rename one configured agent |
| `GET /api/agents/{id}/runs` | List safe run summaries for one agent |
| `POST /api/agents/{id}/runs` | Start a manual run for one legacy churn agent |
| `GET /api/agents/{id}/runs/{runId}` | Get one safe run detail |
| `GET /api/agents/{agentId}/runs` | List safe run summaries for one agent |
| `POST /api/agents/{agentId}/runs` | Start a manual run for one legacy churn agent |
| `GET /api/agents/{agentId}/runs/{runId}` | Get one safe run detail |
| `GET /api/automations/options` | Show automation schemas, constants, and constraints |
| `GET /api/automations` | List configured automations |
| `POST /api/automations` | Create an agent automation |
| `GET /api/automations/{id}` | Get one configured automation |
| `PATCH /api/automations/{id}` | Update one agent automation |
| `GET /api/automations/{id}/runs` | List safe automation run summaries |
| `GET /api/automations/{id}/runs/{runId}` | Get one safe automation run detail |
| `GET /api/automations/{automationId}/runs` | List safe automation run summaries |
| `GET /api/automations/{automationId}/runs/{runId}` | Get one safe automation run detail |
| `POST /api/automations/{id}/enable` | Enable one configured automation |
| `POST /api/automations/{id}/disable` | Disable one configured automation |
| `POST /api/automations/{id}/archive` | Archive one configured automation |
Expand All @@ -156,7 +156,7 @@ This workflow lets the agent discover available templates, understand supported
| `GET /api/destinations` | List configured automation destinations with masked configuration |
| `GET /api/destinations/{id}` | Get one configured automation destination with masked configuration |
| `POST /api/destinations` | Create one Slack channel destination; can set it as default |
| `PATCH /api/destinations/{id}` | Update one automation destination; can set a Slack destination as default |
| `PATCH /api/destinations/{id}` | Update one Slack channel automation destination; can set it as default |
| `POST /api/destinations/{id}/enable` | Enable one configured automation destination |
| `POST /api/destinations/{id}/disable` | Disable one configured automation destination |
| `POST /api/destinations/{id}/archive` | Archive one configured automation destination |
Expand Down
2 changes: 1 addition & 1 deletion docs/cli/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ outlit destinations disable 10000000-0000-4000-8000-000000000003 --json
outlit destinations archive 10000000-0000-4000-8000-000000000003 --json
```

Destination list results are under `result.data.destinations`; get, create, update, enable, and disable results are under `result.data.destination`. New destination creation is Slack-channel backed; use `destinations options` to inspect Slack connection status and available channel IDs. `destinations options` is non-mutating but requires `agents:write` because it lists Slack channel choices used to create destinations. Use `--default` on `destinations create` or `destinations update` to make a Slack destination the default fallback. `destinations update` patches only the fields you pass; use `--type slack` for Slack-backed destinations. Archive results return `result.data.destination.id` and `result.data.destination.archivedAt`. Raw destination secrets and unmasked provider configuration are not returned.
Destination list results are under `result.data.destinations`; get, create, update, enable, and disable results are under `result.data.destination`. Destination creation and update are Slack-channel backed; use `destinations options` to inspect Slack connection status and available channel IDs. `destinations options` is non-mutating but requires `agents:write` because it lists Slack channel choices used to create destinations. Use `--default` on `destinations create` or `destinations update` to make a Slack destination the default fallback. `destinations update` patches only the fields you pass; use `--type slack` for Slack-backed destinations. Archive results return `result.data.destination.id` and `result.data.destination.archivedAt`. Raw destination secrets and unmasked provider configuration are not returned.

## Settings

Expand Down
101 changes: 34 additions & 67 deletions docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1304,15 +1304,15 @@
}
}
},
"/api/automations/{id}/runs": {
"/api/automations/{automationId}/runs": {
"get": {
"tags": ["Platform API"],
"summary": "List automation runs",
"description": "List safe run summaries for one configured Outlit automation. Read-only.",
"operationId": "listAutomationRuns",
"parameters": [
{
"name": "id",
"name": "automationId",
"in": "path",
"required": true,
"description": "Automation ID.",
Expand Down Expand Up @@ -1378,7 +1378,7 @@
}
},
"404": {
"description": "No automation was found for the authenticated organization and requested id.",
"description": "No automation was found for the authenticated organization and requested automation ID.",
"content": {
"application/json": {
"schema": {
Expand All @@ -1403,15 +1403,15 @@
}
}
},
"/api/automations/{id}/runs/{runId}": {
"/api/automations/{automationId}/runs/{runId}": {
"get": {
"tags": ["Platform API"],
"summary": "Get automation run",
"description": "Get safe run details for one configured Outlit automation run. Read-only.",
"operationId": "getAutomationRun",
"parameters": [
{
"name": "id",
"name": "automationId",
"in": "path",
"required": true,
"description": "Automation ID.",
Expand Down Expand Up @@ -2459,15 +2459,15 @@
}
}
},
"/api/agents/{id}/runs": {
"/api/agents/{agentId}/runs": {
"get": {
"tags": ["Platform API"],
"summary": "List agent runs",
"description": "List safe run summaries for one configured Outlit agent. Read-only.",
"operationId": "listAgentRuns",
"parameters": [
{
"name": "id",
"name": "agentId",
"in": "path",
"required": true,
"description": "Agent ID.",
Expand Down Expand Up @@ -2523,7 +2523,7 @@
}
},
"404": {
"description": "No agent was found for the authenticated organization and requested id.",
"description": "No agent was found for the authenticated organization and requested agent ID.",
"content": {
"application/json": {
"schema": {
Expand Down Expand Up @@ -2554,7 +2554,7 @@
"operationId": "startAgentRun",
"parameters": [
{
"name": "id",
"name": "agentId",
"in": "path",
"required": true,
"description": "Agent ID.",
Expand Down Expand Up @@ -2612,7 +2612,7 @@
}
},
"404": {
"description": "No agent was found for the authenticated organization and requested id.",
"description": "No agent was found for the authenticated organization and requested agent ID.",
"content": {
"application/json": {
"schema": {
Expand Down Expand Up @@ -2647,15 +2647,15 @@
}
}
},
"/api/agents/{id}/runs/{runId}": {
"/api/agents/{agentId}/runs/{runId}": {
"get": {
"tags": ["Platform API"],
"summary": "Get agent run",
"description": "Get safe run details for one configured Outlit agent run. Read-only.",
"operationId": "getAgentRun",
"parameters": [
{
"name": "id",
"name": "agentId",
"in": "path",
"required": true,
"description": "Agent ID.",
Expand Down Expand Up @@ -3283,7 +3283,7 @@
"patch": {
"tags": ["Platform API"],
"summary": "Update destination",
"description": "Update one automation destination. Responses include masked configuration only. Passing isDefault true on a Slack destination makes it the default fallback destination and enables it.",
"description": "Update one Slack channel automation destination. Responses include masked configuration only. Passing isDefault true makes it the default fallback destination and enables it.",
"operationId": "updateDestination",
"parameters": [
{
Expand Down Expand Up @@ -8414,62 +8414,29 @@
"additionalProperties": false
},
"UpdateDestinationRequest": {
"oneOf": [
{
"type": "object",
"required": ["type"],
"minProperties": 2,
"properties": {
"type": {
"type": "string",
"const": "WEBHOOK_ENDPOINT"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"description": {
"type": ["string", "null"],
"maxLength": 1000
},
"enabled": {
"type": "boolean"
},
"url": {
"type": "string",
"format": "uri",
"pattern": "^(https://|http://(localhost|127\\.0\\.0\\.1|\\[::1\\]|::1)([:/]|$))"
}
},
"additionalProperties": false
"type": "object",
"required": ["type"],
"minProperties": 2,
"properties": {
"type": {
"type": "string",
"const": "SLACK_CHANNEL"
},
{
"type": "object",
"required": ["type"],
"minProperties": 2,
"properties": {
"type": {
"type": "string",
"const": "SLACK_CHANNEL"
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"enabled": {
"type": "boolean"
},
"isDefault": {
"type": "boolean",
"const": true,
"description": "Set this Slack destination as the default fallback destination."
}
},
"additionalProperties": false
"label": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"enabled": {
"type": "boolean"
},
"isDefault": {
"type": "boolean",
"const": true,
"description": "Set this Slack destination as the default fallback destination."
}
]
},
"additionalProperties": false
},
"UpdateAgentCommandSuccess": {
"type": "object",
Expand Down
5 changes: 1 addition & 4 deletions packages/cli/src/commands/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,14 +356,11 @@ const COMMANDS: readonly CmdDef[] = [
},
{
name: "update",
desc: "Update an automation destination",
desc: "Update a Slack channel destination",
flags: [
...COMMON,
{ name: "--type", desc: "Destination type" },
{ name: "--name", desc: "Webhook destination name" },
{ name: "--url", desc: "Webhook URL" },
{ name: "--label", desc: "Slack channel label" },
{ name: "--description", desc: "Destination description" },
{ name: "--default", desc: "Make this the default destination" },
{ name: "--enabled", desc: "Enable the destination after update" },
{ name: "--disabled", desc: "Disable the destination" },
Expand Down
59 changes: 13 additions & 46 deletions packages/cli/src/commands/destinations/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ import { getClientOrExit, runTool } from "../../lib/api"
import { outputError } from "../../lib/output"
import { optionalTrimmedString, requiredTrimmedString } from "../../lib/platform-input"

function parseDestinationType(type: string, json: boolean): "WEBHOOK_ENDPOINT" | "SLACK_CHANNEL" {
function parseDestinationType(type: string, json: boolean): "SLACK_CHANNEL" {
const normalized = type.trim().toLowerCase()
if (normalized === "webhook" || normalized === "webhook_endpoint") {
return "WEBHOOK_ENDPOINT"
}

if (normalized === "slack" || normalized === "slack_channel") {
return "SLACK_CHANNEL"
}

return outputError({ message: "--type must be webhook or slack", code: "invalid_input" }, json)
return outputError({ message: "--type must be slack", code: "invalid_input" }, json)
}

function parseEnabledFlag(args: { enabled?: boolean; disabled?: boolean }, json: boolean) {
Expand All @@ -36,9 +32,9 @@ export default defineCommand({
meta: {
name: "update",
description: [
"Update an Outlit automation destination.",
"Update an Outlit Slack channel automation destination.",
"",
"Provide --type slack plus one or more fields to patch. Existing webhook destinations can still be patched with --type webhook.",
"Provide --type slack plus one or more fields to patch.",
"",
"Examples:",
" outlit destinations update 10000000-0000-4000-8000-000000000003 --type slack --label '#customer-ops' --json",
Expand All @@ -58,12 +54,9 @@ export default defineCommand({
},
type: {
type: "string",
description: "Required destination type: webhook or slack",
description: "Required destination type: slack",
},
name: { type: "string", description: "Webhook destination name" },
url: { type: "string", description: "Optional webhook URL" },
label: { type: "string", description: "Slack channel label" },
description: { type: "string", description: "Optional destination description" },
default: { type: "boolean", description: "Make this the default destination" },
enabled: { type: "boolean", description: "Enable the destination after update" },
disabled: { type: "boolean", description: "Disable the destination" },
Expand All @@ -85,42 +78,16 @@ export default defineCommand({
json,
)
}
if (args.default === true && type !== "SLACK_CHANNEL") {
return outputError(
{ message: "--default is only supported for Slack destinations", code: "invalid_input" },
json,
)
const label = optionalTrimmedString(args.label)
const input = {
id: args.id,
type,
...(label ? { label } : {}),
...(enabled !== undefined ? { enabled } : {}),
...(args.default === true ? { isDefault: true } : {}),
}
const input =
type === "SLACK_CHANNEL"
? {
id: args.id,
type,
...(optionalTrimmedString(args.label ?? args.name)
? { label: optionalTrimmedString(args.label ?? args.name) }
: {}),
...(enabled !== undefined ? { enabled } : {}),
...(args.default === true ? { isDefault: true } : {}),
}
: {
id: args.id,
type: "WEBHOOK_ENDPOINT",
...(optionalTrimmedString(args.name) ? { name: optionalTrimmedString(args.name) } : {}),
...(args.description !== undefined
? { description: optionalTrimmedString(args.description) }
: {}),
...(enabled !== undefined ? { enabled } : {}),
...(optionalTrimmedString(args.url) ? { url: optionalTrimmedString(args.url) } : {}),
}

if (
!("name" in input) &&
!("description" in input) &&
!("url" in input) &&
!("label" in input) &&
!("enabled" in input) &&
!("isDefault" in input)
) {
if (!("label" in input) && !("enabled" in input) && !("isDefault" in input)) {
return outputError(
{
message: "Provide at least one destination field to update",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/tests/commands/completions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ describe("completions command", () => {
'COMPREPLY=($(compgen -W "--api-key --json --type --channel-id --label --default --disabled"',
)
expect(out).toContain(
'COMPREPLY=($(compgen -W "--api-key --json --type --name --url --label --description --default --enabled --disabled"',
'COMPREPLY=($(compgen -W "--api-key --json --type --label --default --enabled --disabled"',
)
expect(out).toContain(
'COMPREPLY=($(compgen -W "--api-key --json --status --confidence --limit"',
Expand Down
Loading