@outlit/cli 1.6.4 → 1.7.1

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 +425 -74
  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.4",
107
+ version: "1.7.1",
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.3",
138
+ "@outlit/tools": "^0.2.1",
139
139
  citty: "^0.2.1"
140
140
  },
141
141
  devDependencies: {
@@ -1494,11 +1494,11 @@ function isCustomerToolName(value) {
1494
1494
  return customerToolNameSet.has(value);
1495
1495
  }
1496
1496
  function normalizeCustomerSourceType(value) {
1497
- const normalizedValue = value.trim().toUpperCase();
1498
- if (customerSourceTypeSet.has(normalizedValue)) {
1499
- return normalizedValue;
1497
+ const normalized = value.trim().toUpperCase();
1498
+ if (customerSourceTypeSet.has(normalized)) {
1499
+ return normalized;
1500
1500
  }
1501
- return customerSourceTypeAliasMap.get(normalizedValue) ?? null;
1501
+ return customerSourceTypeAliasMap.get(normalized) ?? null;
1502
1502
  }
1503
1503
  function resolveCustomerContextSearchInput(value) {
1504
1504
  if (!value.query) {
@@ -1602,7 +1602,7 @@ function createOutlitClient(options) {
1602
1602
  }
1603
1603
  };
1604
1604
  }
1605
- var customerToolNames, customerSourceTypes, customerSourceTypeAliases, customerSourceTypeInputs, customerToolContracts, customerBillingStatuses, customerFactStatuses, customerFactTypes, unsupportedCustomerFactTypes, customerFactCategories, customerIncludeSections, customerTimeframes, notificationSeverityValues, timelineChannels, timelineTimeframes, userJourneyStages, customerToolNameSet, customerSourceTypeSet, customerSourceTypeAliasMap, iso8601UtcDateTimeRegex, DEFAULT_OUTLIT_API_URL = "https://app.outlit.ai", actionToolNames, defaultAgentToolNames, sqlToolNames, analyticalAgentToolNames;
1605
+ var customerToolNames, customerSourceTypes, customerSourceTypeAliases, customerSourceTypeInputs, customerToolContracts, customerBillingStatuses, customerFactStatuses, customerFactTypes, unsupportedCustomerFactTypes, customerFactCategories, customerIncludeSections, customerTimeframes, notificationProviderValues, notificationSeverityValues, timelineChannels, timelineTimeframes, userJourneyStages, customerToolNameSet, customerSourceTypeSet, customerSourceTypeAliasMap, iso8601UtcDateTimeRegex, DEFAULT_OUTLIT_API_URL = "https://app.outlit.ai", actionToolNames, defaultAgentToolNames, sqlToolNames, analyticalAgentToolNames;
1606
1606
  var init_dist4 = __esm(() => {
1607
1607
  customerToolNames = [
1608
1608
  "outlit_list_customers",
@@ -1612,6 +1612,7 @@ var init_dist4 = __esm(() => {
1612
1612
  "outlit_list_facts",
1613
1613
  "outlit_get_fact",
1614
1614
  "outlit_get_source",
1615
+ "outlit_list_sources",
1615
1616
  "outlit_search_customer_context",
1616
1617
  "outlit_query",
1617
1618
  "outlit_schema",
@@ -2038,6 +2039,69 @@ var init_dist4 = __esm(() => {
2038
2039
  additionalProperties: false
2039
2040
  }
2040
2041
  },
2042
+ outlit_list_sources: {
2043
+ toolName: "outlit_list_sources",
2044
+ description: "List concrete source records deterministically. Use this instead of semantic search when you need enumerated calls, emails, calendar events, support tickets, or opportunities.",
2045
+ inputSchema: {
2046
+ $schema: "https://json-schema.org/draft/2020-12/schema",
2047
+ type: "object",
2048
+ properties: {
2049
+ sourceType: {
2050
+ description: "Generic source type to list.",
2051
+ type: "string",
2052
+ enum: customerSourceTypeInputs
2053
+ },
2054
+ customer: {
2055
+ description: "Customer ID, domain, or name to scope source listing.",
2056
+ type: "string",
2057
+ minLength: 1,
2058
+ maxLength: 200
2059
+ },
2060
+ after: {
2061
+ description: "ISO 8601 datetime lower bound.",
2062
+ type: "string",
2063
+ format: "date-time",
2064
+ pattern: "^(?:(?:\\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))$"
2065
+ },
2066
+ before: {
2067
+ description: "ISO 8601 datetime upper bound.",
2068
+ type: "string",
2069
+ format: "date-time",
2070
+ pattern: "^(?:(?:\\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))$"
2071
+ },
2072
+ participant: {
2073
+ description: "Participant email or name to filter source records.",
2074
+ type: "string",
2075
+ minLength: 1,
2076
+ maxLength: 500
2077
+ },
2078
+ provider: {
2079
+ description: "Provider identifier such as gmail, gong, or google-calendar.",
2080
+ type: "string",
2081
+ minLength: 1,
2082
+ maxLength: 200
2083
+ },
2084
+ hasTranscript: {
2085
+ description: "Filter call sources by transcript presence.",
2086
+ type: "boolean"
2087
+ },
2088
+ limit: {
2089
+ description: "Results per page.",
2090
+ default: 50,
2091
+ type: "integer",
2092
+ minimum: 1,
2093
+ maximum: 100
2094
+ },
2095
+ cursor: {
2096
+ description: "Pagination cursor.",
2097
+ type: "string",
2098
+ minLength: 1,
2099
+ maxLength: 2000
2100
+ }
2101
+ },
2102
+ additionalProperties: false
2103
+ }
2104
+ },
2041
2105
  outlit_search_customer_context: {
2042
2106
  toolName: "outlit_search_customer_context",
2043
2107
  description: "Search across all known customer context using a natural-language query. Returns grouped artifact-level results for matching sources and facts. Omit customer to search across all customers in the organization.",
@@ -2154,7 +2218,7 @@ Returns column definitions and example queries for each view.`,
2154
2218
  },
2155
2219
  outlit_send_notification: {
2156
2220
  toolName: "outlit_send_notification",
2157
- 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.",
2221
+ description: "Send or post a notification. Use only when the user explicitly asks you to send, post, or notify. Slack is the default notifier when destinations are omitted.",
2158
2222
  inputSchema: {
2159
2223
  $schema: "https://json-schema.org/draft/2020-12/schema",
2160
2224
  type: "object",
@@ -2165,41 +2229,18 @@ Returns column definitions and example queries for each view.`,
2165
2229
  maxLength: 160,
2166
2230
  description: "Notification title"
2167
2231
  },
2232
+ markdown: {
2233
+ description: "Markdown notification body rendered for the target provider",
2234
+ type: "string",
2235
+ minLength: 1,
2236
+ maxLength: 1e5
2237
+ },
2168
2238
  payload: {
2169
- description: "JSON-compatible payload rendered in Slack as a code block. Serialized size must be 100,000 characters or fewer.",
2170
- anyOf: [
2171
- {
2172
- type: "string"
2173
- },
2174
- {
2175
- type: "number"
2176
- },
2177
- {
2178
- type: "boolean"
2179
- },
2180
- {
2181
- type: "null"
2182
- },
2183
- {
2184
- type: "array",
2185
- items: {
2186
- $ref: "#/$defs/__schema0"
2187
- }
2188
- },
2189
- {
2190
- type: "object",
2191
- propertyNames: {
2192
- type: "string"
2193
- },
2194
- additionalProperties: {
2195
- $ref: "#/$defs/__schema0"
2196
- }
2197
- }
2198
- ],
2239
+ description: "Optional JSON-compatible payload. Serialized size must be 100,000 characters or fewer.",
2199
2240
  $ref: "#/$defs/__schema0"
2200
2241
  },
2201
2242
  message: {
2202
- description: "Optional Slack message",
2243
+ description: "Optional summary message",
2203
2244
  type: "string",
2204
2245
  minLength: 1,
2205
2246
  maxLength: 1200
@@ -2220,9 +2261,39 @@ Returns column definitions and example queries for each view.`,
2220
2261
  type: "string",
2221
2262
  minLength: 1,
2222
2263
  maxLength: 240
2264
+ },
2265
+ destinations: {
2266
+ description: "Optional explicit notification destinations. Omit to use the default notifier.",
2267
+ minItems: 1,
2268
+ maxItems: 10,
2269
+ type: "array",
2270
+ items: {
2271
+ type: "object",
2272
+ properties: {
2273
+ provider: {
2274
+ description: "Notification provider",
2275
+ type: "string",
2276
+ enum: ["slack"]
2277
+ },
2278
+ channelId: {
2279
+ description: "Provider-specific destination channel ID",
2280
+ type: "string",
2281
+ minLength: 1,
2282
+ maxLength: 240
2283
+ },
2284
+ label: {
2285
+ description: "Optional destination label",
2286
+ type: "string",
2287
+ minLength: 1,
2288
+ maxLength: 120
2289
+ }
2290
+ },
2291
+ required: ["provider"],
2292
+ additionalProperties: false
2293
+ }
2223
2294
  }
2224
2295
  },
2225
- required: ["title", "payload"],
2296
+ required: ["title"],
2226
2297
  additionalProperties: false,
2227
2298
  $defs: {
2228
2299
  __schema0: {
@@ -2313,6 +2384,7 @@ Returns column definitions and example queries for each view.`,
2313
2384
  "behaviorMetrics"
2314
2385
  ];
2315
2386
  customerTimeframes = ["7d", "14d", "30d", "90d"];
2387
+ notificationProviderValues = ["slack"];
2316
2388
  notificationSeverityValues = ["low", "medium", "high"];
2317
2389
  timelineChannels = [
2318
2390
  "SDK",
@@ -2533,10 +2605,12 @@ function renderTable(headers, rows, emptyMessage = "(no results)") {
2533
2605
  function renderPaginationHint(pagination, itemCount) {
2534
2606
  if (itemCount === 0)
2535
2607
  return "";
2608
+ const total = typeof pagination.total === "number" ? pagination.total : null;
2536
2609
  if (pagination.hasMore && pagination.nextCursor) {
2537
- return `Showing ${itemCount} of ${pagination.total} total. Next page: --cursor ${pagination.nextCursor}`;
2610
+ const countLabel = total === null ? `${itemCount} results` : `${itemCount} of ${total} total`;
2611
+ return `Showing ${countLabel}. Next page: --cursor ${pagination.nextCursor}`;
2538
2612
  }
2539
- return `Showing all ${pagination.total} results.`;
2613
+ return total === null ? `Showing ${itemCount} results.` : `Showing all ${total} results.`;
2540
2614
  }
2541
2615
  var BOX;
2542
2616
  var init_table = __esm(() => {
@@ -2593,10 +2667,11 @@ async function pingApiKey(apiKey) {
2593
2667
  const message = payload?.error ?? (text.length > 0 ? text : `API error (${response.status})`);
2594
2668
  throw new Error(message);
2595
2669
  }
2670
+ return payload;
2596
2671
  }
2597
2672
  async function validateKeyOrExit(apiKey, json) {
2598
2673
  try {
2599
- await pingApiKey(apiKey);
2674
+ return await pingApiKey(apiKey);
2600
2675
  } catch (err) {
2601
2676
  return outputError({
2602
2677
  message: `API key is invalid or expired: ${errorMessage(err, "unknown error")}`,
@@ -2923,9 +2998,18 @@ var init_whoami = __esm(() => {
2923
2998
  const json = !!args.json;
2924
2999
  const credential = requireCredential(args["api-key"], json);
2925
3000
  const masked = maskKey(credential.key);
2926
- await validateKeyOrExit(credential.key, json);
3001
+ const validation = await validateKeyOrExit(credential.key, json);
2927
3002
  if (isJsonMode(json)) {
2928
- return outputResult({ key: masked, source: credential.source, valid: true });
3003
+ return outputResult({
3004
+ key: masked,
3005
+ source: credential.source,
3006
+ valid: true,
3007
+ organizationId: validation.organizationId,
3008
+ createdById: validation.createdById,
3009
+ organization: validation.organization,
3010
+ createdBy: validation.createdBy,
3011
+ apiKey: validation.apiKey
3012
+ });
2929
3013
  }
2930
3014
  process.stdout.write(`${masked} (${credential.source})
2931
3015
  `);
@@ -4869,12 +4953,183 @@ var init_facts = __esm(() => {
4869
4953
  });
4870
4954
  });
4871
4955
 
4956
+ // src/commands/sources/list.ts
4957
+ var exports_list4 = {};
4958
+ __export(exports_list4, {
4959
+ default: () => list_default4
4960
+ });
4961
+ function parseLimit(value, json) {
4962
+ if (!value)
4963
+ return;
4964
+ const limit = Number(value);
4965
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
4966
+ outputError({
4967
+ message: `--limit must be an integer between 1 and 100 (got: ${value})`,
4968
+ code: "invalid_input"
4969
+ }, json);
4970
+ return;
4971
+ }
4972
+ return limit;
4973
+ }
4974
+ function parseDateArg(name, value, json) {
4975
+ if (!value)
4976
+ return null;
4977
+ if (!ISO_8601_UTC_DATE_TIME_REGEX.test(value)) {
4978
+ outputError({
4979
+ message: `${name} must be a valid ISO 8601 UTC datetime`,
4980
+ code: "invalid_input"
4981
+ }, json);
4982
+ return null;
4983
+ }
4984
+ const date = new Date(value);
4985
+ if (Number.isNaN(date.getTime())) {
4986
+ outputError({
4987
+ message: `${name} must be a valid ISO 8601 datetime`,
4988
+ code: "invalid_input"
4989
+ }, json);
4990
+ return null;
4991
+ }
4992
+ return date;
4993
+ }
4994
+ var sourceTypeDescription2, ISO_8601_UTC_DATE_TIME_REGEX, list_default4;
4995
+ var init_list4 = __esm(() => {
4996
+ init_dist4();
4997
+ init_dist();
4998
+ init_auth();
4999
+ init_output2();
5000
+ init_api();
5001
+ init_output();
5002
+ sourceTypeDescription2 = `${customerSourceTypes.join(", ")} (aliases: ${customerSourceTypeAliases.join(", ")})`;
5003
+ ISO_8601_UTC_DATE_TIME_REGEX = /^(?:(?:\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))$/;
5004
+ list_default4 = defineCommand2({
5005
+ meta: {
5006
+ name: "list",
5007
+ description: [
5008
+ "List concrete source records deterministically.",
5009
+ "",
5010
+ "Use this when you need enumerated calls, emails, calendar events, support tickets, or opportunities rather than semantic ranking.",
5011
+ "",
5012
+ "Examples:",
5013
+ " outlit sources list --customer acme.com --source-type CALL",
5014
+ " outlit sources list --participant alice@acme.com --source-type CALENDAR_EVENT --json",
5015
+ " outlit sources list --after 2026-01-01T00:00:00Z --limit 25",
5016
+ "",
5017
+ `Source types: ${sourceTypeDescription2}`,
5018
+ "",
5019
+ AGENT_JSON_HINT
5020
+ ].join(`
5021
+ `)
5022
+ },
5023
+ args: {
5024
+ ...authArgs,
5025
+ ...outputArgs,
5026
+ "source-type": {
5027
+ type: "string",
5028
+ description: `Source type (${sourceTypeDescription2})`
5029
+ },
5030
+ customer: {
5031
+ type: "string",
5032
+ description: "Customer UUID, domain, or name to scope source listing"
5033
+ },
5034
+ participant: {
5035
+ type: "string",
5036
+ description: "Participant email or name to filter source records"
5037
+ },
5038
+ provider: {
5039
+ type: "string",
5040
+ description: "Provider identifier such as gmail, gong, or google-calendar"
5041
+ },
5042
+ "has-transcript": {
5043
+ type: "boolean",
5044
+ description: "Only list call sources with a finalized transcript"
5045
+ },
5046
+ after: {
5047
+ type: "string",
5048
+ description: "Filter to sources occurring after this ISO 8601 datetime"
5049
+ },
5050
+ before: {
5051
+ type: "string",
5052
+ description: "Filter to sources occurring before this ISO 8601 datetime"
5053
+ },
5054
+ limit: {
5055
+ type: "string",
5056
+ description: "Results per page (1-100). Default: 50."
5057
+ },
5058
+ cursor: {
5059
+ type: "string",
5060
+ description: "Pagination cursor from a previous response (pagination.nextCursor)"
5061
+ }
5062
+ },
5063
+ async run({ args }) {
5064
+ const json = !!args.json;
5065
+ const sourceType = args["source-type"] ? normalizeCustomerSourceType(args["source-type"]) : undefined;
5066
+ if (args["source-type"] && !sourceType) {
5067
+ return outputError({
5068
+ message: `--source-type must be one of ${customerSourceTypeInputs.join(", ")}`,
5069
+ code: "invalid_input"
5070
+ }, json);
5071
+ }
5072
+ if (args["has-transcript"] && sourceType && sourceType !== "CALL") {
5073
+ return outputError({
5074
+ message: "--has-transcript can only be used with CALL sources",
5075
+ code: "invalid_input"
5076
+ }, json);
5077
+ }
5078
+ const afterDate = parseDateArg("--after", args.after, json);
5079
+ if (args.after && !afterDate)
5080
+ return;
5081
+ const beforeDate = parseDateArg("--before", args.before, json);
5082
+ if (args.before && !beforeDate)
5083
+ return;
5084
+ if (afterDate && beforeDate && afterDate.getTime() > beforeDate.getTime()) {
5085
+ return outputError({
5086
+ message: "--after must be before or equal to --before",
5087
+ code: "invalid_input"
5088
+ }, json);
5089
+ }
5090
+ const limit = parseLimit(args.limit, json);
5091
+ if (args.limit && !limit)
5092
+ return;
5093
+ const client = await getClientOrExit(args["api-key"], json);
5094
+ const params = {};
5095
+ if (sourceType)
5096
+ params.sourceType = sourceType;
5097
+ if (args.customer)
5098
+ params.customer = args.customer;
5099
+ if (args.participant)
5100
+ params.participant = args.participant;
5101
+ if (args.provider)
5102
+ params.provider = args.provider;
5103
+ if (args["has-transcript"])
5104
+ params.hasTranscript = true;
5105
+ if (args.after)
5106
+ params.after = args.after;
5107
+ if (args.before)
5108
+ params.before = args.before;
5109
+ if (limit)
5110
+ params.limit = limit;
5111
+ if (args.cursor)
5112
+ params.cursor = args.cursor;
5113
+ return runTool(client, customerToolContracts.outlit_list_sources.toolName, params, json, {
5114
+ table: {
5115
+ columns: [
5116
+ { header: "TYPE", key: "sourceType" },
5117
+ { header: "OCCURRED", key: "occurredAt" },
5118
+ { header: "TITLE", key: "title" },
5119
+ { header: "SOURCE ID", key: "sourceId" }
5120
+ ]
5121
+ }
5122
+ });
5123
+ }
5124
+ });
5125
+ });
5126
+
4872
5127
  // src/commands/sources/get.ts
4873
5128
  var exports_get3 = {};
4874
5129
  __export(exports_get3, {
4875
5130
  default: () => get_default3
4876
5131
  });
4877
- var sourceTypeDescription2, get_default3;
5132
+ var sourceTypeDescription3, get_default3;
4878
5133
  var init_get3 = __esm(() => {
4879
5134
  init_dist4();
4880
5135
  init_dist();
@@ -4882,19 +5137,21 @@ var init_get3 = __esm(() => {
4882
5137
  init_output2();
4883
5138
  init_api();
4884
5139
  init_output();
4885
- sourceTypeDescription2 = `${customerSourceTypes.join(", ")} (aliases: ${customerSourceTypeAliases.join(", ")})`;
5140
+ sourceTypeDescription3 = `${customerSourceTypes.join(", ")} (aliases: ${customerSourceTypeAliases.join(", ")})`;
4886
5141
  get_default3 = defineCommand2({
4887
5142
  meta: {
4888
5143
  name: "get",
4889
5144
  description: [
4890
5145
  "Get one exact source by source type and source id.",
5146
+ "Returns the same normalized source envelope as `sources list`, with more detailed source-specific fields when available.",
4891
5147
  "",
4892
5148
  "Examples:",
4893
5149
  " outlit sources get --source-type CALL --source-id call_123",
4894
5150
  " outlit sources get --source-type OPPORTUNITY --source-id opp_123",
4895
5151
  " outlit sources get --source-type SUPPORT_TICKET --source-id ticket_456 --json",
4896
5152
  "",
4897
- `Source types: ${sourceTypeDescription2}`,
5153
+ `Source types: ${sourceTypeDescription3}`,
5154
+ "Use `outlit sources list` when you need deterministic enumeration rather than exact lookup.",
4898
5155
  "",
4899
5156
  AGENT_JSON_HINT
4900
5157
  ].join(`
@@ -4905,7 +5162,7 @@ var init_get3 = __esm(() => {
4905
5162
  ...outputArgs,
4906
5163
  "source-type": {
4907
5164
  type: "string",
4908
- description: `Source type (${sourceTypeDescription2})`,
5165
+ description: `Source type (${sourceTypeDescription3})`,
4909
5166
  required: true
4910
5167
  },
4911
5168
  "source-id": {
@@ -4945,9 +5202,10 @@ var init_sources = __esm(() => {
4945
5202
  meta: {
4946
5203
  name: "sources",
4947
5204
  description: [
4948
- "Fetch concrete customer sources by type and id.",
5205
+ "List or fetch concrete customer source records.",
4949
5206
  "",
4950
5207
  "Subcommands:",
5208
+ " list -- list source records with deterministic filters",
4951
5209
  " get -- fetch one exact source by sourceType and sourceId",
4952
5210
  "",
4953
5211
  AGENT_JSON_HINT
@@ -4955,6 +5213,7 @@ var init_sources = __esm(() => {
4955
5213
  `)
4956
5214
  },
4957
5215
  subCommands: {
5216
+ list: () => Promise.resolve().then(() => (init_list4(), exports_list4)).then((m) => m.default),
4958
5217
  get: () => Promise.resolve().then(() => (init_get3(), exports_get3)).then((m) => m.default)
4959
5218
  }
4960
5219
  });
@@ -4965,7 +5224,7 @@ var exports_search = {};
4965
5224
  __export(exports_search, {
4966
5225
  default: () => search_default
4967
5226
  });
4968
- var sourceTypeDescription3, search_default;
5227
+ var sourceTypeDescription4, search_default;
4969
5228
  var init_search = __esm(() => {
4970
5229
  init_dist4();
4971
5230
  init_dist();
@@ -4974,7 +5233,7 @@ var init_search = __esm(() => {
4974
5233
  init_api();
4975
5234
  init_config();
4976
5235
  init_output();
4977
- sourceTypeDescription3 = `${customerSourceTypes.join(", ")} (aliases: ${customerSourceTypeAliases.join(", ")})`;
5236
+ sourceTypeDescription4 = `${customerSourceTypes.join(", ")} (aliases: ${customerSourceTypeAliases.join(", ")})`;
4978
5237
  search_default = defineCommand2({
4979
5238
  meta: {
4980
5239
  name: "search",
@@ -4982,6 +5241,7 @@ var init_search = __esm(() => {
4982
5241
  "Search customer context using natural language.",
4983
5242
  "",
4984
5243
  "Performs a semantic search over grouped source and fact results.",
5244
+ "Use `outlit sources list` when you need deterministic source enumeration rather than semantic ranking.",
4985
5245
  "Optionally scope to a specific customer with --customer.",
4986
5246
  "",
4987
5247
  "Examples:",
@@ -5021,7 +5281,7 @@ var init_search = __esm(() => {
5021
5281
  },
5022
5282
  "source-types": {
5023
5283
  type: "string",
5024
- description: `Comma-separated generic source type filter (${sourceTypeDescription3})`
5284
+ description: `Comma-separated generic source type filter (${sourceTypeDescription4})`
5025
5285
  }
5026
5286
  },
5027
5287
  async run({ args }) {
@@ -5162,7 +5422,33 @@ function payloadSizeIsValid(payload) {
5162
5422
  const serialized = JSON.stringify(payload);
5163
5423
  return typeof serialized === "string" && serialized.length <= 1e5;
5164
5424
  }
5165
- var notify_default;
5425
+ function parseDestinations(raw) {
5426
+ if (raw === undefined) {
5427
+ return;
5428
+ }
5429
+ const destinations = raw.split(",").map((entry) => entry.trim());
5430
+ if (destinations.length > MAX_DESTINATION_COUNT || destinations.some((entry) => entry.length === 0)) {
5431
+ return null;
5432
+ }
5433
+ const parsed = [];
5434
+ for (const destination of destinations) {
5435
+ const [providerInput, ...channelParts] = destination.split(":");
5436
+ const provider = providerInput?.trim().toLowerCase();
5437
+ const channelId = channelParts.join(":").trim();
5438
+ if (!notificationProviderValues.includes(provider)) {
5439
+ return null;
5440
+ }
5441
+ if (channelId.length > MAX_DESTINATION_CHANNEL_ID_LENGTH) {
5442
+ return null;
5443
+ }
5444
+ parsed.push({
5445
+ provider,
5446
+ ...channelId.length > 0 ? { channelId } : {}
5447
+ });
5448
+ }
5449
+ return parsed;
5450
+ }
5451
+ var MAX_DESTINATION_COUNT = 10, MAX_DESTINATION_CHANNEL_ID_LENGTH = 240, notify_default;
5166
5452
  var init_notify = __esm(() => {
5167
5453
  init_dist4();
5168
5454
  init_dist();
@@ -5174,14 +5460,16 @@ var init_notify = __esm(() => {
5174
5460
  meta: {
5175
5461
  name: "notify",
5176
5462
  description: [
5177
- "Send a Slack notification through Outlit.",
5463
+ "Send a notification through Outlit to the organization's configured notifier.",
5178
5464
  "",
5179
- "Provide the payload as a positional argument or via --payload-file.",
5180
- "When both are provided, --payload-file takes precedence.",
5465
+ "Use --markdown or --markdown-file for the human-readable body; Outlit renders it for the destination platform.",
5466
+ "Add a JSON or raw payload when useful for structured context. When --destination is omitted, Outlit uses the default notifier.",
5181
5467
  "",
5182
5468
  "Examples:",
5469
+ " outlit notify --title 'Risk found' --markdown '**Risk found**\\n\\n- Customer: acme.com'",
5183
5470
  ` outlit notify --title 'Risk found' '{"customer":"acme.com"}'`,
5184
5471
  " outlit notify --title 'Risk found' --payload-file ./payload.json",
5472
+ " outlit notify --title 'Escalation' --markdown '**Check this account**' --destination slack:C123",
5185
5473
  ` outlit notify --title 'Escalation' --severity HIGH --message 'Check this account' '{"customer":"acme.com"}'`,
5186
5474
  "",
5187
5475
  AGENT_JSON_HINT
@@ -5205,9 +5493,17 @@ var init_notify = __esm(() => {
5205
5493
  type: "string",
5206
5494
  description: "Path to a payload file to read (takes precedence over positional payload)"
5207
5495
  },
5496
+ markdown: {
5497
+ type: "string",
5498
+ description: "Markdown body rendered for the destination platform."
5499
+ },
5500
+ "markdown-file": {
5501
+ type: "string",
5502
+ description: "Path to a markdown file to render for the destination platform."
5503
+ },
5208
5504
  message: {
5209
5505
  type: "string",
5210
- description: "Optional Slack message"
5506
+ description: "Optional summary message"
5211
5507
  },
5212
5508
  severity: {
5213
5509
  type: "string",
@@ -5220,6 +5516,10 @@ var init_notify = __esm(() => {
5220
5516
  subject: {
5221
5517
  type: "string",
5222
5518
  description: "Optional subject line"
5519
+ },
5520
+ destination: {
5521
+ type: "string",
5522
+ description: "Optional comma-separated destinations in provider[:channelId] form. Supported provider: slack"
5223
5523
  }
5224
5524
  },
5225
5525
  async run({ args }) {
@@ -5234,6 +5534,24 @@ var init_notify = __esm(() => {
5234
5534
  code: "invalid_input"
5235
5535
  }, json);
5236
5536
  }
5537
+ let markdownInput = args.markdown;
5538
+ if (args["markdown-file"]) {
5539
+ try {
5540
+ markdownInput = readFileSync5(args["markdown-file"], "utf-8");
5541
+ } catch (err) {
5542
+ return outputError({
5543
+ message: `Cannot read markdown file: ${errorMessage(err, "unknown error")}`,
5544
+ code: "file_error"
5545
+ }, json);
5546
+ }
5547
+ }
5548
+ const markdown = validateTrimmedText(markdownInput, 1e5);
5549
+ if (markdown === null) {
5550
+ return outputError({
5551
+ message: "--markdown must be between 1 and 100000 characters after trimming",
5552
+ code: "invalid_input"
5553
+ }, json);
5554
+ }
5237
5555
  const message = validateTrimmedText(args.message, 1200);
5238
5556
  if (message === null) {
5239
5557
  return outputError({
@@ -5266,6 +5584,13 @@ var init_notify = __esm(() => {
5266
5584
  }
5267
5585
  severity = normalized;
5268
5586
  }
5587
+ const destinations = parseDestinations(args.destination);
5588
+ if (destinations === null) {
5589
+ return outputError({
5590
+ message: `--destination must use provider[:channelId] with provider one of: ${notificationProviderValues.join(", ")}`,
5591
+ code: "invalid_input"
5592
+ }, json);
5593
+ }
5269
5594
  let payloadInput;
5270
5595
  if (args["payload-file"]) {
5271
5596
  try {
@@ -5278,11 +5603,15 @@ var init_notify = __esm(() => {
5278
5603
  }
5279
5604
  } else if (typeof args.payload === "string" && args.payload.trim().length > 0) {
5280
5605
  payloadInput = args.payload;
5281
- } else {
5282
- return outputError({ message: "Provide a payload or --payload-file", code: "missing_input" }, json);
5283
5606
  }
5284
- const payload = parsePayload(payloadInput);
5285
- if (!payloadSizeIsValid(payload)) {
5607
+ if (!payloadInput && markdown === undefined) {
5608
+ return outputError({
5609
+ message: "Provide --markdown, --markdown-file, a payload, or --payload-file",
5610
+ code: "missing_input"
5611
+ }, json);
5612
+ }
5613
+ const payload = payloadInput === undefined ? undefined : parsePayload(payloadInput);
5614
+ if (payload !== undefined && !payloadSizeIsValid(payload)) {
5286
5615
  return outputError({
5287
5616
  message: "Payload must serialize to 100000 characters or fewer",
5288
5617
  code: "invalid_input"
@@ -5290,9 +5619,14 @@ var init_notify = __esm(() => {
5290
5619
  }
5291
5620
  const client = await getClientOrExit(args["api-key"], json);
5292
5621
  const params = {
5293
- title,
5294
- payload
5622
+ title
5295
5623
  };
5624
+ if (markdown !== undefined) {
5625
+ params.markdown = markdown;
5626
+ }
5627
+ if (payload !== undefined) {
5628
+ params.payload = payload;
5629
+ }
5296
5630
  if (message !== undefined) {
5297
5631
  params.message = message;
5298
5632
  }
@@ -5305,6 +5639,9 @@ var init_notify = __esm(() => {
5305
5639
  if (subject !== undefined) {
5306
5640
  params.subject = subject;
5307
5641
  }
5642
+ if (destinations !== undefined) {
5643
+ params.destinations = destinations;
5644
+ }
5308
5645
  return runTool(client, customerToolContracts.outlit_send_notification.toolName, params, json);
5309
5646
  }
5310
5647
  });
@@ -5463,17 +5800,17 @@ var init_providers = __esm(() => {
5463
5800
  });
5464
5801
 
5465
5802
  // src/commands/integrations/list.ts
5466
- var exports_list4 = {};
5467
- __export(exports_list4, {
5468
- default: () => list_default4
5803
+ var exports_list5 = {};
5804
+ __export(exports_list5, {
5805
+ default: () => list_default5
5469
5806
  });
5470
- var list_default4;
5471
- var init_list4 = __esm(() => {
5807
+ var list_default5;
5808
+ var init_list5 = __esm(() => {
5472
5809
  init_dist();
5473
5810
  init_auth();
5474
5811
  init_output2();
5475
5812
  init_api();
5476
- list_default4 = defineCommand2({
5813
+ list_default5 = defineCommand2({
5477
5814
  meta: {
5478
5815
  name: "list",
5479
5816
  description: [
@@ -5947,7 +6284,7 @@ var init_integrations = __esm(() => {
5947
6284
  `)
5948
6285
  },
5949
6286
  subCommands: {
5950
- list: () => Promise.resolve().then(() => (init_list4(), exports_list4)).then((m) => m.default),
6287
+ list: () => Promise.resolve().then(() => (init_list5(), exports_list5)).then((m) => m.default),
5951
6288
  add: () => Promise.resolve().then(() => (init_add(), exports_add)).then((m) => m.default),
5952
6289
  remove: () => Promise.resolve().then(() => (init_remove(), exports_remove)).then((m) => m.default),
5953
6290
  status: () => Promise.resolve().then(() => (init_status2(), exports_status2)).then((m) => m.default)
@@ -6152,8 +6489,8 @@ function generateFish() {
6152
6489
  }
6153
6490
  }
6154
6491
  }
6155
- return lines.join(`
6156
- `) + `
6492
+ return `${lines.join(`
6493
+ `)}
6157
6494
  `;
6158
6495
  }
6159
6496
  var JSON_F, API_KEY_F, LIMIT_F, CURSOR_F, COMMON, PAGINATED, ACTIVITY_ORDER, COMMANDS, cmdsWithSubs, leafCmds, SCRIPTS, completions_default;
@@ -6276,8 +6613,22 @@ var init_completions = __esm(() => {
6276
6613
  },
6277
6614
  {
6278
6615
  name: "sources",
6279
- desc: "Get a concrete source by type and id",
6616
+ desc: "List or fetch concrete source records",
6280
6617
  subs: [
6618
+ {
6619
+ name: "list",
6620
+ desc: "List source records",
6621
+ flags: [
6622
+ ...PAGINATED,
6623
+ { name: "--source-type", desc: "Source type" },
6624
+ { name: "--customer", desc: "Scope to customer" },
6625
+ { name: "--participant", desc: "Filter by participant" },
6626
+ { name: "--provider", desc: "Filter by provider" },
6627
+ { name: "--has-transcript", desc: "Only calls with transcripts" },
6628
+ { name: "--after", desc: "Sources after date (ISO 8601)" },
6629
+ { name: "--before", desc: "Sources before date (ISO 8601)" }
6630
+ ]
6631
+ },
6281
6632
  {
6282
6633
  name: "get",
6283
6634
  desc: "Get one exact source record",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outlit/cli",
3
- "version": "1.6.4",
3
+ "version": "1.7.1",
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.3",
34
+ "@outlit/tools": "^0.2.1",
35
35
  "citty": "^0.2.1"
36
36
  },
37
37
  "devDependencies": {