@outlit/cli 1.6.2 → 1.6.4

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 +258 -89
  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.2",
107
+ version: "1.6.4",
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.1",
138
+ "@outlit/tools": "^0.1.3",
139
139
  citty: "^0.2.1"
140
140
  },
141
141
  devDependencies: {
@@ -1493,6 +1493,13 @@ var init_signup = __esm(() => {
1493
1493
  function isCustomerToolName(value) {
1494
1494
  return customerToolNameSet.has(value);
1495
1495
  }
1496
+ function normalizeCustomerSourceType(value) {
1497
+ const normalizedValue = value.trim().toUpperCase();
1498
+ if (customerSourceTypeSet.has(normalizedValue)) {
1499
+ return normalizedValue;
1500
+ }
1501
+ return customerSourceTypeAliasMap.get(normalizedValue) ?? null;
1502
+ }
1496
1503
  function resolveCustomerContextSearchInput(value) {
1497
1504
  if (!value.query) {
1498
1505
  return {
@@ -1539,6 +1546,14 @@ function resolveCustomerContextSearchInput(value) {
1539
1546
  message: "--after must be before or equal to --before"
1540
1547
  };
1541
1548
  }
1549
+ const invalidSourceTypes = value.sourceTypes?.filter((sourceType) => !normalizeCustomerSourceType(sourceType)) ?? [];
1550
+ if (invalidSourceTypes.length > 0) {
1551
+ return {
1552
+ ok: false,
1553
+ message: `Unknown source types: ${invalidSourceTypes.join(", ")}. Allowed: ${customerSourceTypeInputs.join(", ")}`
1554
+ };
1555
+ }
1556
+ const normalizedSourceTypes = value.sourceTypes ? Array.from(new Set(value.sourceTypes.map((sourceType) => normalizeCustomerSourceType(sourceType)))).filter((sourceType) => sourceType !== null) : undefined;
1542
1557
  return {
1543
1558
  ok: true,
1544
1559
  request: {
@@ -1547,7 +1562,7 @@ function resolveCustomerContextSearchInput(value) {
1547
1562
  topK: value.topK,
1548
1563
  after: value.after,
1549
1564
  before: value.before,
1550
- sourceTypes: value.sourceTypes
1565
+ sourceTypes: normalizedSourceTypes
1551
1566
  }
1552
1567
  };
1553
1568
  }
@@ -1587,7 +1602,7 @@ function createOutlitClient(options) {
1587
1602
  }
1588
1603
  };
1589
1604
  }
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;
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;
1591
1606
  var init_dist4 = __esm(() => {
1592
1607
  customerToolNames = [
1593
1608
  "outlit_list_customers",
@@ -1602,6 +1617,23 @@ var init_dist4 = __esm(() => {
1602
1617
  "outlit_schema",
1603
1618
  "outlit_send_notification"
1604
1619
  ];
1620
+ customerSourceTypes = [
1621
+ "EMAIL",
1622
+ "CALL",
1623
+ "CALENDAR_EVENT",
1624
+ "SUPPORT_TICKET",
1625
+ "OPPORTUNITY"
1626
+ ];
1627
+ customerSourceTypeAliases = ["CRM", "CRM_OPPORTUNITY"];
1628
+ customerSourceTypeInputs = [
1629
+ "EMAIL",
1630
+ "CALL",
1631
+ "CALENDAR_EVENT",
1632
+ "SUPPORT_TICKET",
1633
+ "OPPORTUNITY",
1634
+ "CRM",
1635
+ "CRM_OPPORTUNITY"
1636
+ ];
1605
1637
  customerToolContracts = {
1606
1638
  outlit_list_customers: {
1607
1639
  toolName: "outlit_list_customers",
@@ -1812,11 +1844,21 @@ var init_dist4 = __esm(() => {
1812
1844
  description: "Customer ID or domain"
1813
1845
  },
1814
1846
  channels: {
1815
- description: "Filter by event channel (e.g., EMAIL, SLACK, CALL)",
1847
+ description: "Filter by event channel (e.g., EMAIL, SLACK, CALL, CALENDAR)",
1816
1848
  type: "array",
1817
1849
  items: {
1818
1850
  type: "string",
1819
- enum: ["SDK", "EMAIL", "SLACK", "CALL", "CRM", "BILLING", "SUPPORT", "INTERNAL"]
1851
+ enum: [
1852
+ "SDK",
1853
+ "EMAIL",
1854
+ "SLACK",
1855
+ "CALL",
1856
+ "CALENDAR",
1857
+ "CRM",
1858
+ "BILLING",
1859
+ "SUPPORT",
1860
+ "INTERNAL"
1861
+ ]
1820
1862
  }
1821
1863
  },
1822
1864
  eventTypes: {
@@ -1883,7 +1925,7 @@ var init_dist4 = __esm(() => {
1883
1925
  type: "array",
1884
1926
  items: {
1885
1927
  type: "string",
1886
- enum: ["EMAIL", "CALL", "CALENDAR_EVENT", "SUPPORT_TICKET"]
1928
+ enum: customerSourceTypeInputs
1887
1929
  }
1888
1930
  },
1889
1931
  factTypes: {
@@ -1984,7 +2026,7 @@ var init_dist4 = __esm(() => {
1984
2026
  properties: {
1985
2027
  sourceType: {
1986
2028
  type: "string",
1987
- enum: ["EMAIL", "CALL", "CALENDAR_EVENT", "SUPPORT_TICKET"]
2029
+ enum: customerSourceTypeInputs
1988
2030
  },
1989
2031
  sourceId: {
1990
2032
  type: "string",
@@ -2045,7 +2087,7 @@ var init_dist4 = __esm(() => {
2045
2087
  type: "array",
2046
2088
  items: {
2047
2089
  type: "string",
2048
- enum: ["EMAIL", "CALL", "CALENDAR_EVENT", "SUPPORT_TICKET"]
2090
+ enum: customerSourceTypeInputs
2049
2091
  }
2050
2092
  }
2051
2093
  },
@@ -2055,21 +2097,22 @@ var init_dist4 = __esm(() => {
2055
2097
  },
2056
2098
  outlit_query: {
2057
2099
  toolName: "outlit_query",
2058
- description: `Execute raw SQL queries against your analytics data.
2100
+ description: `Execute read-only SQL queries against your analytics views.
2059
2101
 
2060
- Available tables:
2061
- - events: Customer activity events (event_name, event_type, event_channel, customer_id, occurred_at, properties, ...)
2062
- - customer_dimensions: Customer attributes (customer_id, domain, name, billing_status, plan, mrr_cents, ...)
2063
- - user_dimensions: User attributes (user_id, email, name, customer_id, ...)
2064
- - mrr_snapshots: Revenue snapshots over time (customer_id, snapshot_date, mrr_cents, ...)
2102
+ Available views:
2103
+ - activity: Customer activity events (event_name, event_type, event_channel, customer_id, occurred_at, properties, ...)
2104
+ - customers: Customer attributes (customer_id, domain, name, billing_status, plan, mrr_cents, traits, ...)
2105
+ - users: User attributes (user_id, email, name, customer_id, traits, ...)
2106
+ - revenue: Revenue snapshots over time (customer_id, snapshot_date, mrr_cents, ...)
2065
2107
 
2066
2108
  All queries are automatically filtered to your organization's data.
2067
2109
  Only SELECT queries are allowed.
2110
+ Properties and traits are JSON strings; inspect schemas and examples before filtering nested values.
2068
2111
 
2069
2112
  Example queries:
2070
- - SELECT event_name, count(*) FROM events GROUP BY 1 ORDER BY 2 DESC LIMIT 10
2071
- - SELECT billing_status, sum(mrr_cents)/100 as mrr FROM customer_dimensions GROUP BY 1
2072
- - SELECT * FROM events WHERE customer_id = 'cust_123' ORDER BY occurred_at DESC LIMIT 50`,
2113
+ - SELECT event_name, count(*) FROM activity GROUP BY 1 ORDER BY 2 DESC LIMIT 10
2114
+ - SELECT billing_status, sum(mrr_cents)/100 as mrr FROM customers GROUP BY 1
2115
+ - SELECT * FROM activity WHERE customer_id = 'cust_123' ORDER BY occurred_at DESC LIMIT 50`,
2073
2116
  inputSchema: {
2074
2117
  $schema: "https://json-schema.org/draft/2020-12/schema",
2075
2118
  type: "object",
@@ -2081,7 +2124,8 @@ Example queries:
2081
2124
  limit: {
2082
2125
  description: "Max rows to return (default 1000, max 10000)",
2083
2126
  default: 1000,
2084
- type: "number",
2127
+ type: "integer",
2128
+ minimum: 1,
2085
2129
  maximum: 1e4
2086
2130
  }
2087
2131
  },
@@ -2091,18 +2135,18 @@ Example queries:
2091
2135
  },
2092
2136
  outlit_schema: {
2093
2137
  toolName: "outlit_schema",
2094
- description: `Get table schemas for available analytics tables.
2138
+ description: `Get schemas for available analytics views.
2095
2139
 
2096
2140
  Use this to discover column names, types, and descriptions before writing SQL queries.
2097
- Returns column definitions and example queries for each table.`,
2141
+ Returns column definitions and example queries for each view.`,
2098
2142
  inputSchema: {
2099
2143
  $schema: "https://json-schema.org/draft/2020-12/schema",
2100
2144
  type: "object",
2101
2145
  properties: {
2102
2146
  table: {
2103
- description: "Specific table to describe, or omit for all tables",
2147
+ description: "Specific analytics view to describe. Omit to list all views.",
2104
2148
  type: "string",
2105
- enum: ["events", "customer_dimensions", "user_dimensions", "mrr_snapshots"]
2149
+ enum: ["activity", "customers", "users", "revenue"]
2106
2150
  }
2107
2151
  },
2108
2152
  additionalProperties: false
@@ -2268,7 +2312,6 @@ Returns column definitions and example queries for each table.`,
2268
2312
  "recentTimeline",
2269
2313
  "behaviorMetrics"
2270
2314
  ];
2271
- customerSourceTypes = ["EMAIL", "CALL", "CALENDAR_EVENT", "SUPPORT_TICKET"];
2272
2315
  customerTimeframes = ["7d", "14d", "30d", "90d"];
2273
2316
  notificationSeverityValues = ["low", "medium", "high"];
2274
2317
  timelineChannels = [
@@ -2276,6 +2319,7 @@ Returns column definitions and example queries for each table.`,
2276
2319
  "EMAIL",
2277
2320
  "SLACK",
2278
2321
  "CALL",
2322
+ "CALENDAR",
2279
2323
  "CRM",
2280
2324
  "BILLING",
2281
2325
  "SUPPORT",
@@ -2289,13 +2333,12 @@ Returns column definitions and example queries for each table.`,
2289
2333
  "ENGAGED",
2290
2334
  "INACTIVE"
2291
2335
  ];
2292
- schemaTables = [
2293
- "events",
2294
- "customer_dimensions",
2295
- "user_dimensions",
2296
- "mrr_snapshots"
2297
- ];
2298
2336
  customerToolNameSet = new Set(customerToolNames);
2337
+ customerSourceTypeSet = new Set(customerSourceTypes);
2338
+ customerSourceTypeAliasMap = /* @__PURE__ */ new Map([
2339
+ ["CRM", "OPPORTUNITY"],
2340
+ ["CRM_OPPORTUNITY", "OPPORTUNITY"]
2341
+ ]);
2299
2342
  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
2343
  actionToolNames = [
2301
2344
  "outlit_send_notification"
@@ -2587,7 +2630,8 @@ ${hint}`);
2587
2630
  async function runTool(client, toolName, params, json, opts) {
2588
2631
  const spinner = opts?.spinnerMessage ? createSpinner(opts.spinnerMessage) : null;
2589
2632
  try {
2590
- const data = await client.callTool(toolName, params);
2633
+ const rawData = await client.callTool(toolName, params);
2634
+ const data = opts?.transform ? opts.transform(rawData) : rawData;
2591
2635
  spinner?.stop("Done");
2592
2636
  const table = opts?.table;
2593
2637
  if (isJsonMode(json) || !table) {
@@ -2923,6 +2967,35 @@ var init_auth2 = __esm(() => {
2923
2967
  });
2924
2968
 
2925
2969
  // src/args/filters.ts
2970
+ function findRawStringFlagValue(rawArgs, flagName) {
2971
+ if (!rawArgs)
2972
+ return;
2973
+ const flag = `--${flagName}`;
2974
+ let found;
2975
+ for (let i = 0;i < rawArgs.length; i++) {
2976
+ const arg = rawArgs[i];
2977
+ if (!arg)
2978
+ continue;
2979
+ if (arg.startsWith(`${flag}=`)) {
2980
+ const value = arg.slice(flag.length + 1);
2981
+ if (value.length > 0)
2982
+ found = value;
2983
+ continue;
2984
+ }
2985
+ if (arg === flag) {
2986
+ const value = rawArgs[i + 1];
2987
+ if (value && !value.startsWith("-"))
2988
+ found = value;
2989
+ }
2990
+ }
2991
+ return found;
2992
+ }
2993
+ function readStringArg(args, flagName, rawArgs) {
2994
+ const value = args[flagName];
2995
+ if (typeof value === "string" && value.length > 0)
2996
+ return value;
2997
+ return findRawStringFlagValue(rawArgs, flagName);
2998
+ }
2926
2999
  function parseTraitFilterValue(value) {
2927
3000
  if (value === "true")
2928
3001
  return true;
@@ -2955,11 +3028,14 @@ function parseTraitFilters(input) {
2955
3028
  }
2956
3029
  return filters;
2957
3030
  }
2958
- function applyListFilters(params, args) {
2959
- if (args["no-activity-in"])
2960
- params.noActivityInLast = args["no-activity-in"];
2961
- if (args["has-activity-in"])
2962
- params.hasActivityInLast = args["has-activity-in"];
3031
+ function applyListFilters(params, args, rawArgs) {
3032
+ const argsRecord = args;
3033
+ const noActivityIn = readStringArg(argsRecord, "no-activity-in", rawArgs);
3034
+ const hasActivityIn = readStringArg(argsRecord, "has-activity-in", rawArgs);
3035
+ if (noActivityIn)
3036
+ params.noActivityInLast = noActivityIn;
3037
+ if (hasActivityIn)
3038
+ params.hasActivityInLast = hasActivityIn;
2963
3039
  if (args.search)
2964
3040
  params.search = args.search;
2965
3041
  if (args["order-by"])
@@ -3088,6 +3164,33 @@ var exports_list = {};
3088
3164
  __export(exports_list, {
3089
3165
  default: () => list_default
3090
3166
  });
3167
+ function normalizeCustomerListResult(data) {
3168
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
3169
+ return data;
3170
+ }
3171
+ const record = data;
3172
+ if (!Array.isArray(record.items)) {
3173
+ return data;
3174
+ }
3175
+ return {
3176
+ ...record,
3177
+ items: record.items.map((item) => {
3178
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
3179
+ return item;
3180
+ }
3181
+ const customer = item;
3182
+ const daysSinceActivity = customer.daysSinceActivity;
3183
+ if (typeof daysSinceActivity !== "number" || daysSinceActivity >= 0) {
3184
+ return item;
3185
+ }
3186
+ return {
3187
+ ...customer,
3188
+ lastActivityAt: null,
3189
+ daysSinceActivity: null
3190
+ };
3191
+ })
3192
+ };
3193
+ }
3091
3194
  var list_default;
3092
3195
  var init_list = __esm(() => {
3093
3196
  init_dist4();
@@ -3145,7 +3248,7 @@ var init_list = __esm(() => {
3145
3248
  description: "Search by customer name or domain"
3146
3249
  }
3147
3250
  },
3148
- async run({ args }) {
3251
+ async run({ args, rawArgs }) {
3149
3252
  const json = !!args.json;
3150
3253
  const client = await getClientOrExit(args["api-key"], json);
3151
3254
  const params = {};
@@ -3178,10 +3281,11 @@ var init_list = __esm(() => {
3178
3281
  }, json);
3179
3282
  }
3180
3283
  }
3181
- applyListFilters(params, args);
3284
+ applyListFilters(params, args, rawArgs);
3182
3285
  applyPagination(params, args, json);
3183
3286
  return runTool(client, customerToolContracts.outlit_list_customers.toolName, params, json, {
3184
3287
  spinnerMessage: "Fetching customers...",
3288
+ transform: normalizeCustomerListResult,
3185
3289
  table: {
3186
3290
  columns: [
3187
3291
  { header: "Name", key: "name", format: (v) => truncate(v, 24) },
@@ -3457,7 +3561,7 @@ var init_list2 = __esm(() => {
3457
3561
  description: "Search by user name or email"
3458
3562
  }
3459
3563
  },
3460
- async run({ args }) {
3564
+ async run({ args, rawArgs }) {
3461
3565
  const json = !!args.json;
3462
3566
  const client = await getClientOrExit(args["api-key"], json);
3463
3567
  const params = {};
@@ -3478,7 +3582,7 @@ var init_list2 = __esm(() => {
3478
3582
  }, json);
3479
3583
  }
3480
3584
  }
3481
- applyListFilters(params, args);
3585
+ applyListFilters(params, args, rawArgs);
3482
3586
  applyPagination(params, args, json);
3483
3587
  return runTool(client, customerToolContracts.outlit_list_users.toolName, params, json, {
3484
3588
  spinnerMessage: "Fetching users...",
@@ -4484,7 +4588,40 @@ function invalidValues(values, allowed) {
4484
4588
  return [];
4485
4589
  return values.filter((value) => !allowed.includes(value));
4486
4590
  }
4487
- var list_default3;
4591
+ function normalizeSourceTypes(values) {
4592
+ if (!values)
4593
+ return;
4594
+ return Array.from(new Set(values.map((value) => normalizeCustomerSourceType(value)))).filter((sourceType) => sourceType !== null);
4595
+ }
4596
+ function isOneOf(values, value) {
4597
+ return typeof value === "string" && values.includes(value);
4598
+ }
4599
+ function annotateFactFilterability(data) {
4600
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
4601
+ return data;
4602
+ }
4603
+ const record = data;
4604
+ if (!Array.isArray(record.facts)) {
4605
+ return data;
4606
+ }
4607
+ return {
4608
+ ...record,
4609
+ facts: record.facts.map((fact) => {
4610
+ if (typeof fact !== "object" || fact === null || Array.isArray(fact)) {
4611
+ return fact;
4612
+ }
4613
+ const factRecord = fact;
4614
+ return {
4615
+ ...factRecord,
4616
+ filterability: {
4617
+ factType: isOneOf(customerFactTypes, factRecord.factType) ? "public" : "internal",
4618
+ factCategory: isOneOf(customerFactCategories, factRecord.factCategory) ? "public" : "internal"
4619
+ }
4620
+ };
4621
+ })
4622
+ };
4623
+ }
4624
+ var sourceTypeDescription, list_default3;
4488
4625
  var init_list3 = __esm(() => {
4489
4626
  init_dist4();
4490
4627
  init_dist();
@@ -4494,6 +4631,7 @@ var init_list3 = __esm(() => {
4494
4631
  init_api();
4495
4632
  init_config();
4496
4633
  init_output();
4634
+ sourceTypeDescription = `${customerSourceTypes.join(", ")} (aliases: ${customerSourceTypeAliases.join(", ")})`;
4497
4635
  list_default3 = defineCommand2({
4498
4636
  meta: {
4499
4637
  name: "list",
@@ -4506,11 +4644,11 @@ var init_list3 = __esm(() => {
4506
4644
  " outlit facts list acme.com",
4507
4645
  " outlit facts list acme.com --status ACTIVE",
4508
4646
  " outlit facts list acme.com --fact-types CHURN_RISK,EXPANSION",
4509
- " outlit facts list acme.com --source-types CALL,EMAIL --after 2025-01-01T00:00:00Z",
4647
+ " outlit facts list acme.com --source-types CALL,OPPORTUNITY --after 2025-01-01T00:00:00Z",
4510
4648
  " outlit facts list acme.com --limit 50 --json",
4511
4649
  "",
4512
4650
  `Statuses: ${customerFactStatuses.join(", ")}`,
4513
- `Source types: ${customerSourceTypes.join(", ")}`,
4651
+ `Source types: ${sourceTypeDescription}`,
4514
4652
  `Fact categories: ${customerFactCategories.join(", ")}`,
4515
4653
  "",
4516
4654
  AGENT_JSON_HINT
@@ -4532,7 +4670,7 @@ var init_list3 = __esm(() => {
4532
4670
  },
4533
4671
  "source-types": {
4534
4672
  type: "string",
4535
- description: `Comma-separated generic source type filter (${customerSourceTypes.join(", ")})`
4673
+ description: `Comma-separated generic source type filter (${sourceTypeDescription})`
4536
4674
  },
4537
4675
  "fact-types": {
4538
4676
  type: "string",
@@ -4564,13 +4702,14 @@ var init_list3 = __esm(() => {
4564
4702
  code: "invalid_input"
4565
4703
  }, json);
4566
4704
  }
4567
- const invalidSourceTypes = invalidValues(sourceTypes, customerSourceTypes);
4705
+ const invalidSourceTypes = sourceTypes?.filter((value) => !normalizeCustomerSourceType(value)) ?? [];
4568
4706
  if (invalidSourceTypes.length > 0) {
4569
4707
  return outputError({
4570
- message: `Unknown source types: ${invalidSourceTypes.join(", ")}. Allowed: ${customerSourceTypes.join(", ")}`,
4708
+ message: `Unknown source types: ${invalidSourceTypes.join(", ")}. Allowed: ${customerSourceTypeInputs.join(", ")}`,
4571
4709
  code: "invalid_input"
4572
4710
  }, json);
4573
4711
  }
4712
+ const normalizedSourceTypes = normalizeSourceTypes(sourceTypes);
4574
4713
  const invalidFactTypes = invalidValues(factTypes, customerFactTypes);
4575
4714
  if (invalidFactTypes.length > 0) {
4576
4715
  const anomalyFactTypes = invalidFactTypes.filter((value) => unsupportedCustomerFactTypes.includes(value));
@@ -4620,8 +4759,8 @@ var init_list3 = __esm(() => {
4620
4759
  };
4621
4760
  if (statuses)
4622
4761
  params.status = statuses;
4623
- if (sourceTypes)
4624
- params.sourceTypes = sourceTypes;
4762
+ if (normalizedSourceTypes)
4763
+ params.sourceTypes = normalizedSourceTypes;
4625
4764
  if (factTypes)
4626
4765
  params.factTypes = factTypes;
4627
4766
  if (factCategories)
@@ -4631,7 +4770,9 @@ var init_list3 = __esm(() => {
4631
4770
  if (args.before)
4632
4771
  params.before = args.before;
4633
4772
  applyPagination(params, args, json);
4634
- return runTool(client, customerToolContracts.outlit_list_facts.toolName, params, json);
4773
+ return runTool(client, customerToolContracts.outlit_list_facts.toolName, params, json, {
4774
+ transform: annotateFactFilterability
4775
+ });
4635
4776
  }
4636
4777
  });
4637
4778
  });
@@ -4733,7 +4874,7 @@ var exports_get3 = {};
4733
4874
  __export(exports_get3, {
4734
4875
  default: () => get_default3
4735
4876
  });
4736
- var get_default3;
4877
+ var sourceTypeDescription2, get_default3;
4737
4878
  var init_get3 = __esm(() => {
4738
4879
  init_dist4();
4739
4880
  init_dist();
@@ -4741,6 +4882,7 @@ var init_get3 = __esm(() => {
4741
4882
  init_output2();
4742
4883
  init_api();
4743
4884
  init_output();
4885
+ sourceTypeDescription2 = `${customerSourceTypes.join(", ")} (aliases: ${customerSourceTypeAliases.join(", ")})`;
4744
4886
  get_default3 = defineCommand2({
4745
4887
  meta: {
4746
4888
  name: "get",
@@ -4749,9 +4891,10 @@ var init_get3 = __esm(() => {
4749
4891
  "",
4750
4892
  "Examples:",
4751
4893
  " outlit sources get --source-type CALL --source-id call_123",
4894
+ " outlit sources get --source-type OPPORTUNITY --source-id opp_123",
4752
4895
  " outlit sources get --source-type SUPPORT_TICKET --source-id ticket_456 --json",
4753
4896
  "",
4754
- `Source types: ${customerSourceTypes.join(", ")}`,
4897
+ `Source types: ${sourceTypeDescription2}`,
4755
4898
  "",
4756
4899
  AGENT_JSON_HINT
4757
4900
  ].join(`
@@ -4762,7 +4905,7 @@ var init_get3 = __esm(() => {
4762
4905
  ...outputArgs,
4763
4906
  "source-type": {
4764
4907
  type: "string",
4765
- description: "Canonical source type",
4908
+ description: `Source type (${sourceTypeDescription2})`,
4766
4909
  required: true
4767
4910
  },
4768
4911
  "source-id": {
@@ -4773,15 +4916,16 @@ var init_get3 = __esm(() => {
4773
4916
  },
4774
4917
  async run({ args }) {
4775
4918
  const json = !!args.json;
4776
- if (!customerSourceTypes.includes(args["source-type"])) {
4919
+ const sourceType = normalizeCustomerSourceType(args["source-type"]);
4920
+ if (!sourceType) {
4777
4921
  return outputError({
4778
- message: `--source-type must be one of ${customerSourceTypes.join(", ")}`,
4922
+ message: `--source-type must be one of ${customerSourceTypeInputs.join(", ")}`,
4779
4923
  code: "invalid_input"
4780
4924
  }, json);
4781
4925
  }
4782
4926
  const client = await getClientOrExit(args["api-key"], json);
4783
4927
  return runTool(client, customerToolContracts.outlit_get_source.toolName, {
4784
- sourceType: args["source-type"],
4928
+ sourceType,
4785
4929
  sourceId: args["source-id"]
4786
4930
  }, json);
4787
4931
  }
@@ -4821,7 +4965,7 @@ var exports_search = {};
4821
4965
  __export(exports_search, {
4822
4966
  default: () => search_default
4823
4967
  });
4824
- var search_default;
4968
+ var sourceTypeDescription3, search_default;
4825
4969
  var init_search = __esm(() => {
4826
4970
  init_dist4();
4827
4971
  init_dist();
@@ -4830,6 +4974,7 @@ var init_search = __esm(() => {
4830
4974
  init_api();
4831
4975
  init_config();
4832
4976
  init_output();
4977
+ sourceTypeDescription3 = `${customerSourceTypes.join(", ")} (aliases: ${customerSourceTypeAliases.join(", ")})`;
4833
4978
  search_default = defineCommand2({
4834
4979
  meta: {
4835
4980
  name: "search",
@@ -4844,7 +4989,7 @@ var init_search = __esm(() => {
4844
4989
  " outlit search 'churn risk signals' --customer acme.com",
4845
4990
  " outlit search 'expansion opportunities' --top-k 50 --json",
4846
4991
  " outlit search 'support escalations' --after 2025-01-01T00:00:00Z --before 2025-03-31T23:59:59Z",
4847
- " outlit search 'onboarding issues' --source-types CALL,EMAIL",
4992
+ " outlit search 'renewal opportunities' --source-types CALL,OPPORTUNITY",
4848
4993
  "",
4849
4994
  AGENT_JSON_HINT
4850
4995
  ].join(`
@@ -4876,7 +5021,7 @@ var init_search = __esm(() => {
4876
5021
  },
4877
5022
  "source-types": {
4878
5023
  type: "string",
4879
- description: `Comma-separated generic source type filter (${customerSourceTypes.join(", ")})`
5024
+ description: `Comma-separated generic source type filter (${sourceTypeDescription3})`
4880
5025
  }
4881
5026
  },
4882
5027
  async run({ args }) {
@@ -4886,13 +5031,6 @@ var init_search = __esm(() => {
4886
5031
  return outputError({ message: "--top-k must be an integer between 1 and 50", code: "invalid_input" }, json);
4887
5032
  }
4888
5033
  const sourceTypes = args["source-types"] ? splitCsv(args["source-types"]).map((item) => item.trim()).filter(Boolean) : undefined;
4889
- const invalidSourceTypes = sourceTypes?.filter((value) => !customerSourceTypes.includes(value));
4890
- if (invalidSourceTypes && invalidSourceTypes.length > 0) {
4891
- return outputError({
4892
- message: `Unknown source types: ${invalidSourceTypes.join(", ")}. Allowed: ${customerSourceTypes.join(", ")}`,
4893
- code: "invalid_input"
4894
- }, json);
4895
- }
4896
5034
  const resolved = resolveCustomerContextSearchInput({
4897
5035
  query: args.query,
4898
5036
  customer: args.customer,
@@ -4919,7 +5057,7 @@ __export(exports_sql, {
4919
5057
  default: () => sql_default
4920
5058
  });
4921
5059
  import { readFileSync as readFileSync4 } from "node:fs";
4922
- var sql_default;
5060
+ var publicSqlViews, sql_default;
4923
5061
  var init_sql = __esm(() => {
4924
5062
  init_dist4();
4925
5063
  init_dist();
@@ -4927,21 +5065,22 @@ var init_sql = __esm(() => {
4927
5065
  init_output2();
4928
5066
  init_api();
4929
5067
  init_output();
5068
+ publicSqlViews = ["activity", "customers", "users", "revenue"];
4930
5069
  sql_default = defineCommand2({
4931
5070
  meta: {
4932
5071
  name: "sql",
4933
5072
  description: [
4934
- "Run a SQL query against Outlit's analytics database.",
5073
+ "Run a SQL query against Outlit analytics views.",
4935
5074
  "",
4936
5075
  "Provide the query as a positional argument or via --query-file.",
4937
5076
  "When both are provided, --query-file takes precedence.",
4938
5077
  "",
4939
- `Available tables: ${schemaTables.join(", ")}`,
5078
+ `Available views: ${publicSqlViews.join(", ")}`,
4940
5079
  "",
4941
5080
  "Examples:",
4942
- " outlit sql 'SELECT * FROM events LIMIT 10'",
5081
+ " outlit sql 'SELECT * FROM activity LIMIT 10'",
4943
5082
  " outlit sql --query-file ./my-query.sql",
4944
- " outlit sql 'SELECT count(*) FROM events' --limit 1 --json",
5083
+ " outlit sql 'SELECT count(*) FROM activity' --limit 1 --json",
4945
5084
  "",
4946
5085
  AGENT_JSON_HINT
4947
5086
  ].join(`
@@ -4984,8 +5123,8 @@ var init_sql = __esm(() => {
4984
5123
  return outputError({ message: "Provide a SQL query or --query-file", code: "missing_input" }, json);
4985
5124
  }
4986
5125
  const limit = Number(args.limit);
4987
- if (!Number.isFinite(limit) || limit <= 0) {
4988
- return outputError({ message: "--limit must be a positive number", code: "invalid_input" }, json);
5126
+ if (!Number.isInteger(limit) || limit < 1 || limit > 1e4) {
5127
+ return outputError({ message: "--limit must be an integer between 1 and 10000", code: "invalid_input" }, json);
4989
5128
  }
4990
5129
  return runTool(client, customerToolContracts.outlit_query.toolName, { sql, limit }, json);
4991
5130
  }
@@ -5176,28 +5315,29 @@ var exports_schema = {};
5176
5315
  __export(exports_schema, {
5177
5316
  default: () => schema_default
5178
5317
  });
5179
- var schema_default;
5318
+ var publicSqlViews2, schema_default;
5180
5319
  var init_schema = __esm(() => {
5181
5320
  init_dist4();
5182
5321
  init_dist();
5183
5322
  init_auth();
5184
5323
  init_output2();
5185
5324
  init_api();
5325
+ publicSqlViews2 = ["activity", "customers", "users", "revenue"];
5186
5326
  schema_default = defineCommand2({
5187
5327
  meta: {
5188
5328
  name: "schema",
5189
5329
  description: [
5190
- "Describe the analytics database schema.",
5330
+ "Describe the available analytics views.",
5191
5331
  "",
5192
- "Without a table name, returns the full schema for all tables.",
5193
- "With a table name, returns detailed column info for that table.",
5332
+ "Without a view name, returns the full schema for all views.",
5333
+ "With a view name, returns detailed column info for that view.",
5194
5334
  "",
5195
- `Available tables: ${schemaTables.join(", ")}`,
5335
+ `Available views: ${publicSqlViews2.join(", ")}`,
5196
5336
  "",
5197
5337
  "Examples:",
5198
5338
  " outlit schema",
5199
- " outlit schema events",
5200
- " outlit schema customer_dimensions --json",
5339
+ " outlit schema activity",
5340
+ " outlit schema customers --json",
5201
5341
  "",
5202
5342
  AGENT_JSON_HINT
5203
5343
  ].join(`
@@ -5206,9 +5346,9 @@ var init_schema = __esm(() => {
5206
5346
  args: {
5207
5347
  ...authArgs,
5208
5348
  ...outputArgs,
5209
- table: {
5349
+ view: {
5210
5350
  type: "positional",
5211
- description: `Table to describe (${schemaTables.join(", ")}). Optional.`,
5351
+ description: `View to describe (${publicSqlViews2.join(", ")}). Optional.`,
5212
5352
  required: false
5213
5353
  }
5214
5354
  },
@@ -5216,8 +5356,9 @@ var init_schema = __esm(() => {
5216
5356
  const json = !!args.json;
5217
5357
  const client = await getClientOrExit(args["api-key"], json);
5218
5358
  const params = {};
5219
- if (args.table)
5220
- params.table = args.table;
5359
+ const view = args.view ?? args.table;
5360
+ if (view)
5361
+ params.table = view;
5221
5362
  return runTool(client, customerToolContracts.outlit_schema.toolName, params, json);
5222
5363
  }
5223
5364
  });
@@ -5252,14 +5393,22 @@ var INTEGRATION_PROVIDERS, PROVIDER_NAMES;
5252
5393
  var init_providers = __esm(() => {
5253
5394
  init_output();
5254
5395
  INTEGRATION_PROVIDERS = {
5396
+ hubspot: { id: "hubspot", name: "HubSpot", category: "crm", authType: "oauth" },
5255
5397
  slack: { id: "slack", name: "Slack", category: "communication", authType: "oauth" },
5256
5398
  gmail: { id: "google-mail", name: "Gmail", category: "communication", authType: "oauth" },
5399
+ "google-mail": {
5400
+ id: "google-mail",
5401
+ name: "Gmail",
5402
+ category: "communication",
5403
+ authType: "oauth"
5404
+ },
5257
5405
  "google-calendar": {
5258
5406
  id: "google-calendar",
5259
5407
  name: "Google Calendar",
5260
5408
  category: "calendar",
5261
5409
  authType: "oauth"
5262
5410
  },
5411
+ granola: { id: "granola", name: "Granola", category: "calls", authType: "oauth" },
5263
5412
  pylon: {
5264
5413
  id: "pylon",
5265
5414
  name: "Pylon",
@@ -5683,6 +5832,25 @@ var exports_status2 = {};
5683
5832
  __export(exports_status2, {
5684
5833
  default: () => status_default2
5685
5834
  });
5835
+ function hideBlankModelSyncs(data) {
5836
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
5837
+ return data;
5838
+ }
5839
+ const record = data;
5840
+ if (!Array.isArray(record.syncs)) {
5841
+ return data;
5842
+ }
5843
+ return {
5844
+ ...record,
5845
+ syncs: record.syncs.filter((sync) => {
5846
+ if (typeof sync !== "object" || sync === null || Array.isArray(sync)) {
5847
+ return false;
5848
+ }
5849
+ const model = sync.model;
5850
+ return typeof model === "string" && model.trim().length > 0;
5851
+ })
5852
+ };
5853
+ }
5686
5854
  var status_default2;
5687
5855
  var init_status2 = __esm(() => {
5688
5856
  init_dist();
@@ -5723,6 +5891,7 @@ var init_status2 = __esm(() => {
5723
5891
  const { provider } = resolveProviderOrExit(args.provider, json);
5724
5892
  return runTool(client, "outlit_integration_sync_status", { provider: provider.id }, json, {
5725
5893
  spinnerMessage: "Fetching sync status...",
5894
+ transform: hideBlankModelSyncs,
5726
5895
  table: {
5727
5896
  columns: [
5728
5897
  { header: "Model", key: "model" },
@@ -6114,7 +6283,7 @@ var init_completions = __esm(() => {
6114
6283
  desc: "Get one exact source record",
6115
6284
  flags: [
6116
6285
  ...COMMON,
6117
- { name: "--source-type", desc: "Canonical source type" },
6286
+ { name: "--source-type", desc: "Source type" },
6118
6287
  { name: "--source-id", desc: "Exact source ID" }
6119
6288
  ]
6120
6289
  }
@@ -6141,7 +6310,7 @@ var init_completions = __esm(() => {
6141
6310
  { name: "--limit", desc: "Max rows to return" }
6142
6311
  ]
6143
6312
  },
6144
- { name: "schema", desc: "Discover table schemas", flags: [...COMMON] },
6313
+ { name: "schema", desc: "Discover analytics view schemas", flags: [...COMMON] },
6145
6314
  {
6146
6315
  name: "integrations",
6147
6316
  desc: "Manage platform integrations",
@@ -6965,11 +7134,11 @@ Usage examples:
6965
7134
  outlit users list --journey-stage CHAMPION
6966
7135
  outlit facts list acme.com --fact-types CHURN_RISK,EXPANSION
6967
7136
  outlit facts get --fact-id fact_123 --include evidence
6968
- outlit sources get --source-type CALL --source-id call_123
6969
- outlit search 'pricing objections last quarter' --source-types CALL,EMAIL
6970
- outlit sql 'SELECT * FROM events LIMIT 10'
7137
+ outlit sources get --source-type OPPORTUNITY --source-id opp_123
7138
+ outlit search 'pricing objections last quarter' --source-types CALL,OPPORTUNITY
7139
+ outlit sql 'SELECT * FROM activity LIMIT 10'
6971
7140
  outlit notify --title 'Risk found' '{"customer":"acme.com"}'
6972
- outlit schema events
7141
+ outlit schema activity
6973
7142
  outlit doctor --json
6974
7143
 
6975
7144
  For AI agents: commands auto-output JSON when stdout is piped. No --json flag needed.`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outlit/cli",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
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.1",
34
+ "@outlit/tools": "^0.1.3",
35
35
  "citty": "^0.2.1"
36
36
  },
37
37
  "devDependencies": {