@dench.com/cli 3.5.8-staging.350 → 3.6.0-staging.356
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/README.md +65 -55
- package/app-sdk.d.ts +1286 -31
- package/apps.ts +1 -1
- package/campaign.ts +1949 -212
- package/crm.ts +21 -12
- package/cron.ts +6 -5
- package/dench.ts +76 -106
- package/fs-daemon.ts +6 -6
- package/image.ts +4 -4
- package/leads.ts +60 -22
- package/lib/api-schemas.ts +1094 -30
- package/lib/app-sdk-catalog.generated.ts +82 -6
- package/lib/app-sdk-surface.ts +240 -0
- package/lib/campaign-agent.ts +1564 -0
- package/lib/campaign-csv.ts +883 -0
- package/lib/campaign-filters.ts +141 -0
- package/lib/campaign-lines.ts +217 -0
- package/lib/campaign-steps.ts +721 -0
- package/lib/campaign-timeline.ts +189 -0
- package/lib/cli-version.ts +14 -0
- package/lib/command-registry.ts +491 -8
- package/lib/connection-source.ts +10 -0
- package/lib/enrichment-gateway.ts +11 -2
- package/lib/public-error.ts +41 -0
- package/lib/search-pricing.ts +9 -0
- package/package.json +1 -1
- package/search.ts +5 -34
- package/tools.ts +51 -42
- package/web.ts +1 -1
package/package.json
CHANGED
package/search.ts
CHANGED
|
@@ -108,8 +108,8 @@ function assertFlagsSupportedForCategory(
|
|
|
108
108
|
);
|
|
109
109
|
if (offenders.length === 0) return;
|
|
110
110
|
throw new SearchCliError(
|
|
111
|
-
`${offenders.join(", ")} has no effect on ${category} search —
|
|
112
|
-
"either rejects it or silently ignores it, so the results would not " +
|
|
111
|
+
`${offenders.join(", ")} has no effect on ${category} search — the ` +
|
|
112
|
+
"search either rejects it or silently ignores it, so the results would not " +
|
|
113
113
|
"match what you asked for. (Unsupported for " +
|
|
114
114
|
`${category}: ${[...unsupported].join(", ")}.) ` +
|
|
115
115
|
"Put those constraints in the query text instead, e.g. " +
|
|
@@ -194,12 +194,6 @@ function asString(value: unknown): string | undefined {
|
|
|
194
194
|
return typeof value === "string" ? value : undefined;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
function asNumber(value: unknown): number | undefined {
|
|
198
|
-
return typeof value === "number" && Number.isFinite(value)
|
|
199
|
-
? value
|
|
200
|
-
: undefined;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
197
|
function asObject(value: unknown): Record<string, unknown> | undefined {
|
|
204
198
|
return value && typeof value === "object" && !Array.isArray(value)
|
|
205
199
|
? (value as Record<string, unknown>)
|
|
@@ -229,11 +223,6 @@ function formatSearchResults(payload: unknown, limit?: number): string {
|
|
|
229
223
|
if (!root) return "(no results)";
|
|
230
224
|
const results = asArray(root.results);
|
|
231
225
|
const lines: string[] = [];
|
|
232
|
-
const auto = asString(root.autopromptString);
|
|
233
|
-
if (auto) {
|
|
234
|
-
lines.push(`Auto-prompt: ${auto}`);
|
|
235
|
-
lines.push("");
|
|
236
|
-
}
|
|
237
226
|
if (results.length === 0) {
|
|
238
227
|
lines.push("(no results)");
|
|
239
228
|
return lines.join("\n");
|
|
@@ -263,10 +252,6 @@ function formatSearchResults(payload: unknown, limit?: number): string {
|
|
|
263
252
|
if (snippet) lines.push(` ${trimSnippet(snippet, 240)}`);
|
|
264
253
|
lines.push("");
|
|
265
254
|
}
|
|
266
|
-
const cost = asNumber(asObject(root.costDollars)?.total);
|
|
267
|
-
if (cost !== undefined) {
|
|
268
|
-
lines.push(`Cost (USD): $${cost.toFixed(4)}`);
|
|
269
|
-
}
|
|
270
255
|
return lines.join("\n").trimEnd();
|
|
271
256
|
}
|
|
272
257
|
|
|
@@ -278,11 +263,6 @@ function formatSearchResults(payload: unknown, limit?: number): string {
|
|
|
278
263
|
function formatPeopleResults(payload: unknown, limit?: number): string {
|
|
279
264
|
const hits = parseExaPeopleResults(payload);
|
|
280
265
|
const lines: string[] = [];
|
|
281
|
-
const auto = asString(asObject(payload)?.autopromptString);
|
|
282
|
-
if (auto) {
|
|
283
|
-
lines.push(`Auto-prompt: ${auto}`);
|
|
284
|
-
lines.push("");
|
|
285
|
-
}
|
|
286
266
|
if (hits.length === 0) {
|
|
287
267
|
lines.push("(no people found)");
|
|
288
268
|
return lines.join("\n");
|
|
@@ -301,8 +281,6 @@ function formatPeopleResults(payload: unknown, limit?: number): string {
|
|
|
301
281
|
if (hit.url) lines.push(` ${hit.url}`);
|
|
302
282
|
lines.push("");
|
|
303
283
|
}
|
|
304
|
-
const cost = asNumber(asObject(asObject(payload)?.costDollars)?.total);
|
|
305
|
-
if (cost !== undefined) lines.push(`Cost (USD): $${cost.toFixed(4)}`);
|
|
306
284
|
return lines.join("\n").trimEnd();
|
|
307
285
|
}
|
|
308
286
|
|
|
@@ -314,11 +292,6 @@ function formatPeopleResults(payload: unknown, limit?: number): string {
|
|
|
314
292
|
function formatCompanyResults(payload: unknown, limit?: number): string {
|
|
315
293
|
const hits = parseExaCompanyResults(payload);
|
|
316
294
|
const lines: string[] = [];
|
|
317
|
-
const auto = asString(asObject(payload)?.autopromptString);
|
|
318
|
-
if (auto) {
|
|
319
|
-
lines.push(`Auto-prompt: ${auto}`);
|
|
320
|
-
lines.push("");
|
|
321
|
-
}
|
|
322
295
|
if (hits.length === 0) {
|
|
323
296
|
lines.push("(no companies found)");
|
|
324
297
|
return lines.join("\n");
|
|
@@ -355,8 +328,6 @@ function formatCompanyResults(payload: unknown, limit?: number): string {
|
|
|
355
328
|
}
|
|
356
329
|
lines.push("");
|
|
357
330
|
}
|
|
358
|
-
const cost = asNumber(asObject(asObject(payload)?.costDollars)?.total);
|
|
359
|
-
if (cost !== undefined) lines.push(`Cost (USD): $${cost.toFixed(4)}`);
|
|
360
331
|
return lines.join("\n").trimEnd();
|
|
361
332
|
}
|
|
362
333
|
|
|
@@ -550,7 +521,7 @@ async function runAnswerSubcommand(ctx: SearchCliContext): Promise<void> {
|
|
|
550
521
|
function searchHelp(): void {
|
|
551
522
|
console.log(`Usage: dench search <subcommand>
|
|
552
523
|
|
|
553
|
-
Live web access through the Dench Cloud Gateway
|
|
524
|
+
Live web access through the Dench Cloud Gateway. Auths
|
|
554
525
|
with DENCH_API_KEY or the active \`dench signin\` agent session. Agent
|
|
555
526
|
sessions require a paid workspace.
|
|
556
527
|
|
|
@@ -582,10 +553,10 @@ Find people or companies (--category people|company):
|
|
|
582
553
|
published-date filters work with neither. Passing one that does not
|
|
583
554
|
apply is refused rather than silently ignored.
|
|
584
555
|
|
|
585
|
-
Deep-read one or more URLs
|
|
556
|
+
Deep-read one or more URLs:
|
|
586
557
|
dench search contents <url> [<url>...] [--max-chars 4000] [--summary "..."] [--json]
|
|
587
558
|
|
|
588
|
-
One-shot synthesised answer with citations
|
|
559
|
+
One-shot synthesised answer with citations:
|
|
589
560
|
dench search answer "<query>" [--json]
|
|
590
561
|
|
|
591
562
|
Environment variables:
|
package/tools.ts
CHANGED
|
@@ -53,11 +53,17 @@ import {
|
|
|
53
53
|
parseJson,
|
|
54
54
|
shift as shiftRaw,
|
|
55
55
|
} from "./lib/cli-args";
|
|
56
|
+
import {
|
|
57
|
+
type ConnectionSource,
|
|
58
|
+
connectionSource,
|
|
59
|
+
} from "./lib/connection-source";
|
|
56
60
|
import {
|
|
57
61
|
normalizeUnipileToolkitSlug,
|
|
58
62
|
unipileConnectKindFromToolkitSlug,
|
|
59
63
|
} from "./lib/unipile-toolkits";
|
|
60
64
|
|
|
65
|
+
export { type ConnectionSource, connectionSource };
|
|
66
|
+
|
|
61
67
|
// ---------------------------------------------------------------------------
|
|
62
68
|
// Public dispatcher
|
|
63
69
|
// ---------------------------------------------------------------------------
|
|
@@ -240,15 +246,15 @@ export async function fetchConnectedAppsSummary(
|
|
|
240
246
|
available: boolean;
|
|
241
247
|
count: number;
|
|
242
248
|
connections: CompactConnection[];
|
|
243
|
-
|
|
244
|
-
|
|
249
|
+
nativeAvailable: boolean;
|
|
250
|
+
nativeError?: string;
|
|
245
251
|
error?: string;
|
|
246
252
|
reason?: string;
|
|
247
253
|
}> {
|
|
248
254
|
const unipile = await fetchUnipileConnections(ctx);
|
|
249
255
|
const unipileFields = {
|
|
250
|
-
|
|
251
|
-
...(unipile.error ? {
|
|
256
|
+
nativeAvailable: unipile.available,
|
|
257
|
+
...(unipile.error ? { nativeError: unipile.error } : {}),
|
|
252
258
|
};
|
|
253
259
|
if (ctx.gatewayAuthError) {
|
|
254
260
|
return {
|
|
@@ -310,8 +316,8 @@ async function runStatusSubcommand(ctx: ToolCliContext): Promise<void> {
|
|
|
310
316
|
available: unipile.available,
|
|
311
317
|
count: unipile.connections.length,
|
|
312
318
|
connections: unipile.connections,
|
|
313
|
-
|
|
314
|
-
...(unipile.error ? {
|
|
319
|
+
nativeAvailable: unipile.available,
|
|
320
|
+
...(unipile.error ? { nativeError: unipile.error } : {}),
|
|
315
321
|
};
|
|
316
322
|
} else {
|
|
317
323
|
connectionsSummary = await fetchConnectedAppsSummary(ctx);
|
|
@@ -339,14 +345,14 @@ async function runStatusSubcommand(ctx: ToolCliContext): Promise<void> {
|
|
|
339
345
|
: allConnections;
|
|
340
346
|
|
|
341
347
|
const summary = {
|
|
342
|
-
ok: unipileToolkit ? connectionsSummary.
|
|
348
|
+
ok: unipileToolkit ? connectionsSummary.nativeAvailable : true,
|
|
343
349
|
available: connectionsSummary.available,
|
|
344
350
|
toolkit: filterToolkit ?? null,
|
|
345
351
|
count: filteredConnections.length,
|
|
346
352
|
connections: filteredConnections,
|
|
347
|
-
|
|
348
|
-
...(connectionsSummary.
|
|
349
|
-
? {
|
|
353
|
+
nativeAvailable: connectionsSummary.nativeAvailable,
|
|
354
|
+
...(connectionsSummary.nativeError
|
|
355
|
+
? { nativeError: connectionsSummary.nativeError }
|
|
350
356
|
: {}),
|
|
351
357
|
...(connectionsSummary.error ? { error: connectionsSummary.error } : {}),
|
|
352
358
|
...(connectionsSummary.reason ? { reason: connectionsSummary.reason } : {}),
|
|
@@ -409,8 +415,8 @@ async function runSearchSubcommand(ctx: ToolCliContext): Promise<void> {
|
|
|
409
415
|
),
|
|
410
416
|
...unipile.tools,
|
|
411
417
|
],
|
|
412
|
-
|
|
413
|
-
...(unipile.error ? {
|
|
418
|
+
nativeAvailable: unipile.available,
|
|
419
|
+
...(unipile.error ? { nativeError: unipile.error } : {}),
|
|
414
420
|
};
|
|
415
421
|
|
|
416
422
|
if (ctx.jsonOutput) {
|
|
@@ -519,7 +525,12 @@ async function fetchUnipileTools(
|
|
|
519
525
|
available: true,
|
|
520
526
|
tools: rows
|
|
521
527
|
.map((row) => asRecord(row))
|
|
522
|
-
.filter((row): row is JsonRecord => row !== undefined)
|
|
528
|
+
.filter((row): row is JsonRecord => row !== undefined)
|
|
529
|
+
.map((row) =>
|
|
530
|
+
typeof row.source === "string"
|
|
531
|
+
? { ...row, source: connectionSource(row.source, "dench") }
|
|
532
|
+
: row,
|
|
533
|
+
),
|
|
523
534
|
};
|
|
524
535
|
} catch (error) {
|
|
525
536
|
return { available: false, tools: [], error: errorMessage(error) };
|
|
@@ -530,7 +541,7 @@ async function runRunSubcommand(ctx: ToolCliContext): Promise<void> {
|
|
|
530
541
|
const toolSlug = ctx.args[0];
|
|
531
542
|
if (!toolSlug || toolSlug.startsWith("--")) {
|
|
532
543
|
throw new ToolCliError(
|
|
533
|
-
'Usage: dench tool run <
|
|
544
|
+
'Usage: dench tool run <tool_slug> [--args \'{"key":"value"}\'] [--account <connectedAccountId>] [--json]',
|
|
534
545
|
);
|
|
535
546
|
}
|
|
536
547
|
ctx.args.shift();
|
|
@@ -659,7 +670,7 @@ async function runSlackConnectSubcommand(
|
|
|
659
670
|
redirectUrl,
|
|
660
671
|
message,
|
|
661
672
|
note:
|
|
662
|
-
"Slack is Dench's in-house integration
|
|
673
|
+
"Slack is Dench's in-house integration. One install powers " +
|
|
663
674
|
"both the Slack messaging channel and the agent SLACK_* tools " +
|
|
664
675
|
"(SLACK_SEND_MESSAGE, SLACK_FETCH_HISTORY, …).",
|
|
665
676
|
};
|
|
@@ -669,7 +680,7 @@ async function runSlackConnectSubcommand(
|
|
|
669
680
|
}
|
|
670
681
|
console.log(message);
|
|
671
682
|
console.log(
|
|
672
|
-
"Slack is Dench's in-house integration
|
|
683
|
+
"Slack is Dench's in-house integration. Once an admin installs it,",
|
|
673
684
|
);
|
|
674
685
|
console.log(
|
|
675
686
|
"run tools with `dench tool run SLACK_SEND_MESSAGE --args '{…}'` — see `dench tool search --toolkit slack`.",
|
|
@@ -699,7 +710,7 @@ async function runConnectSubcommand(ctx: ToolCliContext): Promise<void> {
|
|
|
699
710
|
}
|
|
700
711
|
if (ctx.args.includes("--callback-url")) {
|
|
701
712
|
throw new ToolCliError(
|
|
702
|
-
"
|
|
713
|
+
"Dench-connected accounts use Dench's managed callback. --callback-url is only supported for connected apps.",
|
|
703
714
|
);
|
|
704
715
|
}
|
|
705
716
|
const result = asRecord(
|
|
@@ -717,7 +728,7 @@ async function runConnectSubcommand(ctx: ToolCliContext): Promise<void> {
|
|
|
717
728
|
);
|
|
718
729
|
const redirectUrl = stringField(result, "link");
|
|
719
730
|
if (!redirectUrl) {
|
|
720
|
-
throw new ToolCliError("
|
|
731
|
+
throw new ToolCliError("Dench did not return a connection link.");
|
|
721
732
|
}
|
|
722
733
|
const message = `Connect ${toolkit} here: ${redirectUrl}`;
|
|
723
734
|
if (ctx.jsonOutput) {
|
|
@@ -725,7 +736,7 @@ async function runConnectSubcommand(ctx: ToolCliContext): Promise<void> {
|
|
|
725
736
|
JSON.stringify(
|
|
726
737
|
{
|
|
727
738
|
ok: true,
|
|
728
|
-
source: "
|
|
739
|
+
source: "dench",
|
|
729
740
|
toolkit: normalizeUnipileToolkitSlug(toolkit),
|
|
730
741
|
redirectUrl,
|
|
731
742
|
expiresAt: result?.expiresAt,
|
|
@@ -845,9 +856,7 @@ class GatewayHttpError extends ToolCliError {
|
|
|
845
856
|
constructor(args: { status: number; body: string; path: string }) {
|
|
846
857
|
const truncated =
|
|
847
858
|
args.body.length > 500 ? `${args.body.slice(0, 500)}…` : args.body;
|
|
848
|
-
super(
|
|
849
|
-
`Gateway ${args.path} returned ${args.status}: ${truncated || "(empty)"}`,
|
|
850
|
-
);
|
|
859
|
+
super(`Dench gateway error (${args.status}): ${truncated || "(empty)"}`);
|
|
851
860
|
this.name = "GatewayHttpError";
|
|
852
861
|
this.status = args.status;
|
|
853
862
|
this.body = args.body;
|
|
@@ -1093,12 +1102,12 @@ function extractToolkits(payload: unknown): JsonRecord[] {
|
|
|
1093
1102
|
}
|
|
1094
1103
|
|
|
1095
1104
|
/**
|
|
1096
|
-
* The merged row shape. `source` is the discriminator: `
|
|
1105
|
+
* The merged row shape. `source` is the discriminator: `app` rows carry a
|
|
1097
1106
|
* routable `connectedAccountId` (usable as `dench tool run --account`), while
|
|
1098
|
-
* `
|
|
1107
|
+
* `dench` rows never do — their account id is an internal credential.
|
|
1099
1108
|
*/
|
|
1100
1109
|
export type CompactConnection = {
|
|
1101
|
-
source:
|
|
1110
|
+
source: ConnectionSource;
|
|
1102
1111
|
toolkit: string;
|
|
1103
1112
|
status: string;
|
|
1104
1113
|
connectedAccountId: string | null;
|
|
@@ -1115,7 +1124,7 @@ export type CompactConnection = {
|
|
|
1115
1124
|
|
|
1116
1125
|
function compactConnection(connection: JsonRecord): CompactConnection {
|
|
1117
1126
|
return {
|
|
1118
|
-
source: "
|
|
1127
|
+
source: connectionSource(connection.source, "app"),
|
|
1119
1128
|
toolkit:
|
|
1120
1129
|
stringField(connection, "toolkit_slug", "toolkit") ??
|
|
1121
1130
|
stringField(asRecord(connection.toolkit), "slug", "name") ??
|
|
@@ -1135,7 +1144,7 @@ function compactConnection(connection: JsonRecord): CompactConnection {
|
|
|
1135
1144
|
|
|
1136
1145
|
function compactUnipileConnection(connection: JsonRecord): CompactConnection {
|
|
1137
1146
|
return {
|
|
1138
|
-
source: "
|
|
1147
|
+
source: connectionSource(connection.source, "dench"),
|
|
1139
1148
|
toolkit: stringField(connection, "toolkit") ?? "unknown",
|
|
1140
1149
|
status: stringField(connection, "status") ?? "unknown",
|
|
1141
1150
|
connectedAccountId: null,
|
|
@@ -1153,11 +1162,11 @@ function formatConnectionLine(connection: CompactConnection): string {
|
|
|
1153
1162
|
: "";
|
|
1154
1163
|
// "via Dench" both names the broker and explains why the row has no
|
|
1155
1164
|
// connected-account id to pass to `dench tool run`.
|
|
1156
|
-
const via = connection.source === "
|
|
1165
|
+
const via = connection.source === "dench" ? " via Dench" : "";
|
|
1157
1166
|
// Whose mailbox/LinkedIn it is only matters when it is not this agent's —
|
|
1158
1167
|
// `dench email --mailbox` picks between them.
|
|
1159
1168
|
const owner =
|
|
1160
|
-
connection.source === "
|
|
1169
|
+
connection.source === "dench" &&
|
|
1161
1170
|
connection.isOwner === false &&
|
|
1162
1171
|
connection.ownerName
|
|
1163
1172
|
? ` · ${connection.ownerName}`
|
|
@@ -1172,8 +1181,8 @@ function formatStatusSummary(summary: {
|
|
|
1172
1181
|
toolkit: string | null;
|
|
1173
1182
|
count: number;
|
|
1174
1183
|
connections: CompactConnection[];
|
|
1175
|
-
|
|
1176
|
-
|
|
1184
|
+
nativeAvailable?: boolean;
|
|
1185
|
+
nativeError?: string;
|
|
1177
1186
|
reason?: string;
|
|
1178
1187
|
error?: string;
|
|
1179
1188
|
}): string {
|
|
@@ -1190,16 +1199,16 @@ function formatStatusSummary(summary: {
|
|
|
1190
1199
|
}
|
|
1191
1200
|
// Say so rather than silently listing Composio only — otherwise a connected
|
|
1192
1201
|
// calendar reads as absent, which is the failure this merge exists to fix.
|
|
1193
|
-
if (summary.
|
|
1202
|
+
if (summary.nativeAvailable === false) {
|
|
1194
1203
|
lines.push(
|
|
1195
1204
|
` (could not check Gmail/Outlook/Calendar/LinkedIn: ${
|
|
1196
|
-
summary.
|
|
1205
|
+
summary.nativeError ?? "unknown error"
|
|
1197
1206
|
})`,
|
|
1198
1207
|
);
|
|
1199
1208
|
}
|
|
1200
1209
|
if (summary.reason || summary.error) {
|
|
1201
1210
|
lines.push(
|
|
1202
|
-
` (could not check
|
|
1211
|
+
` (could not check connected apps: ${summary.reason ?? summary.error})`,
|
|
1203
1212
|
);
|
|
1204
1213
|
}
|
|
1205
1214
|
return lines.join("\n");
|
|
@@ -1234,8 +1243,8 @@ function formatSearchResult(searchResult: unknown, compact = false): string {
|
|
|
1234
1243
|
return [
|
|
1235
1244
|
"No matching tools found.",
|
|
1236
1245
|
"",
|
|
1237
|
-
"`dench tool search` is a KEYWORD search over
|
|
1238
|
-
"
|
|
1246
|
+
"`dench tool search` is a KEYWORD search over tool names and",
|
|
1247
|
+
"descriptions, not a semantic / natural-language search.",
|
|
1239
1248
|
"Retry with one or two concrete tokens that likely appear in the",
|
|
1240
1249
|
'tool slug or its docs ("fetch emails", "send message", "create',
|
|
1241
1250
|
'issue", "list channels"). Drop filter words like "today" /',
|
|
@@ -1361,18 +1370,18 @@ Usage:
|
|
|
1361
1370
|
|
|
1362
1371
|
Notes:
|
|
1363
1372
|
All commands authenticate with DENCH_API_KEY or the active \`dench signin\`
|
|
1364
|
-
agent session.
|
|
1373
|
+
agent session. Connected-app commands use paid-workspace gateway credentials.
|
|
1365
1374
|
Native Gmail/Outlook/Calendar/LinkedIn connect/status need no gateway key;
|
|
1366
1375
|
connect requires a workspace member or a member-owned Dench API key.
|
|
1367
|
-
Results carry a "source". "
|
|
1368
|
-
rows (gmail, outlook, calendar, linkedin)
|
|
1369
|
-
|
|
1376
|
+
Results carry a "source". "app" rows are third-party connected apps; "dench"
|
|
1377
|
+
rows (gmail, outlook, calendar, linkedin, slack) are connected by Dench
|
|
1378
|
+
itself. ALL of them run through \`dench tool run\` with the
|
|
1370
1379
|
same slug + --args contract. \`dench tool connect slack\` prints the in-house
|
|
1371
1380
|
Slack install URL (org admin, one click). For gmail/outlook/calendar/linkedin,
|
|
1372
|
-
connect prints a
|
|
1381
|
+
connect prints a Dench sign-in link using the web app's configuration.
|
|
1373
1382
|
Sign in as a workspace member and open the link to authorize the account.
|
|
1374
1383
|
Calendar status accepts calendar, google-calendar, or outlook-calendar.
|
|
1375
|
-
Other toolkits connect
|
|
1384
|
+
Other toolkits connect as connected apps; --callback-url applies only to them.
|
|
1376
1385
|
Slack is ALWAYS in-house: SLACK_* slugs (SLACK_SEND_MESSAGE with Block Kit
|
|
1377
1386
|
blocks/buttons, SLACK_FETCH_HISTORY, SLACK_LIST_CHANNELS, …) run through the
|
|
1378
1387
|
org's own Slack app install and can post to / read any channel.
|
package/web.ts
CHANGED
|
@@ -144,7 +144,7 @@ through the Dench gateway. Prefer these over writing your own scraper.
|
|
|
144
144
|
dench web brand-search <query> [--json]
|
|
145
145
|
|
|
146
146
|
Crawl defaults to 15 pages and is hard-capped at 50. Search stays on
|
|
147
|
-
\`dench search
|
|
147
|
+
\`dench search\`. \`dench context\` is workspace orientation, not this.
|
|
148
148
|
`);
|
|
149
149
|
}
|
|
150
150
|
|