@outlit/cli 1.6.1 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +301 -7
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -104,7 +104,7 @@ var package_default;
104
104
  var init_package = __esm(() => {
105
105
  package_default = {
106
106
  name: "@outlit/cli",
107
- version: "1.6.1",
107
+ version: "1.6.2",
108
108
  description: "CLI for Outlit customer intelligence platform",
109
109
  license: "Apache-2.0",
110
110
  repository: {
@@ -135,7 +135,7 @@ var init_package = __esm(() => {
135
135
  },
136
136
  dependencies: {
137
137
  "@clack/prompts": "^1.0.1",
138
- "@outlit/tools": "^0.1.0",
138
+ "@outlit/tools": "^0.1.1",
139
139
  citty: "^0.2.1"
140
140
  },
141
141
  devDependencies: {
@@ -1587,7 +1587,7 @@ function createOutlitClient(options) {
1587
1587
  }
1588
1588
  };
1589
1589
  }
1590
- var customerToolNames, customerToolContracts, customerBillingStatuses, customerFactStatuses, customerFactTypes, unsupportedCustomerFactTypes, customerFactCategories, customerIncludeSections, customerSourceTypes, customerTimeframes, timelineChannels, timelineTimeframes, userJourneyStages, schemaTables, customerToolNameSet, iso8601UtcDateTimeRegex, DEFAULT_OUTLIT_API_URL = "https://app.outlit.ai", defaultAgentToolNames, sqlToolNames, analyticalAgentToolNames;
1590
+ var customerToolNames, customerToolContracts, customerBillingStatuses, customerFactStatuses, customerFactTypes, unsupportedCustomerFactTypes, customerFactCategories, customerIncludeSections, customerSourceTypes, customerTimeframes, notificationSeverityValues, timelineChannels, timelineTimeframes, userJourneyStages, schemaTables, customerToolNameSet, iso8601UtcDateTimeRegex, DEFAULT_OUTLIT_API_URL = "https://app.outlit.ai", actionToolNames, defaultAgentToolNames, sqlToolNames, analyticalAgentToolNames;
1591
1591
  var init_dist4 = __esm(() => {
1592
1592
  customerToolNames = [
1593
1593
  "outlit_list_customers",
@@ -1599,7 +1599,8 @@ var init_dist4 = __esm(() => {
1599
1599
  "outlit_get_source",
1600
1600
  "outlit_search_customer_context",
1601
1601
  "outlit_query",
1602
- "outlit_schema"
1602
+ "outlit_schema",
1603
+ "outlit_send_notification"
1603
1604
  ];
1604
1605
  customerToolContracts = {
1605
1606
  outlit_list_customers: {
@@ -2057,7 +2058,7 @@ var init_dist4 = __esm(() => {
2057
2058
  description: `Execute raw SQL queries against your analytics data.
2058
2059
 
2059
2060
  Available tables:
2060
- - events: Customer activity events (event_type, event_channel, customer_id, occurred_at, properties, ...)
2061
+ - events: Customer activity events (event_name, event_type, event_channel, customer_id, occurred_at, properties, ...)
2061
2062
  - customer_dimensions: Customer attributes (customer_id, domain, name, billing_status, plan, mrr_cents, ...)
2062
2063
  - user_dimensions: User attributes (user_id, email, name, customer_id, ...)
2063
2064
  - mrr_snapshots: Revenue snapshots over time (customer_id, snapshot_date, mrr_cents, ...)
@@ -2066,7 +2067,7 @@ All queries are automatically filtered to your organization's data.
2066
2067
  Only SELECT queries are allowed.
2067
2068
 
2068
2069
  Example queries:
2069
- - SELECT event_type, count(*) FROM events GROUP BY 1 ORDER BY 2 DESC LIMIT 10
2070
+ - SELECT event_name, count(*) FROM events GROUP BY 1 ORDER BY 2 DESC LIMIT 10
2070
2071
  - SELECT billing_status, sum(mrr_cents)/100 as mrr FROM customer_dimensions GROUP BY 1
2071
2072
  - SELECT * FROM events WHERE customer_id = 'cust_123' ORDER BY occurred_at DESC LIMIT 50`,
2072
2073
  inputSchema: {
@@ -2106,6 +2107,113 @@ Returns column definitions and example queries for each table.`,
2106
2107
  },
2107
2108
  additionalProperties: false
2108
2109
  }
2110
+ },
2111
+ outlit_send_notification: {
2112
+ toolName: "outlit_send_notification",
2113
+ description: "Send or post a Slack notification. Use only when the user explicitly asks you to send, post, or notify. The payload is rendered as a Slack code block.",
2114
+ inputSchema: {
2115
+ $schema: "https://json-schema.org/draft/2020-12/schema",
2116
+ type: "object",
2117
+ properties: {
2118
+ title: {
2119
+ type: "string",
2120
+ minLength: 1,
2121
+ maxLength: 160,
2122
+ description: "Notification title"
2123
+ },
2124
+ payload: {
2125
+ description: "JSON-compatible payload rendered in Slack as a code block. Serialized size must be 100,000 characters or fewer.",
2126
+ anyOf: [
2127
+ {
2128
+ type: "string"
2129
+ },
2130
+ {
2131
+ type: "number"
2132
+ },
2133
+ {
2134
+ type: "boolean"
2135
+ },
2136
+ {
2137
+ type: "null"
2138
+ },
2139
+ {
2140
+ type: "array",
2141
+ items: {
2142
+ $ref: "#/$defs/__schema0"
2143
+ }
2144
+ },
2145
+ {
2146
+ type: "object",
2147
+ propertyNames: {
2148
+ type: "string"
2149
+ },
2150
+ additionalProperties: {
2151
+ $ref: "#/$defs/__schema0"
2152
+ }
2153
+ }
2154
+ ],
2155
+ $ref: "#/$defs/__schema0"
2156
+ },
2157
+ message: {
2158
+ description: "Optional Slack message",
2159
+ type: "string",
2160
+ minLength: 1,
2161
+ maxLength: 1200
2162
+ },
2163
+ severity: {
2164
+ description: "Optional notification severity",
2165
+ type: "string",
2166
+ enum: ["low", "medium", "high"]
2167
+ },
2168
+ source: {
2169
+ description: "Optional source label",
2170
+ type: "string",
2171
+ minLength: 1,
2172
+ maxLength: 120
2173
+ },
2174
+ subject: {
2175
+ description: "Optional subject line",
2176
+ type: "string",
2177
+ minLength: 1,
2178
+ maxLength: 240
2179
+ }
2180
+ },
2181
+ required: ["title", "payload"],
2182
+ additionalProperties: false,
2183
+ $defs: {
2184
+ __schema0: {
2185
+ anyOf: [
2186
+ {
2187
+ type: "string"
2188
+ },
2189
+ {
2190
+ type: "number"
2191
+ },
2192
+ {
2193
+ type: "boolean"
2194
+ },
2195
+ {
2196
+ type: "null"
2197
+ },
2198
+ {
2199
+ type: "array",
2200
+ items: {
2201
+ $ref: "#/$defs/__schema0"
2202
+ }
2203
+ },
2204
+ {
2205
+ type: "object",
2206
+ propertyNames: {
2207
+ type: "string"
2208
+ },
2209
+ additionalProperties: {
2210
+ $ref: "#/$defs/__schema0"
2211
+ }
2212
+ }
2213
+ ]
2214
+ }
2215
+ }
2216
+ }
2109
2217
  }
2110
2218
  };
2111
2219
  customerBillingStatuses = [
@@ -2162,6 +2270,7 @@ Returns column definitions and example queries for each table.`,
2162
2270
  ];
2163
2271
  customerSourceTypes = ["EMAIL", "CALL", "CALENDAR_EVENT", "SUPPORT_TICKET"];
2164
2272
  customerTimeframes = ["7d", "14d", "30d", "90d"];
2273
+ notificationSeverityValues = ["low", "medium", "high"];
2165
2274
  timelineChannels = [
2166
2275
  "SDK",
2167
2276
  "EMAIL",
@@ -2188,6 +2297,9 @@ Returns column definitions and example queries for each table.`,
2188
2297
  ];
2189
2298
  customerToolNameSet = new Set(customerToolNames);
2190
2299
  iso8601UtcDateTimeRegex = /^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$/;
2300
+ actionToolNames = [
2301
+ "outlit_send_notification"
2302
+ ];
2191
2303
  defaultAgentToolNames = [
2192
2304
  "outlit_list_customers",
2193
2305
  "outlit_list_users",
@@ -2196,7 +2308,8 @@ Returns column definitions and example queries for each table.`,
2196
2308
  "outlit_list_facts",
2197
2309
  "outlit_get_fact",
2198
2310
  "outlit_get_source",
2199
- "outlit_search_customer_context"
2311
+ "outlit_search_customer_context",
2312
+ ...actionToolNames
2200
2313
  ];
2201
2314
  sqlToolNames = [
2202
2315
  "outlit_schema",
@@ -4879,6 +4992,185 @@ var init_sql = __esm(() => {
4879
4992
  });
4880
4993
  });
4881
4994
 
4995
+ // src/commands/notify.ts
4996
+ var exports_notify = {};
4997
+ __export(exports_notify, {
4998
+ default: () => notify_default
4999
+ });
5000
+ import { readFileSync as readFileSync5 } from "node:fs";
5001
+ function parsePayload(raw) {
5002
+ try {
5003
+ return JSON.parse(raw);
5004
+ } catch {
5005
+ return raw;
5006
+ }
5007
+ }
5008
+ function validateTrimmedText(value, maxLength) {
5009
+ if (value === undefined) {
5010
+ return;
5011
+ }
5012
+ const trimmed = value.trim();
5013
+ if (trimmed.length === 0 || trimmed.length > maxLength) {
5014
+ return null;
5015
+ }
5016
+ return trimmed;
5017
+ }
5018
+ function normalizeSeverity(severity) {
5019
+ const normalized = severity.trim().toLowerCase();
5020
+ return notificationSeverityValues.includes(normalized) ? normalized : null;
5021
+ }
5022
+ function payloadSizeIsValid(payload) {
5023
+ const serialized = JSON.stringify(payload);
5024
+ return typeof serialized === "string" && serialized.length <= 1e5;
5025
+ }
5026
+ var notify_default;
5027
+ var init_notify = __esm(() => {
5028
+ init_dist4();
5029
+ init_dist();
5030
+ init_auth();
5031
+ init_output2();
5032
+ init_api();
5033
+ init_output();
5034
+ notify_default = defineCommand2({
5035
+ meta: {
5036
+ name: "notify",
5037
+ description: [
5038
+ "Send a Slack notification through Outlit.",
5039
+ "",
5040
+ "Provide the payload as a positional argument or via --payload-file.",
5041
+ "When both are provided, --payload-file takes precedence.",
5042
+ "",
5043
+ "Examples:",
5044
+ ` outlit notify --title 'Risk found' '{"customer":"acme.com"}'`,
5045
+ " outlit notify --title 'Risk found' --payload-file ./payload.json",
5046
+ ` outlit notify --title 'Escalation' --severity HIGH --message 'Check this account' '{"customer":"acme.com"}'`,
5047
+ "",
5048
+ AGENT_JSON_HINT
5049
+ ].join(`
5050
+ `)
5051
+ },
5052
+ args: {
5053
+ ...authArgs,
5054
+ ...outputArgs,
5055
+ title: {
5056
+ type: "string",
5057
+ description: "Notification title",
5058
+ required: false
5059
+ },
5060
+ payload: {
5061
+ type: "positional",
5062
+ description: "Notification payload as JSON or raw string",
5063
+ required: false
5064
+ },
5065
+ "payload-file": {
5066
+ type: "string",
5067
+ description: "Path to a payload file to read (takes precedence over positional payload)"
5068
+ },
5069
+ message: {
5070
+ type: "string",
5071
+ description: "Optional Slack message"
5072
+ },
5073
+ severity: {
5074
+ type: "string",
5075
+ description: `Optional notification severity (${notificationSeverityValues.join(", ")})`
5076
+ },
5077
+ source: {
5078
+ type: "string",
5079
+ description: "Optional source label"
5080
+ },
5081
+ subject: {
5082
+ type: "string",
5083
+ description: "Optional subject line"
5084
+ }
5085
+ },
5086
+ async run({ args }) {
5087
+ const json = !!args.json;
5088
+ const title = args.title?.trim();
5089
+ if (!title) {
5090
+ return outputError({ message: "Provide --title", code: "missing_input" }, json);
5091
+ }
5092
+ if (title.length > 160) {
5093
+ return outputError({
5094
+ message: "--title must be 160 characters or fewer after trimming",
5095
+ code: "invalid_input"
5096
+ }, json);
5097
+ }
5098
+ const message = validateTrimmedText(args.message, 1200);
5099
+ if (message === null) {
5100
+ return outputError({
5101
+ message: "--message must be between 1 and 1200 characters after trimming",
5102
+ code: "invalid_input"
5103
+ }, json);
5104
+ }
5105
+ const source = validateTrimmedText(args.source, 120);
5106
+ if (source === null) {
5107
+ return outputError({
5108
+ message: "--source must be between 1 and 120 characters after trimming",
5109
+ code: "invalid_input"
5110
+ }, json);
5111
+ }
5112
+ const subject = validateTrimmedText(args.subject, 240);
5113
+ if (subject === null) {
5114
+ return outputError({
5115
+ message: "--subject must be between 1 and 240 characters after trimming",
5116
+ code: "invalid_input"
5117
+ }, json);
5118
+ }
5119
+ let severity;
5120
+ if (args.severity) {
5121
+ const normalized = normalizeSeverity(args.severity);
5122
+ if (!normalized) {
5123
+ return outputError({
5124
+ message: `--severity must be one of: ${notificationSeverityValues.join(", ")}`,
5125
+ code: "invalid_input"
5126
+ }, json);
5127
+ }
5128
+ severity = normalized;
5129
+ }
5130
+ let payloadInput;
5131
+ if (args["payload-file"]) {
5132
+ try {
5133
+ payloadInput = readFileSync5(args["payload-file"], "utf-8");
5134
+ } catch (err) {
5135
+ return outputError({
5136
+ message: `Cannot read file: ${errorMessage(err, "unknown error")}`,
5137
+ code: "file_error"
5138
+ }, json);
5139
+ }
5140
+ } else if (typeof args.payload === "string" && args.payload.trim().length > 0) {
5141
+ payloadInput = args.payload;
5142
+ } else {
5143
+ return outputError({ message: "Provide a payload or --payload-file", code: "missing_input" }, json);
5144
+ }
5145
+ const payload = parsePayload(payloadInput);
5146
+ if (!payloadSizeIsValid(payload)) {
5147
+ return outputError({
5148
+ message: "Payload must serialize to 100000 characters or fewer",
5149
+ code: "invalid_input"
5150
+ }, json);
5151
+ }
5152
+ const client = await getClientOrExit(args["api-key"], json);
5153
+ const params = {
5154
+ title,
5155
+ payload
5156
+ };
5157
+ if (message !== undefined) {
5158
+ params.message = message;
5159
+ }
5160
+ if (severity) {
5161
+ params.severity = severity;
5162
+ }
5163
+ if (source !== undefined) {
5164
+ params.source = source;
5165
+ }
5166
+ if (subject !== undefined) {
5167
+ params.subject = subject;
5168
+ }
5169
+ return runTool(client, customerToolContracts.outlit_send_notification.toolName, params, json);
5170
+ }
5171
+ });
5172
+ });
5173
+
4882
5174
  // src/commands/schema.ts
4883
5175
  var exports_schema = {};
4884
5176
  __export(exports_schema, {
@@ -6676,6 +6968,7 @@ Usage examples:
6676
6968
  outlit sources get --source-type CALL --source-id call_123
6677
6969
  outlit search 'pricing objections last quarter' --source-types CALL,EMAIL
6678
6970
  outlit sql 'SELECT * FROM events LIMIT 10'
6971
+ outlit notify --title 'Risk found' '{"customer":"acme.com"}'
6679
6972
  outlit schema events
6680
6973
  outlit doctor --json
6681
6974
 
@@ -6691,6 +6984,7 @@ For AI agents: commands auto-output JSON when stdout is piped. No --json flag ne
6691
6984
  sources: () => Promise.resolve().then(() => (init_sources(), exports_sources)).then((m) => m.default),
6692
6985
  search: () => Promise.resolve().then(() => (init_search(), exports_search)).then((m) => m.default),
6693
6986
  sql: () => Promise.resolve().then(() => (init_sql(), exports_sql)).then((m) => m.default),
6987
+ notify: () => Promise.resolve().then(() => (init_notify(), exports_notify)).then((m) => m.default),
6694
6988
  schema: () => Promise.resolve().then(() => (init_schema(), exports_schema)).then((m) => m.default),
6695
6989
  integrations: () => Promise.resolve().then(() => (init_integrations(), exports_integrations)).then((m) => m.default),
6696
6990
  completions: () => Promise.resolve().then(() => (init_completions(), exports_completions)).then((m) => m.default),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outlit/cli",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
4
4
  "description": "CLI for Outlit customer intelligence platform",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@clack/prompts": "^1.0.1",
34
- "@outlit/tools": "^0.1.0",
34
+ "@outlit/tools": "^0.1.1",
35
35
  "citty": "^0.2.1"
36
36
  },
37
37
  "devDependencies": {