@outlit/cli 1.4.1 → 1.5.0
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.
- package/dist/cli.js +1527 -878
- package/package.json +1 -1
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.
|
|
107
|
+
version: "1.5.0",
|
|
108
108
|
description: "CLI for Outlit customer intelligence platform",
|
|
109
109
|
license: "Apache-2.0",
|
|
110
110
|
repository: {
|
|
@@ -222,6 +222,70 @@ var init_output = __esm(() => {
|
|
|
222
222
|
init_tty();
|
|
223
223
|
});
|
|
224
224
|
|
|
225
|
+
// src/lib/config.ts
|
|
226
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
227
|
+
import { homedir } from "node:os";
|
|
228
|
+
import { dirname, join } from "node:path";
|
|
229
|
+
function isEnoentError(err) {
|
|
230
|
+
return err instanceof Error && err.code === "ENOENT";
|
|
231
|
+
}
|
|
232
|
+
function splitCsv(value) {
|
|
233
|
+
return value.split(",").map((s) => s.trim());
|
|
234
|
+
}
|
|
235
|
+
function getConfigDir() {
|
|
236
|
+
if (process.platform === "win32") {
|
|
237
|
+
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "outlit");
|
|
238
|
+
}
|
|
239
|
+
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "outlit");
|
|
240
|
+
}
|
|
241
|
+
function resolveApiKey(flagValue) {
|
|
242
|
+
if (flagValue)
|
|
243
|
+
return { key: flagValue, source: "flag" };
|
|
244
|
+
const envKey = process.env.OUTLIT_API_KEY;
|
|
245
|
+
if (envKey)
|
|
246
|
+
return { key: envKey, source: "env" };
|
|
247
|
+
const credPath = join(getConfigDir(), "credentials.json");
|
|
248
|
+
if (existsSync(credPath)) {
|
|
249
|
+
try {
|
|
250
|
+
const raw = readFileSync(credPath, "utf-8");
|
|
251
|
+
const config = JSON.parse(raw);
|
|
252
|
+
if (config.apiKey)
|
|
253
|
+
return { key: config.apiKey, source: "config" };
|
|
254
|
+
} catch {}
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
function maskKey(key) {
|
|
259
|
+
if (key.length <= 9)
|
|
260
|
+
return key;
|
|
261
|
+
return `${key.slice(0, 5)}...${key.slice(-4)}`;
|
|
262
|
+
}
|
|
263
|
+
function requireCredential(flagApiKey, json) {
|
|
264
|
+
const credential = resolveApiKey(flagApiKey);
|
|
265
|
+
if (!credential) {
|
|
266
|
+
return outputError({
|
|
267
|
+
message: "Not authenticated. Run `outlit auth login` or pass --api-key.",
|
|
268
|
+
code: "not_authenticated"
|
|
269
|
+
}, json);
|
|
270
|
+
}
|
|
271
|
+
return credential;
|
|
272
|
+
}
|
|
273
|
+
function storeApiKey(apiKey) {
|
|
274
|
+
const configDir = getConfigDir();
|
|
275
|
+
mkdirSync(configDir, { recursive: true, mode: 448 });
|
|
276
|
+
const credPath = join(configDir, "credentials.json");
|
|
277
|
+
writeFileSync(credPath, JSON.stringify({ apiKey }, null, 2), { mode: 384 });
|
|
278
|
+
return credPath;
|
|
279
|
+
}
|
|
280
|
+
var CLI_VERSION2, DEFAULT_API_URL = "https://app.outlit.ai", OUTLIT_DASHBOARD_URL = "https://app.outlit.ai/workspace-profile", OUTLIT_SIGNUP_URL = "https://app.outlit.ai/sign-up", TICK2;
|
|
281
|
+
var init_config = __esm(() => {
|
|
282
|
+
init_package();
|
|
283
|
+
init_output();
|
|
284
|
+
init_tty();
|
|
285
|
+
CLI_VERSION2 = package_default.version;
|
|
286
|
+
TICK2 = `\x1B[32m${isUnicodeSupported ? String.fromCodePoint(10003) : String.fromCodePoint(8730)}\x1B[0m`;
|
|
287
|
+
});
|
|
288
|
+
|
|
225
289
|
// ../../node_modules/.bun/citty@0.2.1/node_modules/citty/dist/index.mjs
|
|
226
290
|
function defineCommand2(def) {
|
|
227
291
|
return def;
|
|
@@ -1375,109 +1439,6 @@ Note: JSON is also auto-enabled when stdout is piped (e.g. in CI, scripts, or AI
|
|
|
1375
1439
|
};
|
|
1376
1440
|
});
|
|
1377
1441
|
|
|
1378
|
-
// src/lib/config.ts
|
|
1379
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
1380
|
-
import { homedir } from "node:os";
|
|
1381
|
-
import { dirname, join } from "node:path";
|
|
1382
|
-
function isEnoentError(err) {
|
|
1383
|
-
return err instanceof Error && err.code === "ENOENT";
|
|
1384
|
-
}
|
|
1385
|
-
function splitCsv(value) {
|
|
1386
|
-
return value.split(",").map((s) => s.trim());
|
|
1387
|
-
}
|
|
1388
|
-
function getClaudeDesktopConfigPath() {
|
|
1389
|
-
const home = homedir();
|
|
1390
|
-
switch (process.platform) {
|
|
1391
|
-
case "win32":
|
|
1392
|
-
return join(process.env.APPDATA ?? join(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
|
|
1393
|
-
case "darwin":
|
|
1394
|
-
return join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
1395
|
-
default:
|
|
1396
|
-
return join(home, ".config", "Claude", "claude_desktop_config.json");
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
function getConfigDir() {
|
|
1400
|
-
if (process.platform === "win32") {
|
|
1401
|
-
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "outlit");
|
|
1402
|
-
}
|
|
1403
|
-
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "outlit");
|
|
1404
|
-
}
|
|
1405
|
-
function resolveApiKey(flagValue) {
|
|
1406
|
-
if (flagValue)
|
|
1407
|
-
return { key: flagValue, source: "flag" };
|
|
1408
|
-
const envKey = process.env.OUTLIT_API_KEY;
|
|
1409
|
-
if (envKey)
|
|
1410
|
-
return { key: envKey, source: "env" };
|
|
1411
|
-
const credPath = join(getConfigDir(), "credentials.json");
|
|
1412
|
-
if (existsSync(credPath)) {
|
|
1413
|
-
try {
|
|
1414
|
-
const raw = readFileSync(credPath, "utf-8");
|
|
1415
|
-
const config = JSON.parse(raw);
|
|
1416
|
-
if (config.apiKey)
|
|
1417
|
-
return { key: config.apiKey, source: "config" };
|
|
1418
|
-
} catch {}
|
|
1419
|
-
}
|
|
1420
|
-
return null;
|
|
1421
|
-
}
|
|
1422
|
-
function maskKey(key) {
|
|
1423
|
-
if (key.length <= 9)
|
|
1424
|
-
return key;
|
|
1425
|
-
return `${key.slice(0, 5)}...${key.slice(-4)}`;
|
|
1426
|
-
}
|
|
1427
|
-
function readJsonConfig(filePath) {
|
|
1428
|
-
if (!existsSync(filePath))
|
|
1429
|
-
return {};
|
|
1430
|
-
try {
|
|
1431
|
-
return JSON.parse(readFileSync(filePath, "utf-8"));
|
|
1432
|
-
} catch {
|
|
1433
|
-
return {};
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
function requireCredential(flagApiKey, json) {
|
|
1437
|
-
const credential = resolveApiKey(flagApiKey);
|
|
1438
|
-
if (!credential) {
|
|
1439
|
-
return outputError({
|
|
1440
|
-
message: "Not authenticated. Run `outlit auth login` or pass --api-key.",
|
|
1441
|
-
code: "not_authenticated"
|
|
1442
|
-
}, json);
|
|
1443
|
-
}
|
|
1444
|
-
return credential;
|
|
1445
|
-
}
|
|
1446
|
-
function writeConfigFile(filePath, content, opts) {
|
|
1447
|
-
try {
|
|
1448
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
1449
|
-
writeFileSync(filePath, content);
|
|
1450
|
-
return true;
|
|
1451
|
-
} catch (err) {
|
|
1452
|
-
return outputError({ message: errorMessage(err, `Failed to write ${opts.label}`), code: "write_error" }, opts.json);
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
function mergeOutlitMcpConfig(configPath, serversKey, outlitConfig, opts) {
|
|
1456
|
-
const existing = readJsonConfig(configPath);
|
|
1457
|
-
const existingServers = existing[serversKey] ?? {};
|
|
1458
|
-
const merged = {
|
|
1459
|
-
...existing,
|
|
1460
|
-
[serversKey]: { ...existingServers, outlit: outlitConfig }
|
|
1461
|
-
};
|
|
1462
|
-
writeConfigFile(configPath, `${JSON.stringify(merged, null, 2)}
|
|
1463
|
-
`, opts);
|
|
1464
|
-
}
|
|
1465
|
-
function storeApiKey(apiKey) {
|
|
1466
|
-
const configDir = getConfigDir();
|
|
1467
|
-
mkdirSync(configDir, { recursive: true, mode: 448 });
|
|
1468
|
-
const credPath = join(configDir, "credentials.json");
|
|
1469
|
-
writeFileSync(credPath, JSON.stringify({ apiKey }, null, 2), { mode: 384 });
|
|
1470
|
-
return credPath;
|
|
1471
|
-
}
|
|
1472
|
-
var CLI_VERSION2, DEFAULT_MCP_URL = "https://mcp.outlit.ai/mcp", DEFAULT_API_URL = "https://app.outlit.ai", OUTLIT_DASHBOARD_URL = "https://app.outlit.ai/workspace-profile", OUTLIT_SIGNUP_URL = "https://app.outlit.ai/sign-up", TICK2;
|
|
1473
|
-
var init_config = __esm(() => {
|
|
1474
|
-
init_package();
|
|
1475
|
-
init_output();
|
|
1476
|
-
init_tty();
|
|
1477
|
-
CLI_VERSION2 = package_default.version;
|
|
1478
|
-
TICK2 = `\x1B[32m${isUnicodeSupported ? String.fromCodePoint(10003) : String.fromCodePoint(8730)}\x1B[0m`;
|
|
1479
|
-
});
|
|
1480
|
-
|
|
1481
1442
|
// src/commands/auth/signup.ts
|
|
1482
1443
|
var exports_signup = {};
|
|
1483
1444
|
__export(exports_signup, {
|
|
@@ -1594,7 +1555,9 @@ var init_client = __esm(() => {
|
|
|
1594
1555
|
outlit_get_customer: { method: "POST", path: "/api/internal/mcp/customers" },
|
|
1595
1556
|
outlit_list_users: { method: "GET", path: "/api/internal/mcp/users" },
|
|
1596
1557
|
outlit_get_timeline: { method: "POST", path: "/api/internal/mcp/timeline" },
|
|
1597
|
-
|
|
1558
|
+
outlit_list_facts: { method: "POST", path: "/api/internal/mcp/facts" },
|
|
1559
|
+
outlit_get_fact: { method: "POST", path: "/api/internal/mcp/facts/get" },
|
|
1560
|
+
outlit_get_source: { method: "POST", path: "/api/internal/mcp/context-source" },
|
|
1598
1561
|
outlit_schema: { method: "GET", path: "/api/internal/mcp/sql-schema" },
|
|
1599
1562
|
outlit_query: { method: "POST", path: "/api/internal/mcp/sql" },
|
|
1600
1563
|
outlit_search_customer_context: { method: "POST", path: "/api/internal/mcp/context-search" },
|
|
@@ -1736,8 +1699,26 @@ async function getClientOrExit(flagApiKey, json) {
|
|
|
1736
1699
|
return createClient(flagApiKey).catch((err) => outputError({ message: errorMessage(err, "Authentication failed"), code: "auth_required" }, json));
|
|
1737
1700
|
}
|
|
1738
1701
|
async function pingApiKey(apiKey) {
|
|
1739
|
-
const
|
|
1740
|
-
|
|
1702
|
+
const baseUrl = process.env.OUTLIT_API_URL ?? DEFAULT_API_URL;
|
|
1703
|
+
const url = new URL("/api/internal/mcp/validate-api-key", baseUrl).toString();
|
|
1704
|
+
const response = await globalThis.fetch(url, {
|
|
1705
|
+
method: "POST",
|
|
1706
|
+
headers: {
|
|
1707
|
+
Authorization: `Bearer ${apiKey}`
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
const text = await response.text();
|
|
1711
|
+
const payload = text.length > 0 ? (() => {
|
|
1712
|
+
try {
|
|
1713
|
+
return JSON.parse(text);
|
|
1714
|
+
} catch {
|
|
1715
|
+
return null;
|
|
1716
|
+
}
|
|
1717
|
+
})() : null;
|
|
1718
|
+
if (!response.ok || !payload?.valid) {
|
|
1719
|
+
const message = payload?.error ?? (text.length > 0 ? text : `API error (${response.status})`);
|
|
1720
|
+
throw new Error(message);
|
|
1721
|
+
}
|
|
1741
1722
|
}
|
|
1742
1723
|
async function validateKeyOrExit(apiKey, json) {
|
|
1743
1724
|
try {
|
|
@@ -1789,6 +1770,7 @@ async function runTool(client, toolName, params, json, opts) {
|
|
|
1789
1770
|
}
|
|
1790
1771
|
var init_api = __esm(() => {
|
|
1791
1772
|
init_client();
|
|
1773
|
+
init_config();
|
|
1792
1774
|
init_output();
|
|
1793
1775
|
init_spinner();
|
|
1794
1776
|
init_table();
|
|
@@ -1922,8 +1904,8 @@ var exports_logout = {};
|
|
|
1922
1904
|
__export(exports_logout, {
|
|
1923
1905
|
default: () => logout_default
|
|
1924
1906
|
});
|
|
1925
|
-
import { rmSync } from "node:fs";
|
|
1926
|
-
import { join as
|
|
1907
|
+
import { rmSync as rmSync2 } from "node:fs";
|
|
1908
|
+
import { join as join3 } from "node:path";
|
|
1927
1909
|
var logout_default;
|
|
1928
1910
|
var init_logout = __esm(() => {
|
|
1929
1911
|
init_dist();
|
|
@@ -1949,13 +1931,13 @@ var init_logout = __esm(() => {
|
|
|
1949
1931
|
async run({ args }) {
|
|
1950
1932
|
const json = !!args.json;
|
|
1951
1933
|
const configDir = getConfigDir();
|
|
1952
|
-
const credPath =
|
|
1934
|
+
const credPath = join3(configDir, "credentials.json");
|
|
1953
1935
|
if (process.env.OUTLIT_API_KEY) {
|
|
1954
1936
|
process.stderr.write(`Warning: OUTLIT_API_KEY env var is still set and will continue to work after logout.
|
|
1955
1937
|
`);
|
|
1956
1938
|
}
|
|
1957
1939
|
try {
|
|
1958
|
-
|
|
1940
|
+
rmSync2(credPath, { force: true });
|
|
1959
1941
|
} catch (err) {
|
|
1960
1942
|
if (!isEnoentError(err)) {
|
|
1961
1943
|
return outputError({ message: errorMessage(err, "Failed to remove credentials file"), code: "unlink_error" }, json);
|
|
@@ -2219,6 +2201,148 @@ Use this to fetch the next page of results.`
|
|
|
2219
2201
|
};
|
|
2220
2202
|
});
|
|
2221
2203
|
|
|
2204
|
+
// src/generated/tool-contracts.ts
|
|
2205
|
+
function resolveCustomerContextSearchInput(value) {
|
|
2206
|
+
if (!value.query) {
|
|
2207
|
+
return {
|
|
2208
|
+
ok: false,
|
|
2209
|
+
message: "A query argument is required"
|
|
2210
|
+
};
|
|
2211
|
+
}
|
|
2212
|
+
const normalizedQuery = value.query.trim();
|
|
2213
|
+
if (normalizedQuery.length < 2) {
|
|
2214
|
+
return {
|
|
2215
|
+
ok: false,
|
|
2216
|
+
message: "Query must be at least 2 non-whitespace characters"
|
|
2217
|
+
};
|
|
2218
|
+
}
|
|
2219
|
+
if (value.after !== undefined && value.before !== undefined && new Date(value.after).getTime() > new Date(value.before).getTime()) {
|
|
2220
|
+
return {
|
|
2221
|
+
ok: false,
|
|
2222
|
+
message: "--after must be before or equal to --before"
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
return {
|
|
2226
|
+
ok: true,
|
|
2227
|
+
request: {
|
|
2228
|
+
query: normalizedQuery,
|
|
2229
|
+
customer: value.customer,
|
|
2230
|
+
topK: value.topK,
|
|
2231
|
+
after: value.after,
|
|
2232
|
+
before: value.before,
|
|
2233
|
+
sourceTypes: value.sourceTypes
|
|
2234
|
+
}
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2237
|
+
var customerToolContracts, customerBillingStatuses, customerFactStatuses, customerIncludeSections, customerSourceTypes, customerTimeframes, timelineChannels, timelineTimeframes, userJourneyStages, schemaTables;
|
|
2238
|
+
var init_tool_contracts = __esm(() => {
|
|
2239
|
+
customerToolContracts = {
|
|
2240
|
+
outlit_list_customers: {
|
|
2241
|
+
toolName: "outlit_list_customers",
|
|
2242
|
+
description: "Browse and filter customers. Use this to find customers by billing status, activity recency, revenue, or name. Returns a paginated list with summary info (MRR, last activity, status)."
|
|
2243
|
+
},
|
|
2244
|
+
outlit_list_users: {
|
|
2245
|
+
toolName: "outlit_list_users",
|
|
2246
|
+
description: "Browse and filter users. Use this to find users by journey stage, activity recency, customer, or email/name. Returns a paginated list with activity info."
|
|
2247
|
+
},
|
|
2248
|
+
outlit_get_customer: {
|
|
2249
|
+
toolName: "outlit_get_customer",
|
|
2250
|
+
description: "Get full details for a single customer. Use this when you already know which customer you want to inspect. Optionally include related data (users, revenue, recent activity, engagement metrics)."
|
|
2251
|
+
},
|
|
2252
|
+
outlit_get_timeline: {
|
|
2253
|
+
toolName: "outlit_get_timeline",
|
|
2254
|
+
description: "Get the chronological activity timeline for a customer. Use this to see what happened and when — emails, calls, Slack messages, billing events, etc. Supports channel and date filtering."
|
|
2255
|
+
},
|
|
2256
|
+
outlit_list_facts: {
|
|
2257
|
+
toolName: "outlit_list_facts",
|
|
2258
|
+
description: "List structured facts known about a customer. Use filters like status, sourceTypes, and date bounds to narrow the result set. For topic-specific retrieval, use outlit_search_customer_context instead."
|
|
2259
|
+
},
|
|
2260
|
+
outlit_get_fact: {
|
|
2261
|
+
toolName: "outlit_get_fact",
|
|
2262
|
+
description: "Get one exact fact by ID. Returns the canonical fact shape and optionally expands requested related data such as evidence."
|
|
2263
|
+
},
|
|
2264
|
+
outlit_get_source: {
|
|
2265
|
+
toolName: "outlit_get_source",
|
|
2266
|
+
description: "Get one exact source record by generic sourceType and sourceId. Use this when you already know the concrete underlying source you want to inspect."
|
|
2267
|
+
},
|
|
2268
|
+
outlit_search_customer_context: {
|
|
2269
|
+
toolName: "outlit_search_customer_context",
|
|
2270
|
+
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."
|
|
2271
|
+
},
|
|
2272
|
+
outlit_query: {
|
|
2273
|
+
toolName: "outlit_query",
|
|
2274
|
+
description: `Execute raw SQL queries against your analytics data.
|
|
2275
|
+
|
|
2276
|
+
Available tables:
|
|
2277
|
+
- events: Customer activity events (event_type, event_channel, customer_id, occurred_at, properties, ...)
|
|
2278
|
+
- customer_dimensions: Customer attributes (customer_id, domain, name, billing_status, plan, mrr_cents, ...)
|
|
2279
|
+
- user_dimensions: User attributes (user_id, email, name, customer_id, ...)
|
|
2280
|
+
- mrr_snapshots: Revenue snapshots over time (customer_id, snapshot_date, mrr_cents, ...)
|
|
2281
|
+
|
|
2282
|
+
All queries are automatically filtered to your organization's data.
|
|
2283
|
+
Only SELECT queries are allowed.
|
|
2284
|
+
|
|
2285
|
+
Example queries:
|
|
2286
|
+
- SELECT event_type, count(*) FROM events GROUP BY 1 ORDER BY 2 DESC LIMIT 10
|
|
2287
|
+
- SELECT billing_status, sum(mrr_cents)/100 as mrr FROM customer_dimensions GROUP BY 1
|
|
2288
|
+
- SELECT * FROM events WHERE customer_id = 'cust_123' ORDER BY occurred_at DESC LIMIT 50`
|
|
2289
|
+
},
|
|
2290
|
+
outlit_schema: {
|
|
2291
|
+
toolName: "outlit_schema",
|
|
2292
|
+
description: `Get table schemas for available analytics tables.
|
|
2293
|
+
|
|
2294
|
+
Use this to discover column names, types, and descriptions before writing SQL queries.
|
|
2295
|
+
Returns column definitions and example queries for each table.`
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
customerBillingStatuses = [
|
|
2299
|
+
"NONE",
|
|
2300
|
+
"TRIALING",
|
|
2301
|
+
"PAYING",
|
|
2302
|
+
"PAST_DUE",
|
|
2303
|
+
"CHURNED"
|
|
2304
|
+
];
|
|
2305
|
+
customerFactStatuses = [
|
|
2306
|
+
"ACTIVE",
|
|
2307
|
+
"ACKNOWLEDGED",
|
|
2308
|
+
"RESOLVED",
|
|
2309
|
+
"SNOOZED",
|
|
2310
|
+
"CANDIDATE"
|
|
2311
|
+
];
|
|
2312
|
+
customerIncludeSections = [
|
|
2313
|
+
"users",
|
|
2314
|
+
"revenue",
|
|
2315
|
+
"recentTimeline",
|
|
2316
|
+
"behaviorMetrics"
|
|
2317
|
+
];
|
|
2318
|
+
customerSourceTypes = ["EMAIL", "CALL", "CALENDAR_EVENT", "SUPPORT_TICKET"];
|
|
2319
|
+
customerTimeframes = ["7d", "14d", "30d", "90d"];
|
|
2320
|
+
timelineChannels = [
|
|
2321
|
+
"SDK",
|
|
2322
|
+
"EMAIL",
|
|
2323
|
+
"SLACK",
|
|
2324
|
+
"CALL",
|
|
2325
|
+
"CRM",
|
|
2326
|
+
"BILLING",
|
|
2327
|
+
"SUPPORT",
|
|
2328
|
+
"INTERNAL"
|
|
2329
|
+
];
|
|
2330
|
+
timelineTimeframes = ["7d", "14d", "30d", "90d", "all"];
|
|
2331
|
+
userJourneyStages = [
|
|
2332
|
+
"DISCOVERED",
|
|
2333
|
+
"SIGNED_UP",
|
|
2334
|
+
"ACTIVATED",
|
|
2335
|
+
"ENGAGED",
|
|
2336
|
+
"INACTIVE"
|
|
2337
|
+
];
|
|
2338
|
+
schemaTables = [
|
|
2339
|
+
"events",
|
|
2340
|
+
"customer_dimensions",
|
|
2341
|
+
"user_dimensions",
|
|
2342
|
+
"mrr_snapshots"
|
|
2343
|
+
];
|
|
2344
|
+
});
|
|
2345
|
+
|
|
2222
2346
|
// src/lib/format.ts
|
|
2223
2347
|
function formatCents(value) {
|
|
2224
2348
|
if (value == null || typeof value !== "number" || Number.isNaN(value))
|
|
@@ -2282,6 +2406,7 @@ var init_list = __esm(() => {
|
|
|
2282
2406
|
init_filters();
|
|
2283
2407
|
init_output2();
|
|
2284
2408
|
init_pagination();
|
|
2409
|
+
init_tool_contracts();
|
|
2285
2410
|
init_api();
|
|
2286
2411
|
init_output();
|
|
2287
2412
|
list_default = defineCommand2({
|
|
@@ -2300,7 +2425,7 @@ var init_list = __esm(() => {
|
|
|
2300
2425
|
" outlit customers list --mrr-above 10000 --limit 50 # high-value at-risk",
|
|
2301
2426
|
" outlit customers list --json | jq '.items[].domain' # pipe-friendly",
|
|
2302
2427
|
"",
|
|
2303
|
-
|
|
2428
|
+
`Billing statuses: ${customerBillingStatuses.join(", ")}`,
|
|
2304
2429
|
"Activity periods: 7d, 14d, 30d, 90d",
|
|
2305
2430
|
"",
|
|
2306
2431
|
AGENT_JSON_HINT
|
|
@@ -2316,7 +2441,7 @@ var init_list = __esm(() => {
|
|
|
2316
2441
|
...orderArgs,
|
|
2317
2442
|
"billing-status": {
|
|
2318
2443
|
type: "string",
|
|
2319
|
-
description:
|
|
2444
|
+
description: `Filter by billing status (${customerBillingStatuses.join(", ")})`
|
|
2320
2445
|
},
|
|
2321
2446
|
"mrr-above": {
|
|
2322
2447
|
type: "string",
|
|
@@ -2329,14 +2454,6 @@ var init_list = __esm(() => {
|
|
|
2329
2454
|
search: {
|
|
2330
2455
|
type: "string",
|
|
2331
2456
|
description: "Search by customer name or domain"
|
|
2332
|
-
},
|
|
2333
|
-
status: {
|
|
2334
|
-
type: "string",
|
|
2335
|
-
description: "Customer status filter (PROVISIONAL, ACTIVE, CHURNED, MERGED)"
|
|
2336
|
-
},
|
|
2337
|
-
type: {
|
|
2338
|
-
type: "string",
|
|
2339
|
-
description: "Customer type filter (COMPANY, INDIVIDUAL)"
|
|
2340
2457
|
}
|
|
2341
2458
|
},
|
|
2342
2459
|
async run({ args }) {
|
|
@@ -2374,11 +2491,7 @@ var init_list = __esm(() => {
|
|
|
2374
2491
|
}
|
|
2375
2492
|
applyListFilters(params, args);
|
|
2376
2493
|
applyPagination(params, args, json);
|
|
2377
|
-
|
|
2378
|
-
params.status = args.status;
|
|
2379
|
-
if (args.type)
|
|
2380
|
-
params.type = args.type;
|
|
2381
|
-
return runTool(client, "outlit_list_customers", params, json, {
|
|
2494
|
+
return runTool(client, customerToolContracts.outlit_list_customers.toolName, params, json, {
|
|
2382
2495
|
spinnerMessage: "Fetching customers...",
|
|
2383
2496
|
table: {
|
|
2384
2497
|
columns: [
|
|
@@ -2404,6 +2517,7 @@ var init_get = __esm(() => {
|
|
|
2404
2517
|
init_dist();
|
|
2405
2518
|
init_auth();
|
|
2406
2519
|
init_output2();
|
|
2520
|
+
init_tool_contracts();
|
|
2407
2521
|
init_api();
|
|
2408
2522
|
init_config();
|
|
2409
2523
|
get_default = defineCommand2({
|
|
@@ -2420,6 +2534,9 @@ var init_get = __esm(() => {
|
|
|
2420
2534
|
'Naming note: --include users returns data under the "contacts" key in',
|
|
2421
2535
|
"the response. This is a server-side naming inconsistency, not a CLI bug.",
|
|
2422
2536
|
"",
|
|
2537
|
+
`Available include sections: ${customerIncludeSections.join(", ")}`,
|
|
2538
|
+
`Timeframes: ${customerTimeframes.join(", ")}`,
|
|
2539
|
+
"",
|
|
2423
2540
|
"Examples:",
|
|
2424
2541
|
" outlit customers get acme.com",
|
|
2425
2542
|
" outlit customers get acme.com --include users,revenue",
|
|
@@ -2441,7 +2558,7 @@ var init_get = __esm(() => {
|
|
|
2441
2558
|
type: "string",
|
|
2442
2559
|
description: [
|
|
2443
2560
|
"Comma-separated sections to include in response.",
|
|
2444
|
-
|
|
2561
|
+
`Available: ${customerIncludeSections.join(", ")}`,
|
|
2445
2562
|
'Note: "users" maps to "contacts" in the response (server naming).'
|
|
2446
2563
|
].join(`
|
|
2447
2564
|
`)
|
|
@@ -2462,7 +2579,7 @@ var init_get = __esm(() => {
|
|
|
2462
2579
|
if (args.include) {
|
|
2463
2580
|
params.include = splitCsv(args.include);
|
|
2464
2581
|
}
|
|
2465
|
-
return runTool(client,
|
|
2582
|
+
return runTool(client, customerToolContracts.outlit_get_customer.toolName, params, json);
|
|
2466
2583
|
}
|
|
2467
2584
|
});
|
|
2468
2585
|
});
|
|
@@ -2478,6 +2595,7 @@ var init_timeline = __esm(() => {
|
|
|
2478
2595
|
init_auth();
|
|
2479
2596
|
init_output2();
|
|
2480
2597
|
init_pagination();
|
|
2598
|
+
init_tool_contracts();
|
|
2481
2599
|
init_api();
|
|
2482
2600
|
init_config();
|
|
2483
2601
|
timeline_default = defineCommand2({
|
|
@@ -2492,6 +2610,8 @@ var init_timeline = __esm(() => {
|
|
|
2492
2610
|
"",
|
|
2493
2611
|
"Timeframe is used when no explicit date range is set.",
|
|
2494
2612
|
"When --start-date or --end-date is provided, --timeframe is ignored.",
|
|
2613
|
+
`Channels: ${timelineChannels.join(", ")}`,
|
|
2614
|
+
`Timeframes: ${timelineTimeframes.join(", ")}`,
|
|
2495
2615
|
"",
|
|
2496
2616
|
"Examples:",
|
|
2497
2617
|
" outlit customers timeline acme.com",
|
|
@@ -2515,7 +2635,7 @@ var init_timeline = __esm(() => {
|
|
|
2515
2635
|
},
|
|
2516
2636
|
channels: {
|
|
2517
2637
|
type: "string",
|
|
2518
|
-
description:
|
|
2638
|
+
description: `Comma-separated list of channels to filter (${timelineChannels.join(", ")})`
|
|
2519
2639
|
},
|
|
2520
2640
|
"event-types": {
|
|
2521
2641
|
type: "string",
|
|
@@ -2523,7 +2643,7 @@ var init_timeline = __esm(() => {
|
|
|
2523
2643
|
},
|
|
2524
2644
|
timeframe: {
|
|
2525
2645
|
type: "string",
|
|
2526
|
-
description:
|
|
2646
|
+
description: `Timeframe for events (${timelineTimeframes.join(", ")}). Ignored when --start-date or --end-date is set.`,
|
|
2527
2647
|
default: "30d"
|
|
2528
2648
|
},
|
|
2529
2649
|
"start-date": {
|
|
@@ -2555,7 +2675,7 @@ var init_timeline = __esm(() => {
|
|
|
2555
2675
|
params.eventTypes = splitCsv(args["event-types"]);
|
|
2556
2676
|
}
|
|
2557
2677
|
applyPagination(params, args, json);
|
|
2558
|
-
return runTool(client,
|
|
2678
|
+
return runTool(client, customerToolContracts.outlit_get_timeline.toolName, params, json);
|
|
2559
2679
|
}
|
|
2560
2680
|
});
|
|
2561
2681
|
});
|
|
@@ -2604,6 +2724,7 @@ var init_list2 = __esm(() => {
|
|
|
2604
2724
|
init_filters();
|
|
2605
2725
|
init_output2();
|
|
2606
2726
|
init_pagination();
|
|
2727
|
+
init_tool_contracts();
|
|
2607
2728
|
init_api();
|
|
2608
2729
|
init_output();
|
|
2609
2730
|
list_default2 = defineCommand2({
|
|
@@ -2617,7 +2738,7 @@ var init_list2 = __esm(() => {
|
|
|
2617
2738
|
"",
|
|
2618
2739
|
"Examples:",
|
|
2619
2740
|
" outlit users list # all users",
|
|
2620
|
-
" outlit users list --journey-stage
|
|
2741
|
+
" outlit users list --journey-stage ENGAGED # engaged users only",
|
|
2621
2742
|
" outlit users list --customer-id <uuid> # users for a customer",
|
|
2622
2743
|
" outlit users list --no-activity-in 30d # inactive users",
|
|
2623
2744
|
" outlit users list --search alice --order-by last_activity_at",
|
|
@@ -2634,7 +2755,7 @@ var init_list2 = __esm(() => {
|
|
|
2634
2755
|
...traitFilterArgs,
|
|
2635
2756
|
"journey-stage": {
|
|
2636
2757
|
type: "string",
|
|
2637
|
-
description:
|
|
2758
|
+
description: `Filter by journey stage (${userJourneyStages.join(", ")})`
|
|
2638
2759
|
},
|
|
2639
2760
|
"customer-id": {
|
|
2640
2761
|
type: "string",
|
|
@@ -2670,7 +2791,7 @@ var init_list2 = __esm(() => {
|
|
|
2670
2791
|
}
|
|
2671
2792
|
applyListFilters(params, args);
|
|
2672
2793
|
applyPagination(params, args, json);
|
|
2673
|
-
return runTool(client,
|
|
2794
|
+
return runTool(client, customerToolContracts.outlit_list_users.toolName, params, json, {
|
|
2674
2795
|
spinnerMessage: "Fetching users...",
|
|
2675
2796
|
table: {
|
|
2676
2797
|
columns: [
|
|
@@ -2714,376 +2835,213 @@ var init_users = __esm(() => {
|
|
|
2714
2835
|
});
|
|
2715
2836
|
});
|
|
2716
2837
|
|
|
2717
|
-
// src/lib/
|
|
2718
|
-
import { execFileSync as
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2838
|
+
// src/lib/update.ts
|
|
2839
|
+
import { execFileSync as execFileSync3, spawn as spawn2, spawnSync as spawnSync2 } from "node:child_process";
|
|
2840
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, realpathSync as realpathSync2, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
2841
|
+
import { homedir as homedir3 } from "node:os";
|
|
2842
|
+
import { dirname as dirname3, join as join4 } from "node:path";
|
|
2843
|
+
function compareVersions2(a, b) {
|
|
2844
|
+
const aParts = a.split("-")[0]?.split(".").map((part) => Number.parseInt(part, 10) || 0) ?? [];
|
|
2845
|
+
const bParts = b.split("-")[0]?.split(".").map((part) => Number.parseInt(part, 10) || 0) ?? [];
|
|
2846
|
+
const maxLength = Math.max(aParts.length, bParts.length);
|
|
2847
|
+
for (let index = 0;index < maxLength; index++) {
|
|
2848
|
+
const left = aParts[index] ?? 0;
|
|
2849
|
+
const right = bParts[index] ?? 0;
|
|
2850
|
+
if (left > right)
|
|
2851
|
+
return 1;
|
|
2852
|
+
if (left < right)
|
|
2853
|
+
return -1;
|
|
2854
|
+
}
|
|
2855
|
+
return 0;
|
|
2856
|
+
}
|
|
2857
|
+
function inferInstallerFromUserAgent2(agent) {
|
|
2858
|
+
if (agent.startsWith("bun/"))
|
|
2859
|
+
return "bun";
|
|
2860
|
+
if (agent.startsWith("npm/"))
|
|
2861
|
+
return "npm";
|
|
2862
|
+
if (agent.startsWith("pnpm/"))
|
|
2863
|
+
return "pnpm";
|
|
2864
|
+
if (agent.startsWith("yarn/"))
|
|
2865
|
+
return "yarn";
|
|
2866
|
+
return null;
|
|
2867
|
+
}
|
|
2868
|
+
function isUnderPath2(path, parent) {
|
|
2869
|
+
const normalizedPath = normalizeInstallerPath2(path);
|
|
2870
|
+
const normalizedParent = normalizeInstallerPath2(parent);
|
|
2871
|
+
return normalizedPath === normalizedParent || normalizedPath.startsWith(`${normalizedParent}/`);
|
|
2872
|
+
}
|
|
2873
|
+
function normalizeInstallerPath2(path) {
|
|
2874
|
+
return path.replace(/^\/private\/tmp\//, "/tmp/");
|
|
2875
|
+
}
|
|
2876
|
+
function inferInstallerFromInstallation2(opts) {
|
|
2877
|
+
const candidatePaths = [opts.argv1, opts.realExecPath].filter((value) => !!value);
|
|
2878
|
+
if (opts.npmGlobalPrefix) {
|
|
2879
|
+
const npmPackageRoots = [
|
|
2880
|
+
join4(opts.npmGlobalPrefix, "node_modules", PACKAGE_NAME2),
|
|
2881
|
+
join4(opts.npmGlobalPrefix, "lib", "node_modules", PACKAGE_NAME2)
|
|
2882
|
+
];
|
|
2883
|
+
if (candidatePaths.some((path) => npmPackageRoots.some((root) => isUnderPath2(path, root)))) {
|
|
2884
|
+
return "npm";
|
|
2738
2885
|
}
|
|
2739
|
-
return { success: false, error: errorMessage(err, `${opts.cliName} mcp add failed`) };
|
|
2740
2886
|
}
|
|
2741
|
-
if (
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
return
|
|
2887
|
+
if (opts.bunGlobalBin) {
|
|
2888
|
+
const bunGlobalBin = opts.bunGlobalBin;
|
|
2889
|
+
if (candidatePaths.some((path) => isUnderPath2(path, bunGlobalBin))) {
|
|
2890
|
+
return "bun";
|
|
2745
2891
|
}
|
|
2746
|
-
console.log(`${TICK2} ${opts.successMessage}`);
|
|
2747
2892
|
}
|
|
2748
|
-
return
|
|
2893
|
+
return null;
|
|
2749
2894
|
}
|
|
2750
|
-
function
|
|
2751
|
-
const mcpConfig = opts.mcpConfig ?? {
|
|
2752
|
-
url: DEFAULT_MCP_URL,
|
|
2753
|
-
headers: { Authorization: `Bearer ${key}` }
|
|
2754
|
-
};
|
|
2895
|
+
function readCommandOutput2(command, args) {
|
|
2755
2896
|
try {
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2897
|
+
return execFileSync3(command, args, {
|
|
2898
|
+
encoding: "utf8",
|
|
2899
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2900
|
+
}).trim();
|
|
2901
|
+
} catch {
|
|
2902
|
+
return null;
|
|
2762
2903
|
}
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2904
|
+
}
|
|
2905
|
+
function inferInstaller2() {
|
|
2906
|
+
const fromAgent = inferInstallerFromUserAgent2(process.env.npm_config_user_agent ?? "");
|
|
2907
|
+
if (fromAgent)
|
|
2908
|
+
return fromAgent;
|
|
2909
|
+
const argv1 = process.argv[1];
|
|
2910
|
+
const realExecPath = argv1 ? readCommandOutput2("realpath", [argv1]) ?? safeRealPath2(argv1) : null;
|
|
2911
|
+
const npmGlobalPrefix = process.env.npm_config_prefix ?? readCommandOutput2("npm", ["prefix", "-g"]);
|
|
2912
|
+
const bunGlobalBin = process.env.BUN_INSTALL ? join4(process.env.BUN_INSTALL, "bin") : readCommandOutput2("bun", ["pm", "bin", "-g"]) ?? join4(homedir3(), ".bun", "bin");
|
|
2913
|
+
return inferInstallerFromInstallation2({
|
|
2914
|
+
argv1,
|
|
2915
|
+
realExecPath,
|
|
2916
|
+
npmGlobalPrefix,
|
|
2917
|
+
bunGlobalBin
|
|
2918
|
+
});
|
|
2919
|
+
}
|
|
2920
|
+
function safeRealPath2(filePath) {
|
|
2921
|
+
try {
|
|
2922
|
+
return realpathSync2(filePath);
|
|
2923
|
+
} catch {
|
|
2924
|
+
return null;
|
|
2769
2925
|
}
|
|
2770
|
-
return { success: true };
|
|
2771
2926
|
}
|
|
2772
|
-
|
|
2927
|
+
function formatUpdateCommand2(installer = inferInstaller2()) {
|
|
2928
|
+
switch (installer) {
|
|
2929
|
+
case "bun":
|
|
2930
|
+
return "bun add -g @outlit/cli";
|
|
2931
|
+
case "npm":
|
|
2932
|
+
return "npm install -g @outlit/cli";
|
|
2933
|
+
case "pnpm":
|
|
2934
|
+
return "pnpm add -g @outlit/cli";
|
|
2935
|
+
case "yarn":
|
|
2936
|
+
return "yarn global add @outlit/cli";
|
|
2937
|
+
default:
|
|
2938
|
+
return `update ${PACKAGE_NAME2} with your package manager`;
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
function getUpgradeCommand(installer = inferInstaller2()) {
|
|
2942
|
+
switch (installer) {
|
|
2943
|
+
case "bun":
|
|
2944
|
+
return {
|
|
2945
|
+
command: "bun",
|
|
2946
|
+
args: ["add", "-g", "@outlit/cli"],
|
|
2947
|
+
displayCommand: "bun add -g @outlit/cli"
|
|
2948
|
+
};
|
|
2949
|
+
case "npm":
|
|
2950
|
+
return {
|
|
2951
|
+
command: "npm",
|
|
2952
|
+
args: ["install", "-g", "@outlit/cli"],
|
|
2953
|
+
displayCommand: "npm install -g @outlit/cli"
|
|
2954
|
+
};
|
|
2955
|
+
case "pnpm":
|
|
2956
|
+
return {
|
|
2957
|
+
command: "pnpm",
|
|
2958
|
+
args: ["add", "-g", "@outlit/cli"],
|
|
2959
|
+
displayCommand: "pnpm add -g @outlit/cli"
|
|
2960
|
+
};
|
|
2961
|
+
case "yarn":
|
|
2962
|
+
return {
|
|
2963
|
+
command: "yarn",
|
|
2964
|
+
args: ["global", "add", "@outlit/cli"],
|
|
2965
|
+
displayCommand: "yarn global add @outlit/cli"
|
|
2966
|
+
};
|
|
2967
|
+
default:
|
|
2968
|
+
return null;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
async function fetchLatestCliVersion2() {
|
|
2972
|
+
const response = await fetch(LATEST_VERSION_URL2, { signal: AbortSignal.timeout(5000) });
|
|
2973
|
+
if (!response.ok)
|
|
2974
|
+
throw new Error("registry unavailable");
|
|
2975
|
+
const data = await response.json();
|
|
2976
|
+
if (!data.version)
|
|
2977
|
+
throw new Error("registry returned no version");
|
|
2978
|
+
return data.version;
|
|
2979
|
+
}
|
|
2980
|
+
function runUpgradeCommand(command) {
|
|
2981
|
+
const result = spawnSync2(command.command, command.args, { stdio: "inherit" });
|
|
2982
|
+
if (result.error)
|
|
2983
|
+
throw result.error;
|
|
2984
|
+
if (result.status !== 0 || result.signal) {
|
|
2985
|
+
throw new Error(`Upgrade command failed: ${command.displayCommand}`);
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
var UPDATE_CHECK_INTERVAL_MS2, PACKAGE_NAME2 = "@outlit/cli", LATEST_VERSION_URL2 = "https://registry.npmjs.org/@outlit%2Fcli/latest";
|
|
2989
|
+
var init_update = __esm(() => {
|
|
2773
2990
|
init_config();
|
|
2774
|
-
|
|
2991
|
+
init_tty();
|
|
2992
|
+
UPDATE_CHECK_INTERVAL_MS2 = 12 * 60 * 60 * 1000;
|
|
2775
2993
|
});
|
|
2776
2994
|
|
|
2777
|
-
// src/commands/setup/
|
|
2778
|
-
var
|
|
2779
|
-
__export(
|
|
2780
|
-
|
|
2781
|
-
|
|
2995
|
+
// src/commands/setup/skills.ts
|
|
2996
|
+
var exports_skills = {};
|
|
2997
|
+
__export(exports_skills, {
|
|
2998
|
+
runSkillsInstall: () => runSkillsInstall,
|
|
2999
|
+
runAgentSkillsInstall: () => runAgentSkillsInstall,
|
|
3000
|
+
getSkillAgentId: () => getSkillAgentId,
|
|
3001
|
+
detectPackageRunner: () => detectPackageRunner,
|
|
3002
|
+
default: () => skills_default,
|
|
3003
|
+
SKILLS_REPO_URL: () => SKILLS_REPO_URL
|
|
2782
3004
|
});
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
var getConfig = () => ({
|
|
2787
|
-
cliName: "claude",
|
|
2788
|
-
agentId: "claude-code",
|
|
2789
|
-
notFoundMessage: "claude CLI not found. Install from https://claude.ai/code",
|
|
2790
|
-
notFoundCode: "claude_not_found",
|
|
2791
|
-
successMessage: "Outlit added to Claude Code. Restart Claude Code to apply."
|
|
2792
|
-
}), claude_code_default;
|
|
2793
|
-
var init_claude_code = __esm(() => {
|
|
2794
|
-
init_dist();
|
|
2795
|
-
init_auth();
|
|
2796
|
-
init_output2();
|
|
2797
|
-
init_config();
|
|
2798
|
-
init_setup();
|
|
2799
|
-
claude_code_default = defineCommand2({
|
|
2800
|
-
meta: {
|
|
2801
|
-
name: "claude-code",
|
|
2802
|
-
description: "Register Outlit MCP server with Claude Code via `claude mcp add`."
|
|
2803
|
-
},
|
|
2804
|
-
args: { ...authArgs, ...outputArgs },
|
|
2805
|
-
run({ args }) {
|
|
2806
|
-
const json = !!args.json;
|
|
2807
|
-
const { key } = requireCredential(args["api-key"], json);
|
|
2808
|
-
runMcpCliSetup(key, json, getConfig());
|
|
2809
|
-
}
|
|
2810
|
-
});
|
|
2811
|
-
});
|
|
2812
|
-
|
|
2813
|
-
// src/commands/setup/claude-desktop.ts
|
|
2814
|
-
var exports_claude_desktop = {};
|
|
2815
|
-
__export(exports_claude_desktop, {
|
|
2816
|
-
default: () => claude_desktop_default,
|
|
2817
|
-
configureSafe: () => configureSafe2
|
|
2818
|
-
});
|
|
2819
|
-
function configureSafe2(key, json) {
|
|
2820
|
-
return runMcpFileSetup(key, json, getConfig2(key), false).success;
|
|
2821
|
-
}
|
|
2822
|
-
var getConfig2 = (key) => {
|
|
2823
|
-
const configPath = getClaudeDesktopConfigPath();
|
|
2824
|
-
return {
|
|
2825
|
-
agentId: "claude-desktop",
|
|
2826
|
-
configPath,
|
|
2827
|
-
serversKey: "mcpServers",
|
|
2828
|
-
label: "Claude Desktop config",
|
|
2829
|
-
successMessage: `Outlit added to Claude Desktop. Restart Claude Desktop to apply.
|
|
2830
|
-
Config: ${configPath}`,
|
|
2831
|
-
mcpConfig: { command: "outlit", args: ["mcp", "serve"], env: { OUTLIT_API_KEY: key } }
|
|
2832
|
-
};
|
|
2833
|
-
}, claude_desktop_default;
|
|
2834
|
-
var init_claude_desktop = __esm(() => {
|
|
2835
|
-
init_dist();
|
|
2836
|
-
init_auth();
|
|
2837
|
-
init_output2();
|
|
2838
|
-
init_config();
|
|
2839
|
-
init_setup();
|
|
2840
|
-
claude_desktop_default = defineCommand2({
|
|
2841
|
-
meta: {
|
|
2842
|
-
name: "claude-desktop",
|
|
2843
|
-
description: "Add Outlit MCP server to Claude Desktop config."
|
|
2844
|
-
},
|
|
2845
|
-
args: { ...authArgs, ...outputArgs },
|
|
2846
|
-
run({ args }) {
|
|
2847
|
-
const json = !!args.json;
|
|
2848
|
-
const { key } = requireCredential(args["api-key"], json);
|
|
2849
|
-
runMcpFileSetup(key, json, getConfig2(key));
|
|
2850
|
-
}
|
|
2851
|
-
});
|
|
2852
|
-
});
|
|
2853
|
-
|
|
2854
|
-
// src/commands/setup/cursor.ts
|
|
2855
|
-
var exports_cursor = {};
|
|
2856
|
-
__export(exports_cursor, {
|
|
2857
|
-
default: () => cursor_default,
|
|
2858
|
-
configureSafe: () => configureSafe3
|
|
2859
|
-
});
|
|
2860
|
-
import { homedir as homedir2 } from "node:os";
|
|
2861
|
-
import { join as join3 } from "node:path";
|
|
2862
|
-
function configureSafe3(key, json) {
|
|
2863
|
-
return runMcpFileSetup(key, json, getConfig3(), false).success;
|
|
2864
|
-
}
|
|
2865
|
-
var getConfig3 = () => ({
|
|
2866
|
-
agentId: "cursor",
|
|
2867
|
-
configPath: join3(homedir2(), ".cursor", "mcp.json"),
|
|
2868
|
-
serversKey: "mcpServers",
|
|
2869
|
-
label: "cursor mcp.json",
|
|
2870
|
-
successMessage: `Outlit added to Cursor MCP config. Restart Cursor to apply.
|
|
2871
|
-
Config: ~/.cursor/mcp.json`
|
|
2872
|
-
}), cursor_default;
|
|
2873
|
-
var init_cursor = __esm(() => {
|
|
2874
|
-
init_dist();
|
|
2875
|
-
init_auth();
|
|
2876
|
-
init_output2();
|
|
2877
|
-
init_config();
|
|
2878
|
-
init_setup();
|
|
2879
|
-
cursor_default = defineCommand2({
|
|
2880
|
-
meta: {
|
|
2881
|
-
name: "cursor",
|
|
2882
|
-
description: "Add Outlit MCP server to ~/.cursor/mcp.json."
|
|
2883
|
-
},
|
|
2884
|
-
args: { ...authArgs, ...outputArgs },
|
|
2885
|
-
run({ args }) {
|
|
2886
|
-
const json = !!args.json;
|
|
2887
|
-
const { key } = requireCredential(args["api-key"], json);
|
|
2888
|
-
runMcpFileSetup(key, json, getConfig3());
|
|
2889
|
-
}
|
|
2890
|
-
});
|
|
2891
|
-
});
|
|
2892
|
-
|
|
2893
|
-
// src/commands/setup/gemini.ts
|
|
2894
|
-
var exports_gemini = {};
|
|
2895
|
-
__export(exports_gemini, {
|
|
2896
|
-
default: () => gemini_default,
|
|
2897
|
-
configureSafe: () => configureSafe4
|
|
2898
|
-
});
|
|
2899
|
-
function configureSafe4(key, json) {
|
|
2900
|
-
return runMcpCliSetup(key, json, getConfig4(), false).success;
|
|
2901
|
-
}
|
|
2902
|
-
var getConfig4 = () => ({
|
|
2903
|
-
cliName: "gemini",
|
|
2904
|
-
agentId: "gemini",
|
|
2905
|
-
notFoundMessage: "gemini CLI not found. Install from https://github.com/google-gemini/gemini-cli",
|
|
2906
|
-
notFoundCode: "gemini_not_found",
|
|
2907
|
-
successMessage: "Outlit added to Gemini CLI. Restart Gemini CLI to apply."
|
|
2908
|
-
}), gemini_default;
|
|
2909
|
-
var init_gemini = __esm(() => {
|
|
2910
|
-
init_dist();
|
|
2911
|
-
init_auth();
|
|
2912
|
-
init_output2();
|
|
2913
|
-
init_config();
|
|
2914
|
-
init_output();
|
|
2915
|
-
init_setup();
|
|
2916
|
-
gemini_default = defineCommand2({
|
|
2917
|
-
meta: {
|
|
2918
|
-
name: "gemini",
|
|
2919
|
-
description: "Register Outlit MCP server with Gemini CLI via `gemini mcp add`."
|
|
2920
|
-
},
|
|
2921
|
-
args: { ...authArgs, ...outputArgs },
|
|
2922
|
-
run({ args }) {
|
|
2923
|
-
const json = !!args.json;
|
|
2924
|
-
const { key } = requireCredential(args["api-key"], json);
|
|
2925
|
-
runMcpCliSetup(key, json, {
|
|
2926
|
-
...getConfig4(),
|
|
2927
|
-
extraErrorHandler(err, j2) {
|
|
2928
|
-
const msg = err instanceof Error ? err.message.toLowerCase() : "";
|
|
2929
|
-
if (msg.includes("mcp") && msg.includes("not")) {
|
|
2930
|
-
outputError({
|
|
2931
|
-
message: "Your Gemini CLI version does not support 'mcp add'. Run 'gemini update' or reinstall.",
|
|
2932
|
-
code: "gemini_mcp_unsupported"
|
|
2933
|
-
}, j2);
|
|
2934
|
-
}
|
|
2935
|
-
}
|
|
2936
|
-
});
|
|
2937
|
-
}
|
|
2938
|
-
});
|
|
2939
|
-
});
|
|
2940
|
-
|
|
2941
|
-
// src/commands/setup/openclaw.ts
|
|
2942
|
-
var exports_openclaw = {};
|
|
2943
|
-
__export(exports_openclaw, {
|
|
2944
|
-
getSkillDir: () => getSkillDir,
|
|
2945
|
-
default: () => openclaw_default,
|
|
2946
|
-
configureSafe: () => configureSafe5,
|
|
2947
|
-
buildSkillContent: () => buildSkillContent
|
|
2948
|
-
});
|
|
2949
|
-
import { homedir as homedir3 } from "node:os";
|
|
2950
|
-
import { join as join4 } from "node:path";
|
|
2951
|
-
function getSkillDir() {
|
|
2952
|
-
const home = homedir3();
|
|
2953
|
-
return join4(home, ".openclaw", "skills", "outlit");
|
|
2954
|
-
}
|
|
2955
|
-
function buildSkillContent(maskedKey) {
|
|
2956
|
-
return `---
|
|
2957
|
-
name: outlit
|
|
2958
|
-
description: Query customer data, revenue metrics, and analytics via the Outlit CLI.
|
|
2959
|
-
metadata:
|
|
2960
|
-
openclaw:
|
|
2961
|
-
requires:
|
|
2962
|
-
bins: ["outlit"]
|
|
2963
|
-
env: ["OUTLIT_API_KEY"]
|
|
2964
|
-
---
|
|
2965
|
-
|
|
2966
|
-
# Outlit Customer Intelligence
|
|
2967
|
-
|
|
2968
|
-
You have access to the \`outlit\` CLI for querying customer data and analytics.
|
|
2969
|
-
The CLI outputs structured JSON automatically in non-TTY contexts.
|
|
2970
|
-
|
|
2971
|
-
## Authentication
|
|
2972
|
-
|
|
2973
|
-
Set the env var before running any command:
|
|
2974
|
-
|
|
2975
|
-
export OUTLIT_API_KEY=${maskedKey}
|
|
2976
|
-
|
|
2977
|
-
## List customers
|
|
2978
|
-
|
|
2979
|
-
outlit customers list --billing-status PAYING --no-activity-in 30d --order-by mrr_cents
|
|
2980
|
-
|
|
2981
|
-
## Get customer details
|
|
2982
|
-
|
|
2983
|
-
outlit customers get acme.com --include users,revenue,recentTimeline
|
|
2984
|
-
|
|
2985
|
-
## Get customer activity timeline
|
|
2986
|
-
|
|
2987
|
-
outlit customers timeline acme.com --channels EMAIL,SLACK --limit 50
|
|
2988
|
-
|
|
2989
|
-
## List users for a customer
|
|
2990
|
-
|
|
2991
|
-
outlit users list --customer-id <uuid> --journey-stage ACTIVATED
|
|
2992
|
-
|
|
2993
|
-
## Search across customer context
|
|
2994
|
-
|
|
2995
|
-
outlit search "budget concerns" --customer acme.com
|
|
2996
|
-
|
|
2997
|
-
## Get facts about a customer
|
|
2998
|
-
|
|
2999
|
-
outlit facts acme.com --timeframe 90d
|
|
3000
|
-
|
|
3001
|
-
## Run custom SQL
|
|
3002
|
-
|
|
3003
|
-
outlit sql "SELECT event_type, count(*) FROM events GROUP BY 1 ORDER BY 2 DESC LIMIT 10"
|
|
3004
|
-
|
|
3005
|
-
## Query with a file (for complex SQL)
|
|
3006
|
-
|
|
3007
|
-
outlit sql --query-file /tmp/query.sql
|
|
3008
|
-
|
|
3009
|
-
## Discover table schemas
|
|
3010
|
-
|
|
3011
|
-
outlit schema
|
|
3012
|
-
outlit schema events
|
|
3013
|
-
|
|
3014
|
-
## Rules
|
|
3015
|
-
- Always parse the JSON response before reporting to the user
|
|
3016
|
-
- Convert monetary values from cents to dollars (divide by 100)
|
|
3017
|
-
- IDs are UUIDs (e.g., "a1b2c3d4-e5f6-...")
|
|
3018
|
-
- Never show the raw API key to the user
|
|
3019
|
-
- Use --query-file for complex SQL to avoid shell escaping issues
|
|
3020
|
-
- All list responses include pagination.hasMore and pagination.nextCursor
|
|
3021
|
-
`;
|
|
3022
|
-
}
|
|
3023
|
-
function configureSafe5(key, json) {
|
|
3024
|
-
const skillPath = join4(getSkillDir(), "SKILL.md");
|
|
3025
|
-
try {
|
|
3026
|
-
writeConfigFile(skillPath, buildSkillContent(maskKey(key)), { json, label: "SKILL.md" });
|
|
3027
|
-
return true;
|
|
3028
|
-
} catch {
|
|
3029
|
-
return false;
|
|
3030
|
-
}
|
|
3005
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
3006
|
+
function getSkillAgentId(agent) {
|
|
3007
|
+
return skillAgentMap[agent];
|
|
3031
3008
|
}
|
|
3032
|
-
var openclaw_default;
|
|
3033
|
-
var init_openclaw = __esm(() => {
|
|
3034
|
-
init_dist();
|
|
3035
|
-
init_auth();
|
|
3036
|
-
init_output2();
|
|
3037
|
-
init_config();
|
|
3038
|
-
init_output();
|
|
3039
|
-
openclaw_default = defineCommand2({
|
|
3040
|
-
meta: {
|
|
3041
|
-
name: "openclaw",
|
|
3042
|
-
description: "Write Outlit skill to ~/.openclaw/skills/ for OpenClaw."
|
|
3043
|
-
},
|
|
3044
|
-
args: { ...authArgs, ...outputArgs },
|
|
3045
|
-
run({ args }) {
|
|
3046
|
-
const json = !!args.json;
|
|
3047
|
-
const { key } = requireCredential(args["api-key"], json);
|
|
3048
|
-
const skillPath = join4(getSkillDir(), "SKILL.md");
|
|
3049
|
-
const content = buildSkillContent(maskKey(key));
|
|
3050
|
-
writeConfigFile(skillPath, content, { json, label: "SKILL.md" });
|
|
3051
|
-
if (isJsonMode(json)) {
|
|
3052
|
-
return outputResult({ success: true, path: skillPath, agent: "openclaw" });
|
|
3053
|
-
}
|
|
3054
|
-
console.log(`${TICK2} Outlit skill written to ${skillPath}. OpenClaw will load it automatically.`);
|
|
3055
|
-
}
|
|
3056
|
-
});
|
|
3057
|
-
});
|
|
3058
|
-
|
|
3059
|
-
// src/commands/setup/skills.ts
|
|
3060
|
-
var exports_skills = {};
|
|
3061
|
-
__export(exports_skills, {
|
|
3062
|
-
runSkillsInstall: () => runSkillsInstall,
|
|
3063
|
-
detectPackageRunner: () => detectPackageRunner,
|
|
3064
|
-
default: () => skills_default
|
|
3065
|
-
});
|
|
3066
|
-
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
3067
3009
|
function detectPackageRunner() {
|
|
3068
3010
|
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
3069
3011
|
for (const runner of ["npx", "bunx", "pnpx"]) {
|
|
3070
3012
|
try {
|
|
3071
|
-
|
|
3013
|
+
execFileSync4(whichCmd, [runner], { stdio: "ignore" });
|
|
3072
3014
|
return runner;
|
|
3073
3015
|
} catch {}
|
|
3074
3016
|
}
|
|
3075
3017
|
return null;
|
|
3076
3018
|
}
|
|
3077
|
-
function buildRunnerArgs(runner) {
|
|
3019
|
+
function buildRunnerArgs(runner, opts) {
|
|
3078
3020
|
const args = runner === "npx" ? ["-y"] : [];
|
|
3079
3021
|
args.push("skills", "add", SKILLS_REPO_URL);
|
|
3080
|
-
for (const
|
|
3081
|
-
args.push("--skill",
|
|
3022
|
+
for (const skillName of opts.skillNames ?? []) {
|
|
3023
|
+
args.push("--skill", skillName);
|
|
3024
|
+
}
|
|
3025
|
+
for (const agent of opts.agents ?? []) {
|
|
3026
|
+
args.push("--agent", agent);
|
|
3027
|
+
}
|
|
3028
|
+
if (opts.autoConfirm) {
|
|
3029
|
+
args.push("-y");
|
|
3030
|
+
}
|
|
3031
|
+
if (opts.global !== false) {
|
|
3032
|
+
args.push("-g");
|
|
3082
3033
|
}
|
|
3083
|
-
args.push("-y", "-g");
|
|
3084
3034
|
return args;
|
|
3085
3035
|
}
|
|
3086
|
-
function runSkillsInstall(
|
|
3036
|
+
function runSkillsInstall(opts) {
|
|
3037
|
+
const {
|
|
3038
|
+
json,
|
|
3039
|
+
exitOnError = true,
|
|
3040
|
+
agents,
|
|
3041
|
+
skillNames,
|
|
3042
|
+
reportedAgent = "skills",
|
|
3043
|
+
autoConfirm = false
|
|
3044
|
+
} = opts;
|
|
3087
3045
|
const runner = detectPackageRunner();
|
|
3088
3046
|
if (!runner) {
|
|
3089
3047
|
if (exitOnError) {
|
|
@@ -3094,8 +3052,11 @@ function runSkillsInstall(json, exitOnError = true) {
|
|
|
3094
3052
|
}
|
|
3095
3053
|
return { success: false, error: "No package runner found" };
|
|
3096
3054
|
}
|
|
3055
|
+
const isInteractiveInstall = (agents?.length ?? 0) === 0 && (skillNames?.length ?? 0) === 0 && !autoConfirm && !isJsonMode(json);
|
|
3097
3056
|
try {
|
|
3098
|
-
|
|
3057
|
+
execFileSync4(runner, buildRunnerArgs(runner, { agents, skillNames, autoConfirm }), {
|
|
3058
|
+
stdio: isInteractiveInstall ? "inherit" : "pipe"
|
|
3059
|
+
});
|
|
3099
3060
|
} catch (err) {
|
|
3100
3061
|
if (exitOnError) {
|
|
3101
3062
|
if (isEnoentError(err)) {
|
|
@@ -3114,210 +3075,355 @@ function runSkillsInstall(json, exitOnError = true) {
|
|
|
3114
3075
|
}
|
|
3115
3076
|
if (exitOnError) {
|
|
3116
3077
|
if (isJsonMode(json)) {
|
|
3117
|
-
outputResult({ success: true, agent:
|
|
3078
|
+
outputResult({ success: true, agent: reportedAgent, runner });
|
|
3118
3079
|
return { success: true, runner };
|
|
3119
3080
|
}
|
|
3120
|
-
|
|
3081
|
+
if (reportedAgent === "skills") {
|
|
3082
|
+
console.log(`${TICK2} Outlit skills installer completed (${runner})`);
|
|
3083
|
+
} else {
|
|
3084
|
+
console.log(`${TICK2} Outlit skill installed for ${reportedAgent}`);
|
|
3085
|
+
}
|
|
3121
3086
|
}
|
|
3122
3087
|
return { success: true, runner };
|
|
3123
3088
|
}
|
|
3124
|
-
|
|
3089
|
+
function runAgentSkillsInstall(agent, json, exitOnError = true) {
|
|
3090
|
+
return runSkillsInstall({
|
|
3091
|
+
json,
|
|
3092
|
+
exitOnError,
|
|
3093
|
+
agents: [getSkillAgentId(agent)],
|
|
3094
|
+
skillNames: [DEFAULT_SKILL_NAME],
|
|
3095
|
+
reportedAgent: agent,
|
|
3096
|
+
autoConfirm: true
|
|
3097
|
+
});
|
|
3098
|
+
}
|
|
3099
|
+
var SKILLS_REPO_URL = "https://github.com/OutlitAI/outlit-agent-skills", DEFAULT_SKILL_NAME = "outlit", skillAgentMap, skills_default;
|
|
3125
3100
|
var init_skills = __esm(() => {
|
|
3126
3101
|
init_dist();
|
|
3127
3102
|
init_output2();
|
|
3128
3103
|
init_config();
|
|
3129
3104
|
init_output();
|
|
3130
|
-
|
|
3105
|
+
skillAgentMap = {
|
|
3106
|
+
"claude-code": "claude-code",
|
|
3107
|
+
codex: "codex",
|
|
3108
|
+
gemini: "gemini-cli",
|
|
3109
|
+
droid: "droid",
|
|
3110
|
+
opencode: "opencode",
|
|
3111
|
+
pi: "pi",
|
|
3112
|
+
openclaw: "openclaw"
|
|
3113
|
+
};
|
|
3131
3114
|
skills_default = defineCommand2({
|
|
3132
3115
|
meta: {
|
|
3133
3116
|
name: "skills",
|
|
3134
3117
|
description: [
|
|
3135
|
-
"
|
|
3118
|
+
"Launch the interactive Skills installer for Outlit.",
|
|
3136
3119
|
"",
|
|
3137
|
-
"
|
|
3120
|
+
"Uses the Outlit skills repo and lets you choose `outlit` and optional extras like `outlit-sdk`.",
|
|
3138
3121
|
"No API key required."
|
|
3139
3122
|
].join(`
|
|
3140
3123
|
`)
|
|
3141
3124
|
},
|
|
3142
3125
|
args: { ...outputArgs },
|
|
3143
3126
|
run({ args }) {
|
|
3144
|
-
|
|
3145
|
-
runSkillsInstall(json);
|
|
3127
|
+
runSkillsInstall({ json: !!args.json });
|
|
3146
3128
|
}
|
|
3147
3129
|
});
|
|
3148
3130
|
});
|
|
3149
3131
|
|
|
3150
|
-
// src/commands/setup/
|
|
3151
|
-
var
|
|
3152
|
-
__export(
|
|
3153
|
-
default: () =>
|
|
3154
|
-
configureSafe: () => configureSafe6
|
|
3132
|
+
// src/commands/setup/claude-code.ts
|
|
3133
|
+
var exports_claude_code = {};
|
|
3134
|
+
__export(exports_claude_code, {
|
|
3135
|
+
default: () => claude_code_default
|
|
3155
3136
|
});
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
return runMcpFileSetup(key, json, getConfig5(), false).success;
|
|
3159
|
-
}
|
|
3160
|
-
var getConfig5 = () => ({
|
|
3161
|
-
agentId: "vscode",
|
|
3162
|
-
configPath: join5(process.cwd(), ".vscode", "mcp.json"),
|
|
3163
|
-
serversKey: "servers",
|
|
3164
|
-
label: ".vscode/mcp.json",
|
|
3165
|
-
successMessage: "Outlit MCP config written to .vscode/mcp.json. Restart VS Code to apply."
|
|
3166
|
-
}), vscode_default;
|
|
3167
|
-
var init_vscode = __esm(() => {
|
|
3137
|
+
var claude_code_default;
|
|
3138
|
+
var init_claude_code = __esm(() => {
|
|
3168
3139
|
init_dist();
|
|
3169
|
-
init_auth();
|
|
3170
3140
|
init_output2();
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
vscode_default = defineCommand2({
|
|
3141
|
+
init_skills();
|
|
3142
|
+
claude_code_default = defineCommand2({
|
|
3174
3143
|
meta: {
|
|
3175
|
-
name: "
|
|
3176
|
-
description: "
|
|
3144
|
+
name: "claude-code",
|
|
3145
|
+
description: "Install the Outlit skill for Claude Code."
|
|
3177
3146
|
},
|
|
3178
|
-
args: { ...
|
|
3147
|
+
args: { ...outputArgs },
|
|
3179
3148
|
run({ args }) {
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3149
|
+
runAgentSkillsInstall("claude-code", !!args.json);
|
|
3150
|
+
}
|
|
3151
|
+
});
|
|
3152
|
+
});
|
|
3153
|
+
|
|
3154
|
+
// src/commands/setup/codex.ts
|
|
3155
|
+
var exports_codex = {};
|
|
3156
|
+
__export(exports_codex, {
|
|
3157
|
+
default: () => codex_default
|
|
3158
|
+
});
|
|
3159
|
+
var codex_default;
|
|
3160
|
+
var init_codex = __esm(() => {
|
|
3161
|
+
init_dist();
|
|
3162
|
+
init_output2();
|
|
3163
|
+
init_skills();
|
|
3164
|
+
codex_default = defineCommand2({
|
|
3165
|
+
meta: {
|
|
3166
|
+
name: "codex",
|
|
3167
|
+
description: "Install the Outlit skill for Codex."
|
|
3168
|
+
},
|
|
3169
|
+
args: { ...outputArgs },
|
|
3170
|
+
run({ args }) {
|
|
3171
|
+
runAgentSkillsInstall("codex", !!args.json);
|
|
3172
|
+
}
|
|
3173
|
+
});
|
|
3174
|
+
});
|
|
3175
|
+
|
|
3176
|
+
// src/commands/setup/gemini.ts
|
|
3177
|
+
var exports_gemini = {};
|
|
3178
|
+
__export(exports_gemini, {
|
|
3179
|
+
default: () => gemini_default
|
|
3180
|
+
});
|
|
3181
|
+
var gemini_default;
|
|
3182
|
+
var init_gemini = __esm(() => {
|
|
3183
|
+
init_dist();
|
|
3184
|
+
init_output2();
|
|
3185
|
+
init_skills();
|
|
3186
|
+
gemini_default = defineCommand2({
|
|
3187
|
+
meta: {
|
|
3188
|
+
name: "gemini",
|
|
3189
|
+
description: "Install the Outlit skill for Gemini CLI."
|
|
3190
|
+
},
|
|
3191
|
+
args: { ...outputArgs },
|
|
3192
|
+
run({ args }) {
|
|
3193
|
+
runAgentSkillsInstall("gemini", !!args.json);
|
|
3194
|
+
}
|
|
3195
|
+
});
|
|
3196
|
+
});
|
|
3197
|
+
|
|
3198
|
+
// src/commands/setup/droid.ts
|
|
3199
|
+
var exports_droid = {};
|
|
3200
|
+
__export(exports_droid, {
|
|
3201
|
+
default: () => droid_default
|
|
3202
|
+
});
|
|
3203
|
+
var droid_default;
|
|
3204
|
+
var init_droid = __esm(() => {
|
|
3205
|
+
init_dist();
|
|
3206
|
+
init_output2();
|
|
3207
|
+
init_skills();
|
|
3208
|
+
droid_default = defineCommand2({
|
|
3209
|
+
meta: {
|
|
3210
|
+
name: "droid",
|
|
3211
|
+
description: "Install the Outlit skill for Droid."
|
|
3212
|
+
},
|
|
3213
|
+
args: { ...outputArgs },
|
|
3214
|
+
run({ args }) {
|
|
3215
|
+
runAgentSkillsInstall("droid", !!args.json);
|
|
3216
|
+
}
|
|
3217
|
+
});
|
|
3218
|
+
});
|
|
3219
|
+
|
|
3220
|
+
// src/commands/setup/opencode.ts
|
|
3221
|
+
var exports_opencode = {};
|
|
3222
|
+
__export(exports_opencode, {
|
|
3223
|
+
default: () => opencode_default
|
|
3224
|
+
});
|
|
3225
|
+
var opencode_default;
|
|
3226
|
+
var init_opencode = __esm(() => {
|
|
3227
|
+
init_dist();
|
|
3228
|
+
init_output2();
|
|
3229
|
+
init_skills();
|
|
3230
|
+
opencode_default = defineCommand2({
|
|
3231
|
+
meta: {
|
|
3232
|
+
name: "opencode",
|
|
3233
|
+
description: "Install the Outlit skill for OpenCode."
|
|
3234
|
+
},
|
|
3235
|
+
args: { ...outputArgs },
|
|
3236
|
+
run({ args }) {
|
|
3237
|
+
runAgentSkillsInstall("opencode", !!args.json);
|
|
3238
|
+
}
|
|
3239
|
+
});
|
|
3240
|
+
});
|
|
3241
|
+
|
|
3242
|
+
// src/commands/setup/pi.ts
|
|
3243
|
+
var exports_pi = {};
|
|
3244
|
+
__export(exports_pi, {
|
|
3245
|
+
default: () => pi_default
|
|
3246
|
+
});
|
|
3247
|
+
var pi_default;
|
|
3248
|
+
var init_pi = __esm(() => {
|
|
3249
|
+
init_dist();
|
|
3250
|
+
init_output2();
|
|
3251
|
+
init_skills();
|
|
3252
|
+
pi_default = defineCommand2({
|
|
3253
|
+
meta: {
|
|
3254
|
+
name: "pi",
|
|
3255
|
+
description: "Install the Outlit skill for Pi."
|
|
3256
|
+
},
|
|
3257
|
+
args: { ...outputArgs },
|
|
3258
|
+
run({ args }) {
|
|
3259
|
+
runAgentSkillsInstall("pi", !!args.json);
|
|
3260
|
+
}
|
|
3261
|
+
});
|
|
3262
|
+
});
|
|
3263
|
+
|
|
3264
|
+
// src/commands/setup/openclaw.ts
|
|
3265
|
+
var exports_openclaw = {};
|
|
3266
|
+
__export(exports_openclaw, {
|
|
3267
|
+
default: () => openclaw_default
|
|
3268
|
+
});
|
|
3269
|
+
var openclaw_default;
|
|
3270
|
+
var init_openclaw = __esm(() => {
|
|
3271
|
+
init_dist();
|
|
3272
|
+
init_output2();
|
|
3273
|
+
init_skills();
|
|
3274
|
+
openclaw_default = defineCommand2({
|
|
3275
|
+
meta: {
|
|
3276
|
+
name: "openclaw",
|
|
3277
|
+
description: "Install the Outlit skill for OpenClaw."
|
|
3278
|
+
},
|
|
3279
|
+
args: { ...outputArgs },
|
|
3280
|
+
run({ args }) {
|
|
3281
|
+
runAgentSkillsInstall("openclaw", !!args.json);
|
|
3183
3282
|
}
|
|
3184
3283
|
});
|
|
3185
3284
|
});
|
|
3186
3285
|
|
|
3187
3286
|
// src/commands/setup/index.ts
|
|
3188
|
-
import { execFileSync as
|
|
3189
|
-
import { existsSync as
|
|
3287
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
3288
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
3190
3289
|
import { homedir as homedir4 } from "node:os";
|
|
3191
|
-
import { join as
|
|
3290
|
+
import { join as join5 } from "node:path";
|
|
3192
3291
|
function isCommandAvailable(cmd) {
|
|
3193
3292
|
try {
|
|
3194
3293
|
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
3195
|
-
|
|
3294
|
+
execFileSync5(whichCmd, [cmd], { stdio: "ignore" });
|
|
3196
3295
|
return true;
|
|
3197
3296
|
} catch {
|
|
3198
3297
|
return false;
|
|
3199
3298
|
}
|
|
3200
3299
|
}
|
|
3300
|
+
function getHomeDir() {
|
|
3301
|
+
return process.env.HOME?.trim() || homedir4();
|
|
3302
|
+
}
|
|
3201
3303
|
function detectAgents() {
|
|
3202
|
-
const home =
|
|
3304
|
+
const home = getHomeDir();
|
|
3305
|
+
const configHome = process.env.XDG_CONFIG_HOME?.trim() || join5(home, ".config");
|
|
3203
3306
|
const detected = [];
|
|
3204
|
-
if (existsSync2(join6(home, ".cursor")))
|
|
3205
|
-
detected.push("cursor");
|
|
3206
3307
|
if (isCommandAvailable("claude"))
|
|
3207
3308
|
detected.push("claude-code");
|
|
3208
|
-
if (
|
|
3209
|
-
detected.push("
|
|
3210
|
-
if (isCommandAvailable("code") || existsSync2(join6(process.cwd(), ".vscode")))
|
|
3211
|
-
detected.push("vscode");
|
|
3309
|
+
if (isCommandAvailable("codex"))
|
|
3310
|
+
detected.push("codex");
|
|
3212
3311
|
if (isCommandAvailable("gemini"))
|
|
3213
3312
|
detected.push("gemini");
|
|
3214
|
-
if (
|
|
3313
|
+
if (existsSync4(join5(home, ".factory")))
|
|
3314
|
+
detected.push("droid");
|
|
3315
|
+
if (existsSync4(join5(configHome, "opencode")))
|
|
3316
|
+
detected.push("opencode");
|
|
3317
|
+
if (existsSync4(join5(home, ".pi", "agent")))
|
|
3318
|
+
detected.push("pi");
|
|
3319
|
+
if (existsSync4(join5(home, ".openclaw")) || existsSync4(join5(home, ".clawdbot")) || existsSync4(join5(home, ".moltbot"))) {
|
|
3215
3320
|
detected.push("openclaw");
|
|
3321
|
+
}
|
|
3216
3322
|
return detected;
|
|
3217
3323
|
}
|
|
3218
|
-
var agentLabels,
|
|
3219
|
-
var
|
|
3324
|
+
var agentLabels, setupSubcommandNames, setup_default;
|
|
3325
|
+
var init_setup = __esm(() => {
|
|
3220
3326
|
init_dist();
|
|
3221
|
-
init_auth();
|
|
3222
3327
|
init_output2();
|
|
3223
3328
|
init_config();
|
|
3224
3329
|
init_output();
|
|
3225
|
-
init_claude_code();
|
|
3226
|
-
init_claude_desktop();
|
|
3227
|
-
init_cursor();
|
|
3228
|
-
init_gemini();
|
|
3229
|
-
init_openclaw();
|
|
3230
3330
|
init_skills();
|
|
3231
|
-
init_vscode();
|
|
3232
3331
|
agentLabels = {
|
|
3233
|
-
cursor: { label: "Cursor", hint: "~/.cursor/" },
|
|
3234
3332
|
"claude-code": { label: "Claude Code", hint: "claude CLI found" },
|
|
3235
|
-
|
|
3236
|
-
vscode: { label: "VS Code", hint: "code CLI or .vscode/ found" },
|
|
3333
|
+
codex: { label: "Codex", hint: "codex CLI found" },
|
|
3237
3334
|
gemini: { label: "Gemini CLI", hint: "gemini CLI found" },
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
"claude-code": configureSafe,
|
|
3243
|
-
"claude-desktop": configureSafe2,
|
|
3244
|
-
vscode: configureSafe6,
|
|
3245
|
-
gemini: configureSafe4,
|
|
3246
|
-
openclaw: configureSafe5
|
|
3335
|
+
droid: { label: "Droid", hint: ".factory config found" },
|
|
3336
|
+
opencode: { label: "OpenCode", hint: "opencode config found" },
|
|
3337
|
+
pi: { label: "Pi", hint: ".pi/agent config found" },
|
|
3338
|
+
openclaw: { label: "OpenClaw", hint: "OpenClaw config found" }
|
|
3247
3339
|
};
|
|
3340
|
+
setupSubcommandNames = new Set([
|
|
3341
|
+
"claude-code",
|
|
3342
|
+
"codex",
|
|
3343
|
+
"gemini",
|
|
3344
|
+
"droid",
|
|
3345
|
+
"opencode",
|
|
3346
|
+
"pi",
|
|
3347
|
+
"openclaw",
|
|
3348
|
+
"skills"
|
|
3349
|
+
]);
|
|
3248
3350
|
setup_default = defineCommand2({
|
|
3249
3351
|
meta: {
|
|
3250
3352
|
name: "setup",
|
|
3251
3353
|
description: [
|
|
3252
|
-
"
|
|
3354
|
+
"Install the Outlit skill for coding agents.",
|
|
3253
3355
|
"",
|
|
3254
|
-
"Without a subcommand, auto-detects
|
|
3255
|
-
"Subcommands:
|
|
3356
|
+
"Without a subcommand, auto-detects supported coding agents and installs `outlit` for all of them.",
|
|
3357
|
+
"Subcommands: claude-code, codex, gemini, droid, opencode, pi, openclaw, skills"
|
|
3256
3358
|
].join(`
|
|
3257
3359
|
`)
|
|
3258
3360
|
},
|
|
3259
3361
|
args: {
|
|
3260
|
-
...authArgs,
|
|
3261
3362
|
...outputArgs,
|
|
3262
3363
|
yes: {
|
|
3263
3364
|
type: "boolean",
|
|
3264
|
-
description: "
|
|
3365
|
+
description: "Install for all detected coding agents without prompting."
|
|
3265
3366
|
}
|
|
3266
3367
|
},
|
|
3267
3368
|
subCommands: {
|
|
3268
|
-
cursor: () => Promise.resolve().then(() => (init_cursor(), exports_cursor)).then((m) => m.default),
|
|
3269
3369
|
"claude-code": () => Promise.resolve().then(() => (init_claude_code(), exports_claude_code)).then((m) => m.default),
|
|
3270
|
-
|
|
3271
|
-
vscode: () => Promise.resolve().then(() => (init_vscode(), exports_vscode)).then((m) => m.default),
|
|
3370
|
+
codex: () => Promise.resolve().then(() => (init_codex(), exports_codex)).then((m) => m.default),
|
|
3272
3371
|
gemini: () => Promise.resolve().then(() => (init_gemini(), exports_gemini)).then((m) => m.default),
|
|
3372
|
+
droid: () => Promise.resolve().then(() => (init_droid(), exports_droid)).then((m) => m.default),
|
|
3373
|
+
opencode: () => Promise.resolve().then(() => (init_opencode(), exports_opencode)).then((m) => m.default),
|
|
3374
|
+
pi: () => Promise.resolve().then(() => (init_pi(), exports_pi)).then((m) => m.default),
|
|
3273
3375
|
openclaw: () => Promise.resolve().then(() => (init_openclaw(), exports_openclaw)).then((m) => m.default),
|
|
3274
3376
|
skills: () => Promise.resolve().then(() => (init_skills(), exports_skills)).then((m) => m.default)
|
|
3275
3377
|
},
|
|
3276
|
-
async run({ args }) {
|
|
3378
|
+
async run({ args, rawArgs }) {
|
|
3379
|
+
const setupRawArgs = rawArgs ?? [];
|
|
3380
|
+
const subcommandName = setupRawArgs.find((arg) => !arg.startsWith("-"));
|
|
3381
|
+
if (subcommandName && setupSubcommandNames.has(subcommandName)) {
|
|
3382
|
+
return;
|
|
3383
|
+
}
|
|
3277
3384
|
const json = !!args.json;
|
|
3278
|
-
const credential = requireCredential(args["api-key"], json);
|
|
3279
3385
|
const detected = detectAgents();
|
|
3280
3386
|
if (detected.length === 0) {
|
|
3281
3387
|
if (isJsonMode(json)) {
|
|
3282
|
-
return outputResult({ detected: [], configured: [], failed: [],
|
|
3388
|
+
return outputResult({ detected: [], configured: [], failed: [], runner: null });
|
|
3283
3389
|
}
|
|
3284
|
-
console.log("No supported
|
|
3390
|
+
console.log("No supported coding agents detected.");
|
|
3285
3391
|
return;
|
|
3286
3392
|
}
|
|
3287
3393
|
if (!isJsonMode(json) && !args.yes) {
|
|
3288
|
-
console.log("Detected agents:");
|
|
3394
|
+
console.log("Detected coding agents:");
|
|
3289
3395
|
for (const agentId of detected) {
|
|
3290
3396
|
const { label, hint } = agentLabels[agentId];
|
|
3291
3397
|
console.log(` ${TICK2} ${label.padEnd(14)} -- ${hint}`);
|
|
3292
3398
|
}
|
|
3293
3399
|
console.log(`
|
|
3294
|
-
|
|
3295
|
-
}
|
|
3296
|
-
const configured = [];
|
|
3297
|
-
const failed = [];
|
|
3298
|
-
for (const agentId of detected) {
|
|
3299
|
-
const ok = configurators[agentId](credential.key, json);
|
|
3300
|
-
if (ok) {
|
|
3301
|
-
configured.push(agentId);
|
|
3302
|
-
} else {
|
|
3303
|
-
failed.push(agentId);
|
|
3304
|
-
}
|
|
3305
|
-
}
|
|
3306
|
-
const skills = runSkillsInstall(json, false);
|
|
3307
|
-
if (!isJsonMode(json) && !skills.success) {
|
|
3308
|
-
console.log(`
|
|
3309
|
-
! Agent skills installation failed: ${skills.error ?? "unknown error"}`);
|
|
3310
|
-
console.log(" Run `outlit setup skills` to retry.");
|
|
3400
|
+
Installing Outlit skill...`);
|
|
3311
3401
|
}
|
|
3402
|
+
const install = runSkillsInstall({
|
|
3403
|
+
json,
|
|
3404
|
+
exitOnError: false,
|
|
3405
|
+
agents: detected.map(getSkillAgentId),
|
|
3406
|
+
skillNames: ["outlit"],
|
|
3407
|
+
autoConfirm: true
|
|
3408
|
+
});
|
|
3409
|
+
const configured = install.success ? detected : [];
|
|
3410
|
+
const failed = install.success ? [] : detected;
|
|
3312
3411
|
if (isJsonMode(json)) {
|
|
3313
|
-
return outputResult({
|
|
3412
|
+
return outputResult({
|
|
3413
|
+
detected,
|
|
3414
|
+
configured,
|
|
3415
|
+
failed,
|
|
3416
|
+
runner: install.runner ?? null
|
|
3417
|
+
});
|
|
3314
3418
|
}
|
|
3315
|
-
if (
|
|
3419
|
+
if (!install.success) {
|
|
3316
3420
|
console.log(`
|
|
3317
|
-
|
|
3421
|
+
! Outlit skill install failed: ${install.error ?? "unknown error"}`);
|
|
3422
|
+
console.log(" Run `outlit setup skills` to retry manually.");
|
|
3423
|
+
return;
|
|
3318
3424
|
}
|
|
3319
3425
|
console.log(`
|
|
3320
|
-
Done. ${configured.length}
|
|
3426
|
+
Done. Installed Outlit for ${configured.length} coding agent(s).`);
|
|
3321
3427
|
}
|
|
3322
3428
|
});
|
|
3323
3429
|
});
|
|
@@ -3325,21 +3431,16 @@ Done. ${configured.length}/${detected.length} agent(s) configured successfully.`
|
|
|
3325
3431
|
// src/commands/doctor.ts
|
|
3326
3432
|
var exports_doctor = {};
|
|
3327
3433
|
__export(exports_doctor, {
|
|
3328
|
-
default: () => doctor_default
|
|
3434
|
+
default: () => doctor_default,
|
|
3435
|
+
buildAgentChecks: () => buildAgentChecks
|
|
3329
3436
|
});
|
|
3330
|
-
import { existsSync as
|
|
3437
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
3331
3438
|
import { homedir as homedir5 } from "node:os";
|
|
3332
|
-
import { join as
|
|
3439
|
+
import { join as join6 } from "node:path";
|
|
3333
3440
|
async function checkCliVersion() {
|
|
3334
3441
|
const current = CLI_VERSION2;
|
|
3335
3442
|
try {
|
|
3336
|
-
const
|
|
3337
|
-
signal: AbortSignal.timeout(5000)
|
|
3338
|
-
});
|
|
3339
|
-
if (!res.ok)
|
|
3340
|
-
throw new Error("registry unavailable");
|
|
3341
|
-
const data = await res.json();
|
|
3342
|
-
const latest = data.version ?? "unknown";
|
|
3443
|
+
const latest = await fetchLatestCliVersion2();
|
|
3343
3444
|
if (latest === current) {
|
|
3344
3445
|
return { name: "CLI version", status: "pass", message: `v${current} (latest)` };
|
|
3345
3446
|
}
|
|
@@ -3347,7 +3448,7 @@ async function checkCliVersion() {
|
|
|
3347
3448
|
name: "CLI version",
|
|
3348
3449
|
status: "warn",
|
|
3349
3450
|
message: `v${current} installed, v${latest} available`,
|
|
3350
|
-
detail:
|
|
3451
|
+
detail: `Run \`${formatUpdateCommand2()}\` to update`
|
|
3351
3452
|
};
|
|
3352
3453
|
} catch {
|
|
3353
3454
|
return {
|
|
@@ -3434,8 +3535,42 @@ async function checkIntegrations(apiKey) {
|
|
|
3434
3535
|
};
|
|
3435
3536
|
}
|
|
3436
3537
|
}
|
|
3437
|
-
function
|
|
3438
|
-
|
|
3538
|
+
function getHomeDir2(options) {
|
|
3539
|
+
return options?.homeDir?.trim() || process.env.HOME?.trim() || homedir5();
|
|
3540
|
+
}
|
|
3541
|
+
function getSharedSkillsDir(options) {
|
|
3542
|
+
return join6(getHomeDir2(options), ".agents", "skills");
|
|
3543
|
+
}
|
|
3544
|
+
function getOpenClawHome(options) {
|
|
3545
|
+
const home = getHomeDir2(options);
|
|
3546
|
+
if (existsSync5(join6(home, ".openclaw")))
|
|
3547
|
+
return join6(home, ".openclaw");
|
|
3548
|
+
if (existsSync5(join6(home, ".clawdbot")))
|
|
3549
|
+
return join6(home, ".clawdbot");
|
|
3550
|
+
if (existsSync5(join6(home, ".moltbot")))
|
|
3551
|
+
return join6(home, ".moltbot");
|
|
3552
|
+
return join6(home, ".openclaw");
|
|
3553
|
+
}
|
|
3554
|
+
function getAgentSkillDir(agentId, options) {
|
|
3555
|
+
const home = getHomeDir2(options);
|
|
3556
|
+
switch (agentId) {
|
|
3557
|
+
case "claude-code":
|
|
3558
|
+
return join6(options?.claudeConfigDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || join6(home, ".claude"), "skills");
|
|
3559
|
+
case "codex":
|
|
3560
|
+
return getSharedSkillsDir(options);
|
|
3561
|
+
case "gemini":
|
|
3562
|
+
return getSharedSkillsDir(options);
|
|
3563
|
+
case "droid":
|
|
3564
|
+
return join6(home, ".factory", "skills");
|
|
3565
|
+
case "opencode":
|
|
3566
|
+
return getSharedSkillsDir(options);
|
|
3567
|
+
case "pi":
|
|
3568
|
+
return join6(home, ".pi", "agent", "skills");
|
|
3569
|
+
case "openclaw":
|
|
3570
|
+
return join6(getOpenClawHome(options), "skills");
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
function buildAgentChecks(detected = detectAgents(), options) {
|
|
3439
3574
|
if (detected.length === 0) {
|
|
3440
3575
|
return [
|
|
3441
3576
|
{
|
|
@@ -3446,66 +3581,15 @@ function detectAgents2() {
|
|
|
3446
3581
|
];
|
|
3447
3582
|
}
|
|
3448
3583
|
const results = [];
|
|
3449
|
-
const home = homedir5();
|
|
3450
3584
|
for (const agentId of detected) {
|
|
3451
3585
|
const meta = agentChecks[agentId];
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
detail: hasSkill ? undefined : "Run `clawhub install outlit` to configure"
|
|
3460
|
-
});
|
|
3461
|
-
continue;
|
|
3462
|
-
}
|
|
3463
|
-
if (!meta.configCheck) {
|
|
3464
|
-
results.push({
|
|
3465
|
-
name: meta.name,
|
|
3466
|
-
status: "warn",
|
|
3467
|
-
message: "Installed, but Outlit MCP not verified",
|
|
3468
|
-
detail: `Run \`outlit setup ${agentId}\` to configure`
|
|
3469
|
-
});
|
|
3470
|
-
if (agentId === "claude-code") {
|
|
3471
|
-
const skillsDir = join7(home, ".claude", "skills");
|
|
3472
|
-
const hasSkills = existsSync3(join7(skillsDir, "outlit-cli")) || existsSync3(join7(skillsDir, "outlit-sdk")) || existsSync3(join7(skillsDir, "outlit-mcp"));
|
|
3473
|
-
results.push({
|
|
3474
|
-
name: "Agent Skills",
|
|
3475
|
-
status: hasSkills ? "pass" : "warn",
|
|
3476
|
-
message: hasSkills ? "Outlit agent skills installed" : "Outlit agent skills not found",
|
|
3477
|
-
detail: hasSkills ? undefined : "Run `outlit setup skills` to install deeper AI agent context"
|
|
3478
|
-
});
|
|
3479
|
-
}
|
|
3480
|
-
continue;
|
|
3481
|
-
}
|
|
3482
|
-
const { path, key } = meta.configCheck;
|
|
3483
|
-
if (!existsSync3(path)) {
|
|
3484
|
-
results.push({
|
|
3485
|
-
name: meta.name,
|
|
3486
|
-
status: "warn",
|
|
3487
|
-
message: "Installed, but config file not found",
|
|
3488
|
-
detail: `Run \`outlit setup ${agentId}\` to configure`
|
|
3489
|
-
});
|
|
3490
|
-
continue;
|
|
3491
|
-
}
|
|
3492
|
-
try {
|
|
3493
|
-
const config = readJsonConfig(path);
|
|
3494
|
-
const configured = !!config[key]?.outlit;
|
|
3495
|
-
results.push({
|
|
3496
|
-
name: meta.name,
|
|
3497
|
-
status: configured ? "pass" : "warn",
|
|
3498
|
-
message: configured ? "Installed, Outlit MCP configured" : "Installed, but Outlit MCP not configured",
|
|
3499
|
-
detail: configured ? undefined : `Run \`outlit setup ${agentId}\` to configure`
|
|
3500
|
-
});
|
|
3501
|
-
} catch {
|
|
3502
|
-
results.push({
|
|
3503
|
-
name: meta.name,
|
|
3504
|
-
status: "warn",
|
|
3505
|
-
message: "Installed, but config file is malformed",
|
|
3506
|
-
detail: `Check ${path} for JSON syntax errors`
|
|
3507
|
-
});
|
|
3508
|
-
}
|
|
3586
|
+
const hasSkill = existsSync5(join6(getAgentSkillDir(agentId, options), "outlit", "SKILL.md"));
|
|
3587
|
+
results.push({
|
|
3588
|
+
name: meta.name,
|
|
3589
|
+
status: hasSkill ? "pass" : "warn",
|
|
3590
|
+
message: hasSkill ? "Outlit skill installed" : "Installed, but Outlit skill not found",
|
|
3591
|
+
detail: hasSkill ? undefined : meta.missingDetail
|
|
3592
|
+
});
|
|
3509
3593
|
}
|
|
3510
3594
|
return results;
|
|
3511
3595
|
}
|
|
@@ -3540,7 +3624,8 @@ var init_doctor = __esm(() => {
|
|
|
3540
3624
|
init_config();
|
|
3541
3625
|
init_output();
|
|
3542
3626
|
init_tty();
|
|
3543
|
-
|
|
3627
|
+
init_update();
|
|
3628
|
+
init_setup();
|
|
3544
3629
|
FAIL_SYMBOL2 = isUnicodeSupported ? String.fromCodePoint(10007) : "x";
|
|
3545
3630
|
STATUS_ICONS = {
|
|
3546
3631
|
pass: TICK2,
|
|
@@ -3557,73 +3642,335 @@ var init_doctor = __esm(() => {
|
|
|
3557
3642
|
" 1. CLI version -- compares against npm registry",
|
|
3558
3643
|
" 2. API key -- checks presence and format (ok_ prefix)",
|
|
3559
3644
|
" 3. API validation -- makes a live test call to verify the key works",
|
|
3560
|
-
" 4. Agent detection -- detects
|
|
3645
|
+
" 4. Agent detection -- detects supported coding agents and whether the Outlit skill is installed",
|
|
3561
3646
|
"",
|
|
3562
3647
|
"Exit code: 0 if all checks pass or warn, 1 if any check fails.",
|
|
3563
3648
|
"",
|
|
3564
|
-
"JSON output format:",
|
|
3565
|
-
' { "ok": boolean, "checks": [{ "name", "status", "message", "detail?" }] }',
|
|
3649
|
+
"JSON output format:",
|
|
3650
|
+
' { "ok": boolean, "checks": [{ "name", "status", "message", "detail?" }] }',
|
|
3651
|
+
"",
|
|
3652
|
+
"Examples:",
|
|
3653
|
+
" outlit doctor",
|
|
3654
|
+
" outlit doctor --json",
|
|
3655
|
+
` outlit doctor --json | jq '.checks[] | select(.status == "fail")'`,
|
|
3656
|
+
"",
|
|
3657
|
+
"For AI agents: use outlit doctor --json to get structured diagnostics."
|
|
3658
|
+
].join(`
|
|
3659
|
+
`)
|
|
3660
|
+
},
|
|
3661
|
+
args: { ...authArgs, ...outputArgs },
|
|
3662
|
+
async run({ args }) {
|
|
3663
|
+
const json = !!args.json;
|
|
3664
|
+
const checks = [];
|
|
3665
|
+
checks.push(await checkCliVersion());
|
|
3666
|
+
const credential = resolveApiKey(args["api-key"]);
|
|
3667
|
+
checks.push(checkApiKeyPresence(credential));
|
|
3668
|
+
if (credential) {
|
|
3669
|
+
const apiCheck = await validateApiKey(credential.key);
|
|
3670
|
+
checks.push(apiCheck);
|
|
3671
|
+
if (apiCheck.status !== "fail") {
|
|
3672
|
+
checks.push(await checkIntegrations(credential.key));
|
|
3673
|
+
}
|
|
3674
|
+
} else {
|
|
3675
|
+
checks.push({
|
|
3676
|
+
name: "API validation",
|
|
3677
|
+
status: "fail",
|
|
3678
|
+
message: "Skipped -- no API key found"
|
|
3679
|
+
});
|
|
3680
|
+
}
|
|
3681
|
+
checks.push(...buildAgentChecks());
|
|
3682
|
+
const hasFail = checks.some((c) => c.status === "fail");
|
|
3683
|
+
if (isJsonMode(json)) {
|
|
3684
|
+
outputResult({ ok: !hasFail, checks });
|
|
3685
|
+
} else {
|
|
3686
|
+
printChecks(checks);
|
|
3687
|
+
}
|
|
3688
|
+
if (hasFail)
|
|
3689
|
+
process.exit(1);
|
|
3690
|
+
}
|
|
3691
|
+
});
|
|
3692
|
+
agentChecks = {
|
|
3693
|
+
"claude-code": {
|
|
3694
|
+
name: "Claude Code",
|
|
3695
|
+
missingDetail: "Run `outlit setup claude-code` to install the Outlit skill"
|
|
3696
|
+
},
|
|
3697
|
+
codex: {
|
|
3698
|
+
name: "Codex",
|
|
3699
|
+
missingDetail: "Run `outlit setup codex` to install the Outlit skill"
|
|
3700
|
+
},
|
|
3701
|
+
gemini: {
|
|
3702
|
+
name: "Gemini CLI",
|
|
3703
|
+
missingDetail: "Run `outlit setup gemini` to install the Outlit skill"
|
|
3704
|
+
},
|
|
3705
|
+
droid: {
|
|
3706
|
+
name: "Droid",
|
|
3707
|
+
missingDetail: "Run `outlit setup droid` to install the Outlit skill"
|
|
3708
|
+
},
|
|
3709
|
+
opencode: {
|
|
3710
|
+
name: "OpenCode",
|
|
3711
|
+
missingDetail: "Run `outlit setup opencode` to install the Outlit skill"
|
|
3712
|
+
},
|
|
3713
|
+
pi: {
|
|
3714
|
+
name: "Pi",
|
|
3715
|
+
missingDetail: "Run `outlit setup pi` to install the Outlit skill"
|
|
3716
|
+
},
|
|
3717
|
+
openclaw: {
|
|
3718
|
+
name: "OpenClaw",
|
|
3719
|
+
missingDetail: "Run `outlit setup openclaw` to install the Outlit skill"
|
|
3720
|
+
}
|
|
3721
|
+
};
|
|
3722
|
+
});
|
|
3723
|
+
|
|
3724
|
+
// src/commands/upgrade.ts
|
|
3725
|
+
var exports_upgrade = {};
|
|
3726
|
+
__export(exports_upgrade, {
|
|
3727
|
+
default: () => upgrade_default
|
|
3728
|
+
});
|
|
3729
|
+
var upgrade_default;
|
|
3730
|
+
var init_upgrade = __esm(() => {
|
|
3731
|
+
init_dist();
|
|
3732
|
+
init_config();
|
|
3733
|
+
init_output();
|
|
3734
|
+
init_update();
|
|
3735
|
+
upgrade_default = defineCommand2({
|
|
3736
|
+
meta: {
|
|
3737
|
+
name: "upgrade",
|
|
3738
|
+
description: [
|
|
3739
|
+
"Upgrade the Outlit CLI using the same package manager it was installed with.",
|
|
3740
|
+
"",
|
|
3741
|
+
"Checks npm for the latest published version first.",
|
|
3742
|
+
"If the current version is already latest, no install command is run.",
|
|
3743
|
+
"",
|
|
3744
|
+
"Examples:",
|
|
3745
|
+
" outlit upgrade"
|
|
3746
|
+
].join(`
|
|
3747
|
+
`)
|
|
3748
|
+
},
|
|
3749
|
+
async run() {
|
|
3750
|
+
const upgradeCommand = getUpgradeCommand();
|
|
3751
|
+
if (!upgradeCommand) {
|
|
3752
|
+
return outputError({
|
|
3753
|
+
message: "Could not determine how Outlit CLI was installed. Update it manually with your package manager, for example `bun add -g @outlit/cli` or `npm install -g @outlit/cli`.",
|
|
3754
|
+
code: "unknown_installer"
|
|
3755
|
+
}, false);
|
|
3756
|
+
}
|
|
3757
|
+
let latestVersion;
|
|
3758
|
+
try {
|
|
3759
|
+
latestVersion = await fetchLatestCliVersion2();
|
|
3760
|
+
} catch {
|
|
3761
|
+
return outputError({
|
|
3762
|
+
message: "Could not check for CLI updates. Try again later or update manually.",
|
|
3763
|
+
code: "update_check_failed"
|
|
3764
|
+
}, false);
|
|
3765
|
+
}
|
|
3766
|
+
if (compareVersions2(CLI_VERSION2, latestVersion) >= 0) {
|
|
3767
|
+
console.log(`Outlit CLI is already up to date (v${CLI_VERSION2})`);
|
|
3768
|
+
return;
|
|
3769
|
+
}
|
|
3770
|
+
try {
|
|
3771
|
+
runUpgradeCommand(upgradeCommand);
|
|
3772
|
+
} catch (err) {
|
|
3773
|
+
return outputError({
|
|
3774
|
+
message: errorMessage(err, `Failed to run ${upgradeCommand.displayCommand}`),
|
|
3775
|
+
code: "upgrade_failed"
|
|
3776
|
+
}, false);
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
});
|
|
3780
|
+
});
|
|
3781
|
+
|
|
3782
|
+
// src/commands/facts/list.ts
|
|
3783
|
+
var exports_list3 = {};
|
|
3784
|
+
__export(exports_list3, {
|
|
3785
|
+
default: () => list_default3
|
|
3786
|
+
});
|
|
3787
|
+
function parseCsvArg(value) {
|
|
3788
|
+
if (!value)
|
|
3789
|
+
return;
|
|
3790
|
+
const items = splitCsv(value).map((item) => item.trim()).filter(Boolean);
|
|
3791
|
+
return items.length > 0 ? items : undefined;
|
|
3792
|
+
}
|
|
3793
|
+
function invalidValues(values, allowed) {
|
|
3794
|
+
if (!values)
|
|
3795
|
+
return [];
|
|
3796
|
+
return values.filter((value) => !allowed.includes(value));
|
|
3797
|
+
}
|
|
3798
|
+
var list_default3;
|
|
3799
|
+
var init_list3 = __esm(() => {
|
|
3800
|
+
init_dist();
|
|
3801
|
+
init_auth();
|
|
3802
|
+
init_output2();
|
|
3803
|
+
init_pagination();
|
|
3804
|
+
init_tool_contracts();
|
|
3805
|
+
init_api();
|
|
3806
|
+
init_config();
|
|
3807
|
+
init_output();
|
|
3808
|
+
list_default3 = defineCommand2({
|
|
3809
|
+
meta: {
|
|
3810
|
+
name: "list",
|
|
3811
|
+
description: [
|
|
3812
|
+
"List structured facts for a customer.",
|
|
3813
|
+
"",
|
|
3814
|
+
"Filter by fact status, source type, or occurrence date range.",
|
|
3815
|
+
"",
|
|
3816
|
+
"Examples:",
|
|
3817
|
+
" outlit facts list acme.com",
|
|
3818
|
+
" outlit facts list acme.com --status ACTIVE",
|
|
3819
|
+
" outlit facts list acme.com --source-types CALL,EMAIL --after 2025-01-01T00:00:00Z",
|
|
3820
|
+
" outlit facts list acme.com --limit 50 --json",
|
|
3821
|
+
"",
|
|
3822
|
+
`Statuses: ${customerFactStatuses.join(", ")}`,
|
|
3823
|
+
`Source types: ${customerSourceTypes.join(", ")}`,
|
|
3824
|
+
"",
|
|
3825
|
+
AGENT_JSON_HINT
|
|
3826
|
+
].join(`
|
|
3827
|
+
`)
|
|
3828
|
+
},
|
|
3829
|
+
args: {
|
|
3830
|
+
...authArgs,
|
|
3831
|
+
...outputArgs,
|
|
3832
|
+
...paginationArgs,
|
|
3833
|
+
customer: {
|
|
3834
|
+
type: "positional",
|
|
3835
|
+
description: "Customer UUID or domain to retrieve facts for",
|
|
3836
|
+
required: true
|
|
3837
|
+
},
|
|
3838
|
+
status: {
|
|
3839
|
+
type: "string",
|
|
3840
|
+
description: `Comma-separated fact statuses (${customerFactStatuses.join(", ")})`
|
|
3841
|
+
},
|
|
3842
|
+
"source-types": {
|
|
3843
|
+
type: "string",
|
|
3844
|
+
description: `Comma-separated generic source type filter (${customerSourceTypes.join(", ")})`
|
|
3845
|
+
},
|
|
3846
|
+
after: {
|
|
3847
|
+
type: "string",
|
|
3848
|
+
description: "Filter to facts occurring after this ISO 8601 datetime"
|
|
3849
|
+
},
|
|
3850
|
+
before: {
|
|
3851
|
+
type: "string",
|
|
3852
|
+
description: "Filter to facts occurring before this ISO 8601 datetime"
|
|
3853
|
+
}
|
|
3854
|
+
},
|
|
3855
|
+
async run({ args }) {
|
|
3856
|
+
const json = !!args.json;
|
|
3857
|
+
const statuses = parseCsvArg(args.status);
|
|
3858
|
+
const sourceTypes = parseCsvArg(args["source-types"]);
|
|
3859
|
+
const invalidStatuses = invalidValues(statuses, customerFactStatuses);
|
|
3860
|
+
if (invalidStatuses.length > 0) {
|
|
3861
|
+
return outputError({
|
|
3862
|
+
message: `Unknown fact statuses: ${invalidStatuses.join(", ")}. Allowed: ${customerFactStatuses.join(", ")}`,
|
|
3863
|
+
code: "invalid_input"
|
|
3864
|
+
}, json);
|
|
3865
|
+
}
|
|
3866
|
+
const invalidSourceTypes = invalidValues(sourceTypes, customerSourceTypes);
|
|
3867
|
+
if (invalidSourceTypes.length > 0) {
|
|
3868
|
+
return outputError({
|
|
3869
|
+
message: `Unknown source types: ${invalidSourceTypes.join(", ")}. Allowed: ${customerSourceTypes.join(", ")}`,
|
|
3870
|
+
code: "invalid_input"
|
|
3871
|
+
}, json);
|
|
3872
|
+
}
|
|
3873
|
+
const afterDate = args.after ? new Date(args.after) : null;
|
|
3874
|
+
const beforeDate = args.before ? new Date(args.before) : null;
|
|
3875
|
+
if (afterDate && Number.isNaN(afterDate.getTime())) {
|
|
3876
|
+
return outputError({
|
|
3877
|
+
message: "--after must be a valid ISO 8601 datetime",
|
|
3878
|
+
code: "invalid_input"
|
|
3879
|
+
}, json);
|
|
3880
|
+
}
|
|
3881
|
+
if (beforeDate && Number.isNaN(beforeDate.getTime())) {
|
|
3882
|
+
return outputError({
|
|
3883
|
+
message: "--before must be a valid ISO 8601 datetime",
|
|
3884
|
+
code: "invalid_input"
|
|
3885
|
+
}, json);
|
|
3886
|
+
}
|
|
3887
|
+
if (afterDate && beforeDate && afterDate.getTime() > beforeDate.getTime()) {
|
|
3888
|
+
return outputError({
|
|
3889
|
+
message: "--after must be before or equal to --before",
|
|
3890
|
+
code: "invalid_input"
|
|
3891
|
+
}, json);
|
|
3892
|
+
}
|
|
3893
|
+
const client = await getClientOrExit(args["api-key"], json);
|
|
3894
|
+
const params = {
|
|
3895
|
+
customer: args.customer
|
|
3896
|
+
};
|
|
3897
|
+
if (statuses)
|
|
3898
|
+
params.status = statuses;
|
|
3899
|
+
if (sourceTypes)
|
|
3900
|
+
params.sourceTypes = sourceTypes;
|
|
3901
|
+
if (args.after)
|
|
3902
|
+
params.after = args.after;
|
|
3903
|
+
if (args.before)
|
|
3904
|
+
params.before = args.before;
|
|
3905
|
+
applyPagination(params, args, json);
|
|
3906
|
+
return runTool(client, customerToolContracts.outlit_list_facts.toolName, params, json);
|
|
3907
|
+
}
|
|
3908
|
+
});
|
|
3909
|
+
});
|
|
3910
|
+
|
|
3911
|
+
// src/commands/facts/get.ts
|
|
3912
|
+
var exports_get2 = {};
|
|
3913
|
+
__export(exports_get2, {
|
|
3914
|
+
default: () => get_default2
|
|
3915
|
+
});
|
|
3916
|
+
function parseCsvArg2(value) {
|
|
3917
|
+
if (!value)
|
|
3918
|
+
return;
|
|
3919
|
+
const items = splitCsv(value).map((item) => item.trim()).filter(Boolean);
|
|
3920
|
+
return items.length > 0 ? items : undefined;
|
|
3921
|
+
}
|
|
3922
|
+
var get_default2;
|
|
3923
|
+
var init_get2 = __esm(() => {
|
|
3924
|
+
init_dist();
|
|
3925
|
+
init_auth();
|
|
3926
|
+
init_output2();
|
|
3927
|
+
init_tool_contracts();
|
|
3928
|
+
init_api();
|
|
3929
|
+
init_config();
|
|
3930
|
+
get_default2 = defineCommand2({
|
|
3931
|
+
meta: {
|
|
3932
|
+
name: "get",
|
|
3933
|
+
description: [
|
|
3934
|
+
"Get one exact fact by ID.",
|
|
3935
|
+
"",
|
|
3936
|
+
"Use --include evidence to request best-effort evidence expansion.",
|
|
3566
3937
|
"",
|
|
3567
3938
|
"Examples:",
|
|
3568
|
-
" outlit
|
|
3569
|
-
" outlit
|
|
3570
|
-
` outlit doctor --json | jq '.checks[] | select(.status == "fail")'`,
|
|
3939
|
+
" outlit facts get --fact-id fact_123",
|
|
3940
|
+
" outlit facts get --fact-id fact_123 --include evidence",
|
|
3571
3941
|
"",
|
|
3572
|
-
|
|
3942
|
+
AGENT_JSON_HINT
|
|
3573
3943
|
].join(`
|
|
3574
3944
|
`)
|
|
3575
3945
|
},
|
|
3576
|
-
args: {
|
|
3946
|
+
args: {
|
|
3947
|
+
...authArgs,
|
|
3948
|
+
...outputArgs,
|
|
3949
|
+
"fact-id": {
|
|
3950
|
+
type: "string",
|
|
3951
|
+
description: "Fact ID to fetch",
|
|
3952
|
+
required: true
|
|
3953
|
+
},
|
|
3954
|
+
include: {
|
|
3955
|
+
type: "string",
|
|
3956
|
+
description: "Comma-separated best-effort expansions (for example: evidence)"
|
|
3957
|
+
}
|
|
3958
|
+
},
|
|
3577
3959
|
async run({ args }) {
|
|
3578
3960
|
const json = !!args.json;
|
|
3579
|
-
const
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
checks.push(await checkIntegrations(credential.key));
|
|
3588
|
-
}
|
|
3589
|
-
} else {
|
|
3590
|
-
checks.push({
|
|
3591
|
-
name: "API validation",
|
|
3592
|
-
status: "fail",
|
|
3593
|
-
message: "Skipped -- no API key found"
|
|
3594
|
-
});
|
|
3595
|
-
}
|
|
3596
|
-
checks.push(...detectAgents2());
|
|
3597
|
-
const hasFail = checks.some((c) => c.status === "fail");
|
|
3598
|
-
if (isJsonMode(json)) {
|
|
3599
|
-
outputResult({ ok: !hasFail, checks });
|
|
3600
|
-
} else {
|
|
3601
|
-
printChecks(checks);
|
|
3602
|
-
}
|
|
3603
|
-
if (hasFail)
|
|
3604
|
-
process.exit(1);
|
|
3961
|
+
const client = await getClientOrExit(args["api-key"], json);
|
|
3962
|
+
const params = {
|
|
3963
|
+
factId: args["fact-id"]
|
|
3964
|
+
};
|
|
3965
|
+
const include = parseCsvArg2(args.include);
|
|
3966
|
+
if (include)
|
|
3967
|
+
params.include = include;
|
|
3968
|
+
return runTool(client, customerToolContracts.outlit_get_fact.toolName, params, json);
|
|
3605
3969
|
}
|
|
3606
3970
|
});
|
|
3607
|
-
agentChecks = {
|
|
3608
|
-
cursor: {
|
|
3609
|
-
name: "Cursor",
|
|
3610
|
-
configCheck: { path: join7(homedir5(), ".cursor", "mcp.json"), key: "mcpServers" }
|
|
3611
|
-
},
|
|
3612
|
-
"claude-code": { name: "Claude Code" },
|
|
3613
|
-
"claude-desktop": {
|
|
3614
|
-
name: "Claude Desktop",
|
|
3615
|
-
configCheck: { path: getClaudeDesktopConfigPath(), key: "mcpServers" }
|
|
3616
|
-
},
|
|
3617
|
-
vscode: {
|
|
3618
|
-
name: "VS Code",
|
|
3619
|
-
configCheck: { path: join7(process.cwd(), ".vscode", "mcp.json"), key: "servers" }
|
|
3620
|
-
},
|
|
3621
|
-
gemini: { name: "Gemini CLI" },
|
|
3622
|
-
openclaw: { name: "OpenClaw" }
|
|
3623
|
-
};
|
|
3624
3971
|
});
|
|
3625
3972
|
|
|
3626
|
-
// src/commands/facts.ts
|
|
3973
|
+
// src/commands/facts/index.ts
|
|
3627
3974
|
var exports_facts = {};
|
|
3628
3975
|
__export(exports_facts, {
|
|
3629
3976
|
default: () => facts_default
|
|
@@ -3631,23 +3978,52 @@ __export(exports_facts, {
|
|
|
3631
3978
|
var facts_default;
|
|
3632
3979
|
var init_facts = __esm(() => {
|
|
3633
3980
|
init_dist();
|
|
3634
|
-
init_auth();
|
|
3635
3981
|
init_output2();
|
|
3636
|
-
init_pagination();
|
|
3637
|
-
init_api();
|
|
3638
3982
|
facts_default = defineCommand2({
|
|
3639
3983
|
meta: {
|
|
3640
3984
|
name: "facts",
|
|
3641
3985
|
description: [
|
|
3642
|
-
"
|
|
3986
|
+
"Query structured customer facts.",
|
|
3643
3987
|
"",
|
|
3644
|
-
"
|
|
3645
|
-
"
|
|
3988
|
+
"Subcommands:",
|
|
3989
|
+
" list -- list facts for a customer with filters",
|
|
3990
|
+
" get -- fetch one exact fact by id",
|
|
3991
|
+
"",
|
|
3992
|
+
AGENT_JSON_HINT
|
|
3993
|
+
].join(`
|
|
3994
|
+
`)
|
|
3995
|
+
},
|
|
3996
|
+
subCommands: {
|
|
3997
|
+
list: () => Promise.resolve().then(() => (init_list3(), exports_list3)).then((m) => m.default),
|
|
3998
|
+
get: () => Promise.resolve().then(() => (init_get2(), exports_get2)).then((m) => m.default)
|
|
3999
|
+
}
|
|
4000
|
+
});
|
|
4001
|
+
});
|
|
4002
|
+
|
|
4003
|
+
// src/commands/sources/get.ts
|
|
4004
|
+
var exports_get3 = {};
|
|
4005
|
+
__export(exports_get3, {
|
|
4006
|
+
default: () => get_default3
|
|
4007
|
+
});
|
|
4008
|
+
var get_default3;
|
|
4009
|
+
var init_get3 = __esm(() => {
|
|
4010
|
+
init_dist();
|
|
4011
|
+
init_auth();
|
|
4012
|
+
init_output2();
|
|
4013
|
+
init_tool_contracts();
|
|
4014
|
+
init_api();
|
|
4015
|
+
init_output();
|
|
4016
|
+
get_default3 = defineCommand2({
|
|
4017
|
+
meta: {
|
|
4018
|
+
name: "get",
|
|
4019
|
+
description: [
|
|
4020
|
+
"Get one exact source by source type and source id.",
|
|
3646
4021
|
"",
|
|
3647
4022
|
"Examples:",
|
|
3648
|
-
" outlit
|
|
3649
|
-
" outlit
|
|
3650
|
-
"
|
|
4023
|
+
" outlit sources get --source-type CALL --source-id call_123",
|
|
4024
|
+
" outlit sources get --source-type SUPPORT_TICKET --source-id ticket_456 --json",
|
|
4025
|
+
"",
|
|
4026
|
+
`Source types: ${customerSourceTypes.join(", ")}`,
|
|
3651
4027
|
"",
|
|
3652
4028
|
AGENT_JSON_HINT
|
|
3653
4029
|
].join(`
|
|
@@ -3656,27 +4032,58 @@ var init_facts = __esm(() => {
|
|
|
3656
4032
|
args: {
|
|
3657
4033
|
...authArgs,
|
|
3658
4034
|
...outputArgs,
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
description: "Customer UUID or domain to retrieve facts for",
|
|
4035
|
+
"source-type": {
|
|
4036
|
+
type: "string",
|
|
4037
|
+
description: "Canonical source type",
|
|
3663
4038
|
required: true
|
|
3664
4039
|
},
|
|
3665
|
-
|
|
4040
|
+
"source-id": {
|
|
3666
4041
|
type: "string",
|
|
3667
|
-
description: "
|
|
3668
|
-
|
|
4042
|
+
description: "Exact source id",
|
|
4043
|
+
required: true
|
|
3669
4044
|
}
|
|
3670
4045
|
},
|
|
3671
4046
|
async run({ args }) {
|
|
3672
4047
|
const json = !!args.json;
|
|
4048
|
+
if (!customerSourceTypes.includes(args["source-type"])) {
|
|
4049
|
+
return outputError({
|
|
4050
|
+
message: `--source-type must be one of ${customerSourceTypes.join(", ")}`,
|
|
4051
|
+
code: "invalid_input"
|
|
4052
|
+
}, json);
|
|
4053
|
+
}
|
|
3673
4054
|
const client = await getClientOrExit(args["api-key"], json);
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
};
|
|
3678
|
-
|
|
3679
|
-
|
|
4055
|
+
return runTool(client, customerToolContracts.outlit_get_source.toolName, {
|
|
4056
|
+
sourceType: args["source-type"],
|
|
4057
|
+
sourceId: args["source-id"]
|
|
4058
|
+
}, json);
|
|
4059
|
+
}
|
|
4060
|
+
});
|
|
4061
|
+
});
|
|
4062
|
+
|
|
4063
|
+
// src/commands/sources/index.ts
|
|
4064
|
+
var exports_sources = {};
|
|
4065
|
+
__export(exports_sources, {
|
|
4066
|
+
default: () => sources_default
|
|
4067
|
+
});
|
|
4068
|
+
var sources_default;
|
|
4069
|
+
var init_sources = __esm(() => {
|
|
4070
|
+
init_dist();
|
|
4071
|
+
init_output2();
|
|
4072
|
+
sources_default = defineCommand2({
|
|
4073
|
+
meta: {
|
|
4074
|
+
name: "sources",
|
|
4075
|
+
description: [
|
|
4076
|
+
"Fetch concrete customer sources by type and id.",
|
|
4077
|
+
"",
|
|
4078
|
+
"Subcommands:",
|
|
4079
|
+
" get -- fetch one exact source by sourceType and sourceId",
|
|
4080
|
+
"",
|
|
4081
|
+
AGENT_JSON_HINT
|
|
4082
|
+
].join(`
|
|
4083
|
+
`)
|
|
4084
|
+
},
|
|
4085
|
+
subCommands: {
|
|
4086
|
+
get: () => Promise.resolve().then(() => (init_get3(), exports_get3)).then((m) => m.default)
|
|
3680
4087
|
}
|
|
3681
4088
|
});
|
|
3682
4089
|
});
|
|
@@ -3691,25 +4098,25 @@ var init_search = __esm(() => {
|
|
|
3691
4098
|
init_dist();
|
|
3692
4099
|
init_auth();
|
|
3693
4100
|
init_output2();
|
|
4101
|
+
init_tool_contracts();
|
|
3694
4102
|
init_api();
|
|
4103
|
+
init_config();
|
|
3695
4104
|
init_output();
|
|
3696
4105
|
search_default = defineCommand2({
|
|
3697
4106
|
meta: {
|
|
3698
4107
|
name: "search",
|
|
3699
4108
|
description: [
|
|
3700
|
-
"Search customer context using natural language
|
|
4109
|
+
"Search customer context using natural language.",
|
|
3701
4110
|
"",
|
|
3702
|
-
"Performs a semantic search over
|
|
4111
|
+
"Performs a semantic search over grouped source and fact results.",
|
|
3703
4112
|
"Optionally scope to a specific customer with --customer.",
|
|
3704
|
-
"Use --source-type and --source-id for direct source lookup (query becomes optional).",
|
|
3705
4113
|
"",
|
|
3706
4114
|
"Examples:",
|
|
3707
4115
|
" outlit search 'pricing objections last quarter'",
|
|
3708
4116
|
" outlit search 'churn risk signals' --customer acme.com",
|
|
3709
4117
|
" outlit search 'expansion opportunities' --top-k 50 --json",
|
|
3710
|
-
" outlit search 'support escalations' --after 2025-01-
|
|
3711
|
-
" outlit search 'onboarding issues' --source-types
|
|
3712
|
-
" outlit search --source-type call_transcript --source-id call_123",
|
|
4118
|
+
" outlit search 'support escalations' --after 2025-01-01T00:00:00Z --before 2025-03-31T23:59:59Z",
|
|
4119
|
+
" outlit search 'onboarding issues' --source-types CALL,EMAIL",
|
|
3713
4120
|
"",
|
|
3714
4121
|
AGENT_JSON_HINT
|
|
3715
4122
|
].join(`
|
|
@@ -3720,8 +4127,8 @@ var init_search = __esm(() => {
|
|
|
3720
4127
|
...outputArgs,
|
|
3721
4128
|
query: {
|
|
3722
4129
|
type: "positional",
|
|
3723
|
-
description: "Natural language search query
|
|
3724
|
-
required:
|
|
4130
|
+
description: "Natural language search query",
|
|
4131
|
+
required: true
|
|
3725
4132
|
},
|
|
3726
4133
|
customer: {
|
|
3727
4134
|
type: "string",
|
|
@@ -3729,75 +4136,51 @@ var init_search = __esm(() => {
|
|
|
3729
4136
|
},
|
|
3730
4137
|
"top-k": {
|
|
3731
4138
|
type: "string",
|
|
3732
|
-
description: "Maximum number of results to return (1–50). Default: 20."
|
|
3733
|
-
default: "20"
|
|
4139
|
+
description: "Maximum number of results to return (1–50). Default: 20."
|
|
3734
4140
|
},
|
|
3735
4141
|
after: {
|
|
3736
4142
|
type: "string",
|
|
3737
|
-
description: "Filter to events occurring after this
|
|
4143
|
+
description: "Filter to events occurring after this datetime (ISO 8601, e.g. 2025-01-01T00:00:00Z)"
|
|
3738
4144
|
},
|
|
3739
4145
|
before: {
|
|
3740
4146
|
type: "string",
|
|
3741
|
-
description: "Filter to events occurring before this
|
|
4147
|
+
description: "Filter to events occurring before this datetime (ISO 8601, e.g. 2025-03-31T23:59:59Z)"
|
|
3742
4148
|
},
|
|
3743
4149
|
"source-types": {
|
|
3744
4150
|
type: "string",
|
|
3745
|
-
description:
|
|
3746
|
-
},
|
|
3747
|
-
"source-type": {
|
|
3748
|
-
type: "string",
|
|
3749
|
-
description: "Exact source type for direct lookup (must pair with --source-id)"
|
|
3750
|
-
},
|
|
3751
|
-
"source-id": {
|
|
3752
|
-
type: "string",
|
|
3753
|
-
description: "Exact source ID for direct lookup (must pair with --source-type)"
|
|
4151
|
+
description: `Comma-separated generic source type filter (${customerSourceTypes.join(", ")})`
|
|
3754
4152
|
}
|
|
3755
4153
|
},
|
|
3756
4154
|
async run({ args }) {
|
|
3757
4155
|
const json = !!args.json;
|
|
3758
|
-
const topK = Number(args["top-k"]);
|
|
3759
|
-
if (!Number.isFinite(topK) || topK < 1 || topK > 50) {
|
|
4156
|
+
const topK = args["top-k"] ? Number(args["top-k"]) : undefined;
|
|
4157
|
+
if (topK !== undefined && (!Number.isFinite(topK) || !Number.isInteger(topK) || topK < 1 || topK > 50)) {
|
|
3760
4158
|
return outputError({ message: "--top-k must be an integer between 1 and 50", code: "invalid_input" }, json);
|
|
3761
4159
|
}
|
|
3762
|
-
const
|
|
3763
|
-
const
|
|
3764
|
-
|
|
3765
|
-
if (sourceType && !sourceId || !sourceType && sourceId) {
|
|
4160
|
+
const sourceTypes = args["source-types"] ? splitCsv(args["source-types"]).map((item) => item.trim()).filter(Boolean) : undefined;
|
|
4161
|
+
const invalidSourceTypes = sourceTypes?.filter((value) => !customerSourceTypes.includes(value));
|
|
4162
|
+
if (invalidSourceTypes && invalidSourceTypes.length > 0) {
|
|
3766
4163
|
return outputError({
|
|
3767
|
-
message:
|
|
4164
|
+
message: `Unknown source types: ${invalidSourceTypes.join(", ")}. Allowed: ${customerSourceTypes.join(", ")}`,
|
|
3768
4165
|
code: "invalid_input"
|
|
3769
4166
|
}, json);
|
|
3770
4167
|
}
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
4168
|
+
const resolved = resolveCustomerContextSearchInput({
|
|
4169
|
+
query: args.query,
|
|
4170
|
+
customer: args.customer,
|
|
4171
|
+
topK,
|
|
4172
|
+
after: args.after,
|
|
4173
|
+
before: args.before,
|
|
4174
|
+
sourceTypes
|
|
4175
|
+
});
|
|
4176
|
+
if (!resolved.ok) {
|
|
3778
4177
|
return outputError({
|
|
3779
|
-
message:
|
|
4178
|
+
message: resolved.message,
|
|
3780
4179
|
code: "invalid_input"
|
|
3781
4180
|
}, json);
|
|
3782
4181
|
}
|
|
3783
4182
|
const client = await getClientOrExit(args["api-key"], json);
|
|
3784
|
-
|
|
3785
|
-
const params = { topK };
|
|
3786
|
-
if (args.query)
|
|
3787
|
-
params.query = args.query;
|
|
3788
|
-
if (args.customer)
|
|
3789
|
-
params.customer = args.customer;
|
|
3790
|
-
if (args.after)
|
|
3791
|
-
params.occurredAfter = args.after;
|
|
3792
|
-
if (args.before)
|
|
3793
|
-
params.occurredBefore = args.before;
|
|
3794
|
-
if (sourceTypes)
|
|
3795
|
-
params.sourceTypes = parseCsv(sourceTypes);
|
|
3796
|
-
if (sourceType)
|
|
3797
|
-
params.sourceType = sourceType;
|
|
3798
|
-
if (sourceId)
|
|
3799
|
-
params.sourceId = sourceId;
|
|
3800
|
-
return runTool(client, "outlit_search_customer_context", params, json);
|
|
4183
|
+
return runTool(client, customerToolContracts.outlit_search_customer_context.toolName, resolved.request, json);
|
|
3801
4184
|
}
|
|
3802
4185
|
});
|
|
3803
4186
|
});
|
|
@@ -3807,12 +4190,13 @@ var exports_sql = {};
|
|
|
3807
4190
|
__export(exports_sql, {
|
|
3808
4191
|
default: () => sql_default
|
|
3809
4192
|
});
|
|
3810
|
-
import { readFileSync as
|
|
4193
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
3811
4194
|
var sql_default;
|
|
3812
4195
|
var init_sql = __esm(() => {
|
|
3813
4196
|
init_dist();
|
|
3814
4197
|
init_auth();
|
|
3815
4198
|
init_output2();
|
|
4199
|
+
init_tool_contracts();
|
|
3816
4200
|
init_api();
|
|
3817
4201
|
init_output();
|
|
3818
4202
|
sql_default = defineCommand2({
|
|
@@ -3824,7 +4208,7 @@ var init_sql = __esm(() => {
|
|
|
3824
4208
|
"Provide the query as a positional argument or via --query-file.",
|
|
3825
4209
|
"When both are provided, --query-file takes precedence.",
|
|
3826
4210
|
"",
|
|
3827
|
-
|
|
4211
|
+
`Available tables: ${schemaTables.join(", ")}`,
|
|
3828
4212
|
"",
|
|
3829
4213
|
"Examples:",
|
|
3830
4214
|
" outlit sql 'SELECT * FROM events LIMIT 10'",
|
|
@@ -3859,7 +4243,7 @@ var init_sql = __esm(() => {
|
|
|
3859
4243
|
let sql;
|
|
3860
4244
|
if (args["query-file"]) {
|
|
3861
4245
|
try {
|
|
3862
|
-
sql =
|
|
4246
|
+
sql = readFileSync4(args["query-file"], "utf-8");
|
|
3863
4247
|
} catch (err) {
|
|
3864
4248
|
return outputError({
|
|
3865
4249
|
message: `Cannot read file: ${errorMessage(err, "unknown error")}`,
|
|
@@ -3875,7 +4259,7 @@ var init_sql = __esm(() => {
|
|
|
3875
4259
|
if (!Number.isFinite(limit) || limit <= 0) {
|
|
3876
4260
|
return outputError({ message: "--limit must be a positive number", code: "invalid_input" }, json);
|
|
3877
4261
|
}
|
|
3878
|
-
return runTool(client,
|
|
4262
|
+
return runTool(client, customerToolContracts.outlit_query.toolName, { sql, limit }, json);
|
|
3879
4263
|
}
|
|
3880
4264
|
});
|
|
3881
4265
|
});
|
|
@@ -3890,6 +4274,7 @@ var init_schema = __esm(() => {
|
|
|
3890
4274
|
init_dist();
|
|
3891
4275
|
init_auth();
|
|
3892
4276
|
init_output2();
|
|
4277
|
+
init_tool_contracts();
|
|
3893
4278
|
init_api();
|
|
3894
4279
|
schema_default = defineCommand2({
|
|
3895
4280
|
meta: {
|
|
@@ -3900,7 +4285,7 @@ var init_schema = __esm(() => {
|
|
|
3900
4285
|
"Without a table name, returns the full schema for all tables.",
|
|
3901
4286
|
"With a table name, returns detailed column info for that table.",
|
|
3902
4287
|
"",
|
|
3903
|
-
|
|
4288
|
+
`Available tables: ${schemaTables.join(", ")}`,
|
|
3904
4289
|
"",
|
|
3905
4290
|
"Examples:",
|
|
3906
4291
|
" outlit schema",
|
|
@@ -3916,7 +4301,7 @@ var init_schema = __esm(() => {
|
|
|
3916
4301
|
...outputArgs,
|
|
3917
4302
|
table: {
|
|
3918
4303
|
type: "positional",
|
|
3919
|
-
description:
|
|
4304
|
+
description: `Table to describe (${schemaTables.join(", ")}). Optional.`,
|
|
3920
4305
|
required: false
|
|
3921
4306
|
}
|
|
3922
4307
|
},
|
|
@@ -3926,7 +4311,7 @@ var init_schema = __esm(() => {
|
|
|
3926
4311
|
const params = {};
|
|
3927
4312
|
if (args.table)
|
|
3928
4313
|
params.table = args.table;
|
|
3929
|
-
return runTool(client,
|
|
4314
|
+
return runTool(client, customerToolContracts.outlit_schema.toolName, params, json);
|
|
3930
4315
|
}
|
|
3931
4316
|
});
|
|
3932
4317
|
});
|
|
@@ -4022,17 +4407,17 @@ var init_providers = __esm(() => {
|
|
|
4022
4407
|
});
|
|
4023
4408
|
|
|
4024
4409
|
// src/commands/integrations/list.ts
|
|
4025
|
-
var
|
|
4026
|
-
__export(
|
|
4027
|
-
default: () =>
|
|
4410
|
+
var exports_list4 = {};
|
|
4411
|
+
__export(exports_list4, {
|
|
4412
|
+
default: () => list_default4
|
|
4028
4413
|
});
|
|
4029
|
-
var
|
|
4030
|
-
var
|
|
4414
|
+
var list_default4;
|
|
4415
|
+
var init_list4 = __esm(() => {
|
|
4031
4416
|
init_dist();
|
|
4032
4417
|
init_auth();
|
|
4033
4418
|
init_output2();
|
|
4034
4419
|
init_api();
|
|
4035
|
-
|
|
4420
|
+
list_default4 = defineCommand2({
|
|
4036
4421
|
meta: {
|
|
4037
4422
|
name: "list",
|
|
4038
4423
|
description: [
|
|
@@ -4486,7 +4871,7 @@ var init_integrations = __esm(() => {
|
|
|
4486
4871
|
`)
|
|
4487
4872
|
},
|
|
4488
4873
|
subCommands: {
|
|
4489
|
-
list: () => Promise.resolve().then(() => (
|
|
4874
|
+
list: () => Promise.resolve().then(() => (init_list4(), exports_list4)).then((m) => m.default),
|
|
4490
4875
|
add: () => Promise.resolve().then(() => (init_add(), exports_add)).then((m) => m.default),
|
|
4491
4876
|
remove: () => Promise.resolve().then(() => (init_remove(), exports_remove)).then((m) => m.default),
|
|
4492
4877
|
status: () => Promise.resolve().then(() => (init_status2(), exports_status2)).then((m) => m.default)
|
|
@@ -4741,9 +5126,7 @@ var init_completions = __esm(() => {
|
|
|
4741
5126
|
{ name: "--billing-status", desc: "Filter by billing status" },
|
|
4742
5127
|
{ name: "--mrr-above", desc: "MRR above threshold (cents)" },
|
|
4743
5128
|
{ name: "--mrr-below", desc: "MRR below threshold (cents)" },
|
|
4744
|
-
{ name: "--search", desc: "Search name or domain" }
|
|
4745
|
-
{ name: "--status", desc: "Customer status filter" },
|
|
4746
|
-
{ name: "--type", desc: "Customer type filter" }
|
|
5129
|
+
{ name: "--search", desc: "Search name or domain" }
|
|
4747
5130
|
]
|
|
4748
5131
|
},
|
|
4749
5132
|
{
|
|
@@ -4790,7 +5173,43 @@ var init_completions = __esm(() => {
|
|
|
4790
5173
|
{
|
|
4791
5174
|
name: "facts",
|
|
4792
5175
|
desc: "Get customer facts",
|
|
4793
|
-
|
|
5176
|
+
subs: [
|
|
5177
|
+
{
|
|
5178
|
+
name: "list",
|
|
5179
|
+
desc: "List customer facts",
|
|
5180
|
+
flags: [
|
|
5181
|
+
...PAGINATED,
|
|
5182
|
+
{ name: "--status", desc: "Filter by fact status" },
|
|
5183
|
+
{ name: "--source-types", desc: "Filter by source types" },
|
|
5184
|
+
{ name: "--after", desc: "Facts after date (ISO 8601)" },
|
|
5185
|
+
{ name: "--before", desc: "Facts before date (ISO 8601)" }
|
|
5186
|
+
]
|
|
5187
|
+
},
|
|
5188
|
+
{
|
|
5189
|
+
name: "get",
|
|
5190
|
+
desc: "Get a single fact by ID",
|
|
5191
|
+
flags: [
|
|
5192
|
+
...COMMON,
|
|
5193
|
+
{ name: "--fact-id", desc: "Fact ID to fetch" },
|
|
5194
|
+
{ name: "--include", desc: "Best-effort expansions" }
|
|
5195
|
+
]
|
|
5196
|
+
}
|
|
5197
|
+
]
|
|
5198
|
+
},
|
|
5199
|
+
{
|
|
5200
|
+
name: "sources",
|
|
5201
|
+
desc: "Get a concrete source by type and id",
|
|
5202
|
+
subs: [
|
|
5203
|
+
{
|
|
5204
|
+
name: "get",
|
|
5205
|
+
desc: "Get one exact source record",
|
|
5206
|
+
flags: [
|
|
5207
|
+
...COMMON,
|
|
5208
|
+
{ name: "--source-type", desc: "Canonical source type" },
|
|
5209
|
+
{ name: "--source-id", desc: "Exact source ID" }
|
|
5210
|
+
]
|
|
5211
|
+
}
|
|
5212
|
+
]
|
|
4794
5213
|
},
|
|
4795
5214
|
{
|
|
4796
5215
|
name: "search",
|
|
@@ -4800,7 +5219,8 @@ var init_completions = __esm(() => {
|
|
|
4800
5219
|
{ name: "--customer", desc: "Scope to customer (UUID or domain)" },
|
|
4801
5220
|
{ name: "--top-k", desc: "Max results" },
|
|
4802
5221
|
{ name: "--after", desc: "Events after date (ISO 8601)" },
|
|
4803
|
-
{ name: "--before", desc: "Events before date (ISO 8601)" }
|
|
5222
|
+
{ name: "--before", desc: "Events before date (ISO 8601)" },
|
|
5223
|
+
{ name: "--source-types", desc: "Broad source type filter" }
|
|
4804
5224
|
]
|
|
4805
5225
|
},
|
|
4806
5226
|
{
|
|
@@ -4837,17 +5257,20 @@ var init_completions = __esm(() => {
|
|
|
4837
5257
|
},
|
|
4838
5258
|
{
|
|
4839
5259
|
name: "setup",
|
|
4840
|
-
desc: "
|
|
4841
|
-
flags: [
|
|
5260
|
+
desc: "Install Outlit skills for coding agents",
|
|
5261
|
+
flags: [JSON_F, { name: "--yes", desc: "Skip prompts" }],
|
|
4842
5262
|
subs: [
|
|
4843
|
-
{ name: "
|
|
4844
|
-
{ name: "
|
|
4845
|
-
{ name: "
|
|
4846
|
-
{ name: "
|
|
4847
|
-
{ name: "
|
|
4848
|
-
{ name: "
|
|
5263
|
+
{ name: "claude-code", desc: "Install the Outlit skill for Claude Code", flags: [JSON_F] },
|
|
5264
|
+
{ name: "codex", desc: "Install the Outlit skill for Codex", flags: [JSON_F] },
|
|
5265
|
+
{ name: "gemini", desc: "Install the Outlit skill for Gemini CLI", flags: [JSON_F] },
|
|
5266
|
+
{ name: "droid", desc: "Install the Outlit skill for Droid", flags: [JSON_F] },
|
|
5267
|
+
{ name: "opencode", desc: "Install the Outlit skill for OpenCode", flags: [JSON_F] },
|
|
5268
|
+
{ name: "pi", desc: "Install the Outlit skill for Pi", flags: [JSON_F] },
|
|
5269
|
+
{ name: "openclaw", desc: "Install the Outlit skill for OpenClaw", flags: [JSON_F] },
|
|
5270
|
+
{ name: "skills", desc: "Launch the interactive Outlit skills installer", flags: [JSON_F] }
|
|
4849
5271
|
]
|
|
4850
5272
|
},
|
|
5273
|
+
{ name: "upgrade", desc: "Upgrade the CLI", flags: [] },
|
|
4851
5274
|
{ name: "doctor", desc: "Diagnose environment", flags: [...COMMON] },
|
|
4852
5275
|
{ name: "completions", desc: "Generate shell completions", flags: [] }
|
|
4853
5276
|
];
|
|
@@ -4900,142 +5323,149 @@ var init_completions = __esm(() => {
|
|
|
4900
5323
|
var exports_setup = {};
|
|
4901
5324
|
__export(exports_setup, {
|
|
4902
5325
|
isCommandAvailable: () => isCommandAvailable2,
|
|
4903
|
-
detectAgents: () =>
|
|
5326
|
+
detectAgents: () => detectAgents2,
|
|
4904
5327
|
default: () => setup_default2
|
|
4905
5328
|
});
|
|
4906
|
-
import { execFileSync as
|
|
4907
|
-
import { existsSync as
|
|
5329
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
5330
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
4908
5331
|
import { homedir as homedir6 } from "node:os";
|
|
4909
|
-
import { join as
|
|
5332
|
+
import { join as join7 } from "node:path";
|
|
4910
5333
|
function isCommandAvailable2(cmd) {
|
|
4911
5334
|
try {
|
|
4912
5335
|
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
4913
|
-
|
|
5336
|
+
execFileSync6(whichCmd, [cmd], { stdio: "ignore" });
|
|
4914
5337
|
return true;
|
|
4915
5338
|
} catch {
|
|
4916
5339
|
return false;
|
|
4917
5340
|
}
|
|
4918
5341
|
}
|
|
4919
|
-
function
|
|
4920
|
-
|
|
5342
|
+
function getHomeDir3() {
|
|
5343
|
+
return process.env.HOME?.trim() || homedir6();
|
|
5344
|
+
}
|
|
5345
|
+
function detectAgents2() {
|
|
5346
|
+
const home = getHomeDir3();
|
|
5347
|
+
const configHome = process.env.XDG_CONFIG_HOME?.trim() || join7(home, ".config");
|
|
4921
5348
|
const detected = [];
|
|
4922
|
-
if (existsSync4(join8(home, ".cursor")))
|
|
4923
|
-
detected.push("cursor");
|
|
4924
5349
|
if (isCommandAvailable2("claude"))
|
|
4925
5350
|
detected.push("claude-code");
|
|
4926
|
-
if (
|
|
4927
|
-
detected.push("
|
|
4928
|
-
if (isCommandAvailable2("code") || existsSync4(join8(process.cwd(), ".vscode")))
|
|
4929
|
-
detected.push("vscode");
|
|
5351
|
+
if (isCommandAvailable2("codex"))
|
|
5352
|
+
detected.push("codex");
|
|
4930
5353
|
if (isCommandAvailable2("gemini"))
|
|
4931
5354
|
detected.push("gemini");
|
|
4932
|
-
if (
|
|
5355
|
+
if (existsSync6(join7(home, ".factory")))
|
|
5356
|
+
detected.push("droid");
|
|
5357
|
+
if (existsSync6(join7(configHome, "opencode")))
|
|
5358
|
+
detected.push("opencode");
|
|
5359
|
+
if (existsSync6(join7(home, ".pi", "agent")))
|
|
5360
|
+
detected.push("pi");
|
|
5361
|
+
if (existsSync6(join7(home, ".openclaw")) || existsSync6(join7(home, ".clawdbot")) || existsSync6(join7(home, ".moltbot"))) {
|
|
4933
5362
|
detected.push("openclaw");
|
|
5363
|
+
}
|
|
4934
5364
|
return detected;
|
|
4935
5365
|
}
|
|
4936
|
-
var agentLabels2,
|
|
4937
|
-
var
|
|
5366
|
+
var agentLabels2, setupSubcommandNames2, setup_default2;
|
|
5367
|
+
var init_setup2 = __esm(() => {
|
|
4938
5368
|
init_dist();
|
|
4939
|
-
init_auth();
|
|
4940
5369
|
init_output2();
|
|
4941
5370
|
init_config();
|
|
4942
5371
|
init_output();
|
|
4943
|
-
init_claude_code();
|
|
4944
|
-
init_claude_desktop();
|
|
4945
|
-
init_cursor();
|
|
4946
|
-
init_gemini();
|
|
4947
|
-
init_openclaw();
|
|
4948
5372
|
init_skills();
|
|
4949
|
-
init_vscode();
|
|
4950
5373
|
agentLabels2 = {
|
|
4951
|
-
cursor: { label: "Cursor", hint: "~/.cursor/" },
|
|
4952
5374
|
"claude-code": { label: "Claude Code", hint: "claude CLI found" },
|
|
4953
|
-
|
|
4954
|
-
vscode: { label: "VS Code", hint: "code CLI or .vscode/ found" },
|
|
5375
|
+
codex: { label: "Codex", hint: "codex CLI found" },
|
|
4955
5376
|
gemini: { label: "Gemini CLI", hint: "gemini CLI found" },
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
"claude-code": configureSafe,
|
|
4961
|
-
"claude-desktop": configureSafe2,
|
|
4962
|
-
vscode: configureSafe6,
|
|
4963
|
-
gemini: configureSafe4,
|
|
4964
|
-
openclaw: configureSafe5
|
|
5377
|
+
droid: { label: "Droid", hint: ".factory config found" },
|
|
5378
|
+
opencode: { label: "OpenCode", hint: "opencode config found" },
|
|
5379
|
+
pi: { label: "Pi", hint: ".pi/agent config found" },
|
|
5380
|
+
openclaw: { label: "OpenClaw", hint: "OpenClaw config found" }
|
|
4965
5381
|
};
|
|
5382
|
+
setupSubcommandNames2 = new Set([
|
|
5383
|
+
"claude-code",
|
|
5384
|
+
"codex",
|
|
5385
|
+
"gemini",
|
|
5386
|
+
"droid",
|
|
5387
|
+
"opencode",
|
|
5388
|
+
"pi",
|
|
5389
|
+
"openclaw",
|
|
5390
|
+
"skills"
|
|
5391
|
+
]);
|
|
4966
5392
|
setup_default2 = defineCommand2({
|
|
4967
5393
|
meta: {
|
|
4968
5394
|
name: "setup",
|
|
4969
5395
|
description: [
|
|
4970
|
-
"
|
|
5396
|
+
"Install the Outlit skill for coding agents.",
|
|
4971
5397
|
"",
|
|
4972
|
-
"Without a subcommand, auto-detects
|
|
4973
|
-
"Subcommands:
|
|
5398
|
+
"Without a subcommand, auto-detects supported coding agents and installs `outlit` for all of them.",
|
|
5399
|
+
"Subcommands: claude-code, codex, gemini, droid, opencode, pi, openclaw, skills"
|
|
4974
5400
|
].join(`
|
|
4975
5401
|
`)
|
|
4976
5402
|
},
|
|
4977
5403
|
args: {
|
|
4978
|
-
...authArgs,
|
|
4979
5404
|
...outputArgs,
|
|
4980
5405
|
yes: {
|
|
4981
5406
|
type: "boolean",
|
|
4982
|
-
description: "
|
|
5407
|
+
description: "Install for all detected coding agents without prompting."
|
|
4983
5408
|
}
|
|
4984
5409
|
},
|
|
4985
5410
|
subCommands: {
|
|
4986
|
-
cursor: () => Promise.resolve().then(() => (init_cursor(), exports_cursor)).then((m) => m.default),
|
|
4987
5411
|
"claude-code": () => Promise.resolve().then(() => (init_claude_code(), exports_claude_code)).then((m) => m.default),
|
|
4988
|
-
|
|
4989
|
-
vscode: () => Promise.resolve().then(() => (init_vscode(), exports_vscode)).then((m) => m.default),
|
|
5412
|
+
codex: () => Promise.resolve().then(() => (init_codex(), exports_codex)).then((m) => m.default),
|
|
4990
5413
|
gemini: () => Promise.resolve().then(() => (init_gemini(), exports_gemini)).then((m) => m.default),
|
|
5414
|
+
droid: () => Promise.resolve().then(() => (init_droid(), exports_droid)).then((m) => m.default),
|
|
5415
|
+
opencode: () => Promise.resolve().then(() => (init_opencode(), exports_opencode)).then((m) => m.default),
|
|
5416
|
+
pi: () => Promise.resolve().then(() => (init_pi(), exports_pi)).then((m) => m.default),
|
|
4991
5417
|
openclaw: () => Promise.resolve().then(() => (init_openclaw(), exports_openclaw)).then((m) => m.default),
|
|
4992
5418
|
skills: () => Promise.resolve().then(() => (init_skills(), exports_skills)).then((m) => m.default)
|
|
4993
5419
|
},
|
|
4994
|
-
async run({ args }) {
|
|
5420
|
+
async run({ args, rawArgs }) {
|
|
5421
|
+
const setupRawArgs = rawArgs ?? [];
|
|
5422
|
+
const subcommandName = setupRawArgs.find((arg) => !arg.startsWith("-"));
|
|
5423
|
+
if (subcommandName && setupSubcommandNames2.has(subcommandName)) {
|
|
5424
|
+
return;
|
|
5425
|
+
}
|
|
4995
5426
|
const json = !!args.json;
|
|
4996
|
-
const
|
|
4997
|
-
const detected = detectAgents3();
|
|
5427
|
+
const detected = detectAgents2();
|
|
4998
5428
|
if (detected.length === 0) {
|
|
4999
5429
|
if (isJsonMode(json)) {
|
|
5000
|
-
return outputResult({ detected: [], configured: [], failed: [],
|
|
5430
|
+
return outputResult({ detected: [], configured: [], failed: [], runner: null });
|
|
5001
5431
|
}
|
|
5002
|
-
console.log("No supported
|
|
5432
|
+
console.log("No supported coding agents detected.");
|
|
5003
5433
|
return;
|
|
5004
5434
|
}
|
|
5005
5435
|
if (!isJsonMode(json) && !args.yes) {
|
|
5006
|
-
console.log("Detected agents:");
|
|
5436
|
+
console.log("Detected coding agents:");
|
|
5007
5437
|
for (const agentId of detected) {
|
|
5008
5438
|
const { label, hint } = agentLabels2[agentId];
|
|
5009
5439
|
console.log(` ${TICK2} ${label.padEnd(14)} -- ${hint}`);
|
|
5010
5440
|
}
|
|
5011
5441
|
console.log(`
|
|
5012
|
-
|
|
5013
|
-
}
|
|
5014
|
-
const configured = [];
|
|
5015
|
-
const failed = [];
|
|
5016
|
-
for (const agentId of detected) {
|
|
5017
|
-
const ok = configurators2[agentId](credential.key, json);
|
|
5018
|
-
if (ok) {
|
|
5019
|
-
configured.push(agentId);
|
|
5020
|
-
} else {
|
|
5021
|
-
failed.push(agentId);
|
|
5022
|
-
}
|
|
5023
|
-
}
|
|
5024
|
-
const skills = runSkillsInstall(json, false);
|
|
5025
|
-
if (!isJsonMode(json) && !skills.success) {
|
|
5026
|
-
console.log(`
|
|
5027
|
-
! Agent skills installation failed: ${skills.error ?? "unknown error"}`);
|
|
5028
|
-
console.log(" Run `outlit setup skills` to retry.");
|
|
5442
|
+
Installing Outlit skill...`);
|
|
5029
5443
|
}
|
|
5444
|
+
const install = runSkillsInstall({
|
|
5445
|
+
json,
|
|
5446
|
+
exitOnError: false,
|
|
5447
|
+
agents: detected.map(getSkillAgentId),
|
|
5448
|
+
skillNames: ["outlit"],
|
|
5449
|
+
autoConfirm: true
|
|
5450
|
+
});
|
|
5451
|
+
const configured = install.success ? detected : [];
|
|
5452
|
+
const failed = install.success ? [] : detected;
|
|
5030
5453
|
if (isJsonMode(json)) {
|
|
5031
|
-
return outputResult({
|
|
5454
|
+
return outputResult({
|
|
5455
|
+
detected,
|
|
5456
|
+
configured,
|
|
5457
|
+
failed,
|
|
5458
|
+
runner: install.runner ?? null
|
|
5459
|
+
});
|
|
5032
5460
|
}
|
|
5033
|
-
if (
|
|
5461
|
+
if (!install.success) {
|
|
5034
5462
|
console.log(`
|
|
5035
|
-
|
|
5463
|
+
! Outlit skill install failed: ${install.error ?? "unknown error"}`);
|
|
5464
|
+
console.log(" Run `outlit setup skills` to retry manually.");
|
|
5465
|
+
return;
|
|
5036
5466
|
}
|
|
5037
5467
|
console.log(`
|
|
5038
|
-
Done. ${configured.length}
|
|
5468
|
+
Done. Installed Outlit for ${configured.length} coding agent(s).`);
|
|
5039
5469
|
}
|
|
5040
5470
|
});
|
|
5041
5471
|
});
|
|
@@ -5392,11 +5822,226 @@ init_tty();
|
|
|
5392
5822
|
var CLI_VERSION = package_default.version;
|
|
5393
5823
|
var TICK = `\x1B[32m${isUnicodeSupported ? String.fromCodePoint(10003) : String.fromCodePoint(8730)}\x1B[0m`;
|
|
5394
5824
|
|
|
5825
|
+
// src/lib/update.ts
|
|
5826
|
+
init_config();
|
|
5827
|
+
init_tty();
|
|
5828
|
+
import { execFileSync as execFileSync2, spawn, spawnSync } from "node:child_process";
|
|
5829
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, realpathSync, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
5830
|
+
import { homedir as homedir2 } from "node:os";
|
|
5831
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
5832
|
+
var UPDATE_CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
|
|
5833
|
+
var PACKAGE_NAME = "@outlit/cli";
|
|
5834
|
+
var LATEST_VERSION_URL = "https://registry.npmjs.org/@outlit%2Fcli/latest";
|
|
5835
|
+
var INTERNAL_UPDATE_FLAG = "--internal-update-check";
|
|
5836
|
+
function getUpdateCachePath() {
|
|
5837
|
+
return join2(getConfigDir(), "update-check.json");
|
|
5838
|
+
}
|
|
5839
|
+
function readCachedUpdateState() {
|
|
5840
|
+
const cachePath = getUpdateCachePath();
|
|
5841
|
+
if (!existsSync2(cachePath))
|
|
5842
|
+
return null;
|
|
5843
|
+
try {
|
|
5844
|
+
return JSON.parse(readFileSync2(cachePath, "utf8"));
|
|
5845
|
+
} catch {
|
|
5846
|
+
return null;
|
|
5847
|
+
}
|
|
5848
|
+
}
|
|
5849
|
+
function writeCachedUpdateState(state) {
|
|
5850
|
+
const cachePath = getUpdateCachePath();
|
|
5851
|
+
mkdirSync2(dirname2(cachePath), { recursive: true });
|
|
5852
|
+
writeFileSync2(cachePath, `${JSON.stringify(state, null, 2)}
|
|
5853
|
+
`);
|
|
5854
|
+
}
|
|
5855
|
+
function isUpdateCheckDue(state) {
|
|
5856
|
+
if (!state?.lastCheckedAt)
|
|
5857
|
+
return true;
|
|
5858
|
+
return Date.now() - state.lastCheckedAt >= UPDATE_CHECK_INTERVAL_MS;
|
|
5859
|
+
}
|
|
5860
|
+
function compareVersions(a, b) {
|
|
5861
|
+
const aParts = a.split("-")[0]?.split(".").map((part) => Number.parseInt(part, 10) || 0) ?? [];
|
|
5862
|
+
const bParts = b.split("-")[0]?.split(".").map((part) => Number.parseInt(part, 10) || 0) ?? [];
|
|
5863
|
+
const maxLength = Math.max(aParts.length, bParts.length);
|
|
5864
|
+
for (let index = 0;index < maxLength; index++) {
|
|
5865
|
+
const left = aParts[index] ?? 0;
|
|
5866
|
+
const right = bParts[index] ?? 0;
|
|
5867
|
+
if (left > right)
|
|
5868
|
+
return 1;
|
|
5869
|
+
if (left < right)
|
|
5870
|
+
return -1;
|
|
5871
|
+
}
|
|
5872
|
+
return 0;
|
|
5873
|
+
}
|
|
5874
|
+
function inferInstallerFromUserAgent(agent) {
|
|
5875
|
+
if (agent.startsWith("bun/"))
|
|
5876
|
+
return "bun";
|
|
5877
|
+
if (agent.startsWith("npm/"))
|
|
5878
|
+
return "npm";
|
|
5879
|
+
if (agent.startsWith("pnpm/"))
|
|
5880
|
+
return "pnpm";
|
|
5881
|
+
if (agent.startsWith("yarn/"))
|
|
5882
|
+
return "yarn";
|
|
5883
|
+
return null;
|
|
5884
|
+
}
|
|
5885
|
+
function isUnderPath(path, parent) {
|
|
5886
|
+
const normalizedPath = normalizeInstallerPath(path);
|
|
5887
|
+
const normalizedParent = normalizeInstallerPath(parent);
|
|
5888
|
+
return normalizedPath === normalizedParent || normalizedPath.startsWith(`${normalizedParent}/`);
|
|
5889
|
+
}
|
|
5890
|
+
function normalizeInstallerPath(path) {
|
|
5891
|
+
return path.replace(/^\/private\/tmp\//, "/tmp/");
|
|
5892
|
+
}
|
|
5893
|
+
function inferInstallerFromInstallation(opts) {
|
|
5894
|
+
const candidatePaths = [opts.argv1, opts.realExecPath].filter((value) => !!value);
|
|
5895
|
+
if (opts.npmGlobalPrefix) {
|
|
5896
|
+
const npmPackageRoots = [
|
|
5897
|
+
join2(opts.npmGlobalPrefix, "node_modules", PACKAGE_NAME),
|
|
5898
|
+
join2(opts.npmGlobalPrefix, "lib", "node_modules", PACKAGE_NAME)
|
|
5899
|
+
];
|
|
5900
|
+
if (candidatePaths.some((path) => npmPackageRoots.some((root) => isUnderPath(path, root)))) {
|
|
5901
|
+
return "npm";
|
|
5902
|
+
}
|
|
5903
|
+
}
|
|
5904
|
+
if (opts.bunGlobalBin) {
|
|
5905
|
+
const bunGlobalBin = opts.bunGlobalBin;
|
|
5906
|
+
if (candidatePaths.some((path) => isUnderPath(path, bunGlobalBin))) {
|
|
5907
|
+
return "bun";
|
|
5908
|
+
}
|
|
5909
|
+
}
|
|
5910
|
+
return null;
|
|
5911
|
+
}
|
|
5912
|
+
function readCommandOutput(command, args) {
|
|
5913
|
+
try {
|
|
5914
|
+
return execFileSync2(command, args, {
|
|
5915
|
+
encoding: "utf8",
|
|
5916
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
5917
|
+
}).trim();
|
|
5918
|
+
} catch {
|
|
5919
|
+
return null;
|
|
5920
|
+
}
|
|
5921
|
+
}
|
|
5922
|
+
function inferInstaller() {
|
|
5923
|
+
const fromAgent = inferInstallerFromUserAgent(process.env.npm_config_user_agent ?? "");
|
|
5924
|
+
if (fromAgent)
|
|
5925
|
+
return fromAgent;
|
|
5926
|
+
const argv1 = process.argv[1];
|
|
5927
|
+
const realExecPath = argv1 ? readCommandOutput("realpath", [argv1]) ?? safeRealPath(argv1) : null;
|
|
5928
|
+
const npmGlobalPrefix = process.env.npm_config_prefix ?? readCommandOutput("npm", ["prefix", "-g"]);
|
|
5929
|
+
const bunGlobalBin = process.env.BUN_INSTALL ? join2(process.env.BUN_INSTALL, "bin") : readCommandOutput("bun", ["pm", "bin", "-g"]) ?? join2(homedir2(), ".bun", "bin");
|
|
5930
|
+
return inferInstallerFromInstallation({
|
|
5931
|
+
argv1,
|
|
5932
|
+
realExecPath,
|
|
5933
|
+
npmGlobalPrefix,
|
|
5934
|
+
bunGlobalBin
|
|
5935
|
+
});
|
|
5936
|
+
}
|
|
5937
|
+
function safeRealPath(filePath) {
|
|
5938
|
+
try {
|
|
5939
|
+
return realpathSync(filePath);
|
|
5940
|
+
} catch {
|
|
5941
|
+
return null;
|
|
5942
|
+
}
|
|
5943
|
+
}
|
|
5944
|
+
function formatUpdateCommand(installer = inferInstaller()) {
|
|
5945
|
+
switch (installer) {
|
|
5946
|
+
case "bun":
|
|
5947
|
+
return "bun add -g @outlit/cli";
|
|
5948
|
+
case "npm":
|
|
5949
|
+
return "npm install -g @outlit/cli";
|
|
5950
|
+
case "pnpm":
|
|
5951
|
+
return "pnpm add -g @outlit/cli";
|
|
5952
|
+
case "yarn":
|
|
5953
|
+
return "yarn global add @outlit/cli";
|
|
5954
|
+
default:
|
|
5955
|
+
return `update ${PACKAGE_NAME} with your package manager`;
|
|
5956
|
+
}
|
|
5957
|
+
}
|
|
5958
|
+
function getCachedUpdateNotice(state = readCachedUpdateState()) {
|
|
5959
|
+
if (!state?.latestVersion)
|
|
5960
|
+
return null;
|
|
5961
|
+
if (compareVersions(CLI_VERSION2, state.latestVersion) >= 0)
|
|
5962
|
+
return null;
|
|
5963
|
+
return {
|
|
5964
|
+
currentVersion: CLI_VERSION2,
|
|
5965
|
+
latestVersion: state.latestVersion,
|
|
5966
|
+
command: formatUpdateCommand(state.installer)
|
|
5967
|
+
};
|
|
5968
|
+
}
|
|
5969
|
+
function shouldCheckForUpdates() {
|
|
5970
|
+
if (process.env.OUTLIT_NO_UPDATE_NOTIFIER)
|
|
5971
|
+
return false;
|
|
5972
|
+
return isInteractive();
|
|
5973
|
+
}
|
|
5974
|
+
function shouldShowUpdateNotice(argv = process.argv) {
|
|
5975
|
+
return shouldCheckForUpdates() && !argv.includes("--json") && !argv.includes(INTERNAL_UPDATE_FLAG);
|
|
5976
|
+
}
|
|
5977
|
+
function printCachedUpdateNotice(argv = process.argv, notify = console.error) {
|
|
5978
|
+
if (!shouldShowUpdateNotice(argv))
|
|
5979
|
+
return false;
|
|
5980
|
+
const notice = getCachedUpdateNotice();
|
|
5981
|
+
if (!notice)
|
|
5982
|
+
return false;
|
|
5983
|
+
notify(`Outlit CLI update available: ${notice.currentVersion} -> ${notice.latestVersion}
|
|
5984
|
+
Update with: ${notice.command}`);
|
|
5985
|
+
return true;
|
|
5986
|
+
}
|
|
5987
|
+
function scheduleBackgroundUpdateCheck(argv = process.argv, spawnProcess = spawn) {
|
|
5988
|
+
if (!shouldShowUpdateNotice(argv))
|
|
5989
|
+
return false;
|
|
5990
|
+
if (!isUpdateCheckDue(readCachedUpdateState()))
|
|
5991
|
+
return false;
|
|
5992
|
+
const runtimePath = argv[0];
|
|
5993
|
+
const scriptPath = argv[1];
|
|
5994
|
+
if (!runtimePath || !scriptPath)
|
|
5995
|
+
return false;
|
|
5996
|
+
const child = spawnProcess(runtimePath, [scriptPath, INTERNAL_UPDATE_FLAG], {
|
|
5997
|
+
detached: true,
|
|
5998
|
+
stdio: "ignore"
|
|
5999
|
+
});
|
|
6000
|
+
child.unref?.();
|
|
6001
|
+
return true;
|
|
6002
|
+
}
|
|
6003
|
+
function initializeUpdateNotifier(opts) {
|
|
6004
|
+
const argv = opts?.argv ?? process.argv;
|
|
6005
|
+
printCachedUpdateNotice(argv, opts?.notify);
|
|
6006
|
+
scheduleBackgroundUpdateCheck(argv, opts?.spawn);
|
|
6007
|
+
}
|
|
6008
|
+
async function fetchLatestCliVersion() {
|
|
6009
|
+
const response = await fetch(LATEST_VERSION_URL, { signal: AbortSignal.timeout(5000) });
|
|
6010
|
+
if (!response.ok)
|
|
6011
|
+
throw new Error("registry unavailable");
|
|
6012
|
+
const data = await response.json();
|
|
6013
|
+
if (!data.version)
|
|
6014
|
+
throw new Error("registry returned no version");
|
|
6015
|
+
return data.version;
|
|
6016
|
+
}
|
|
6017
|
+
async function runInternalUpdateCheck(opts) {
|
|
6018
|
+
const fetchLatestVersion = opts?.fetchLatestVersion ?? fetchLatestCliVersion;
|
|
6019
|
+
const installer = opts?.installer ?? inferInstaller();
|
|
6020
|
+
try {
|
|
6021
|
+
const latestVersion = await fetchLatestVersion();
|
|
6022
|
+
writeCachedUpdateState({
|
|
6023
|
+
lastCheckedAt: Date.now(),
|
|
6024
|
+
latestVersion,
|
|
6025
|
+
...installer ? { installer } : {}
|
|
6026
|
+
});
|
|
6027
|
+
} catch {
|
|
6028
|
+
writeCachedUpdateState({
|
|
6029
|
+
lastCheckedAt: Date.now(),
|
|
6030
|
+
...installer ? { installer } : {}
|
|
6031
|
+
});
|
|
6032
|
+
}
|
|
6033
|
+
}
|
|
6034
|
+
|
|
5395
6035
|
// src/cli.ts
|
|
5396
6036
|
if (process.argv.includes("-v")) {
|
|
5397
6037
|
console.log(CLI_VERSION);
|
|
5398
6038
|
process.exit(0);
|
|
5399
6039
|
}
|
|
6040
|
+
if (process.argv.includes(INTERNAL_UPDATE_FLAG)) {
|
|
6041
|
+
await runInternalUpdateCheck();
|
|
6042
|
+
process.exit(0);
|
|
6043
|
+
}
|
|
6044
|
+
initializeUpdateNotifier();
|
|
5400
6045
|
var main = defineCommand({
|
|
5401
6046
|
meta: {
|
|
5402
6047
|
name: "outlit",
|
|
@@ -5408,8 +6053,10 @@ Usage examples:
|
|
|
5408
6053
|
outlit customers get acme.com --include users,revenue
|
|
5409
6054
|
outlit customers timeline acme.com --timeframe 90d
|
|
5410
6055
|
outlit users list --journey-stage CHAMPION
|
|
5411
|
-
outlit facts acme.com --
|
|
5412
|
-
outlit
|
|
6056
|
+
outlit facts list acme.com --source-types CALL --after 2025-01-01T00:00:00Z
|
|
6057
|
+
outlit facts get --fact-id fact_123 --include evidence
|
|
6058
|
+
outlit sources get --source-type CALL --source-id call_123
|
|
6059
|
+
outlit search 'pricing objections last quarter' --source-types CALL,EMAIL
|
|
5413
6060
|
outlit sql 'SELECT * FROM events LIMIT 10'
|
|
5414
6061
|
outlit schema events
|
|
5415
6062
|
outlit doctor --json
|
|
@@ -5421,13 +6068,15 @@ For AI agents: commands auto-output JSON when stdout is piped. No --json flag ne
|
|
|
5421
6068
|
customers: () => Promise.resolve().then(() => (init_customers(), exports_customers)).then((m) => m.default),
|
|
5422
6069
|
users: () => Promise.resolve().then(() => (init_users(), exports_users)).then((m) => m.default),
|
|
5423
6070
|
doctor: () => Promise.resolve().then(() => (init_doctor(), exports_doctor)).then((m) => m.default),
|
|
6071
|
+
upgrade: () => Promise.resolve().then(() => (init_upgrade(), exports_upgrade)).then((m) => m.default),
|
|
5424
6072
|
facts: () => Promise.resolve().then(() => (init_facts(), exports_facts)).then((m) => m.default),
|
|
6073
|
+
sources: () => Promise.resolve().then(() => (init_sources(), exports_sources)).then((m) => m.default),
|
|
5425
6074
|
search: () => Promise.resolve().then(() => (init_search(), exports_search)).then((m) => m.default),
|
|
5426
6075
|
sql: () => Promise.resolve().then(() => (init_sql(), exports_sql)).then((m) => m.default),
|
|
5427
6076
|
schema: () => Promise.resolve().then(() => (init_schema(), exports_schema)).then((m) => m.default),
|
|
5428
6077
|
integrations: () => Promise.resolve().then(() => (init_integrations(), exports_integrations)).then((m) => m.default),
|
|
5429
6078
|
completions: () => Promise.resolve().then(() => (init_completions(), exports_completions)).then((m) => m.default),
|
|
5430
|
-
setup: () => Promise.resolve().then(() => (
|
|
6079
|
+
setup: () => Promise.resolve().then(() => (init_setup2(), exports_setup)).then((m) => m.default)
|
|
5431
6080
|
}
|
|
5432
6081
|
});
|
|
5433
6082
|
runMain(main);
|