@eliya-oss/agent-slack 0.1.12 → 0.1.14
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/.agents/cli-api.md +22 -3
- package/CHANGELOG.md +19 -0
- package/dist/main.js +208 -121
- package/package.json +1 -1
package/.agents/cli-api.md
CHANGED
|
@@ -22,7 +22,8 @@ Non-goal for v0: agent-side summarization. The CLI returns clean context; agents
|
|
|
22
22
|
## Global Flags
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
agent-slack [--
|
|
25
|
+
agent-slack [--version] [--help]
|
|
26
|
+
[--profile NAME] [--team TEAM_ID] [--token user|bot|admin|app]
|
|
26
27
|
[--json] [--format json|ndjson|table] [--pretty] [--full]
|
|
27
28
|
[--fields FIELD[,FIELD...]]
|
|
28
29
|
[--limit N] [--cursor CURSOR] [--all]
|
|
@@ -35,6 +36,7 @@ Defaults:
|
|
|
35
36
|
- `--token user` for user-visible data.
|
|
36
37
|
- `--format json` when stdout is not a TTY.
|
|
37
38
|
- `--limit` uses Slack's method default unless a command defines a smaller agent-safe default.
|
|
39
|
+
- `--version` prints the CLI version as a bare line and exits `0`. `--help` prints the command catalog.
|
|
38
40
|
|
|
39
41
|
## Auth
|
|
40
42
|
|
|
@@ -116,6 +118,8 @@ agent-slack conversation context CHANNEL_ID [--since 24h] [--include users,threa
|
|
|
116
118
|
|
|
117
119
|
`conversation context` returns normalized messages, hydrated users, thread refs, file refs, reactions, and permalinks in one deterministic payload for agents.
|
|
118
120
|
|
|
121
|
+
`conversation list`, `conversation history`, and `conversation context` accept `--all` to auto-paginate every page, plus `--types`/`--limit` where relevant. These flags are advertised in `describe --json` and `<command> --help` so agents can discover them; without `--all` a large list returns only the first page with `paging.has_more: true`.
|
|
122
|
+
|
|
119
123
|
### Threads and messages
|
|
120
124
|
|
|
121
125
|
```bash
|
|
@@ -205,8 +209,9 @@ normalization and returns the raw Slack objects.
|
|
|
205
209
|
`tz`, and team fields.
|
|
206
210
|
- **file**: `id`, `name`, `mimetype`, `size`, and `permalink` when present.
|
|
207
211
|
Drops thumbnails and private URLs.
|
|
208
|
-
- **conversation**: `id`, `name`, `is_private`, `is_archived`, `
|
|
209
|
-
`purpose`, `num_members` when present.
|
|
212
|
+
- **conversation**: `id`, `name`, `is_private`, `is_archived`, `is_member`,
|
|
213
|
+
`topic`, `purpose`, `num_members` when present. `is_member` is kept as an
|
|
214
|
+
explicit boolean so an agent can tell membership from a list.
|
|
210
215
|
- `conversation context` dedupes thread roots already present in `messages` and
|
|
211
216
|
hydrates every unique author, including those who appear only in replies.
|
|
212
217
|
|
|
@@ -240,6 +245,17 @@ NDJSON streaming record:
|
|
|
240
245
|
{"ok":true,"type":"slack.message","team_id":"T123","channel_id":"C123","ts":"1710000000.000100","data":{}}
|
|
241
246
|
```
|
|
242
247
|
|
|
248
|
+
NDJSON enrichment records: when `--include` is combined with `--format ndjson`,
|
|
249
|
+
the hydration maps that `--json` returns under `data.users`/`data.threads`/`data.permalinks`
|
|
250
|
+
are streamed as typed records after the message lines, so the streaming mode is
|
|
251
|
+
not lossy. Message lines stay bare; enrichment lines carry a `type`:
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{"type":"slack.user","data":{"id":"U123","name":"ada","real_name":"Ada"}}
|
|
255
|
+
{"type":"slack.thread","data":{"ts":"1710000000.000100","replies":[]}}
|
|
256
|
+
{"type":"slack.permalink","data":{"ts":"1710000000.000100","permalink":"https://slack.com/..."}}
|
|
257
|
+
```
|
|
258
|
+
|
|
243
259
|
Structured error on stderr:
|
|
244
260
|
|
|
245
261
|
```json
|
|
@@ -287,6 +303,9 @@ Schema output includes:
|
|
|
287
303
|
|
|
288
304
|
- command description and examples
|
|
289
305
|
- positional args and flags
|
|
306
|
+
- `dataKey`: the key under the response envelope's `data` that holds the
|
|
307
|
+
command's primary payload (for example `conversation list` reports
|
|
308
|
+
`dataKey: "channels"`, so the array is at `data.channels`, not `data`)
|
|
290
309
|
- payload schema when known
|
|
291
310
|
- required Slack method/scopes
|
|
292
311
|
- output schema
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @eliya-oss/agent-slack
|
|
2
2
|
|
|
3
|
+
## 0.1.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d856e3b: Two agent-facing discoverability improvements.
|
|
8
|
+
|
|
9
|
+
- `describe --json` and `<command> --help --json` now report a `dataKey` for each command: the key under the response envelope's `data` that holds the primary payload (for example `conversation list` reports `dataKey: "channels"`, so results are at `data.channels`). Agents no longer have to probe the response shape.
|
|
10
|
+
- Conversation results now keep `is_member` as an explicit boolean, so an agent can tell which channels the active token has joined directly from `conversation list`.
|
|
11
|
+
|
|
12
|
+
## 0.1.13
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 48d5879: Three CLI fixes for agents.
|
|
17
|
+
|
|
18
|
+
- `agent-slack --version` now prints the version and exits 0 instead of raising a usage error.
|
|
19
|
+
- `conversation list`, `conversation history`, and `conversation context` now advertise their pagination flags (`--all`, `--types`, `--limit`) in `describe --json` and `--help`, so agents can discover `--all` instead of only getting the first page.
|
|
20
|
+
- `--include users,threads,permalinks` now works with `--format ndjson`: the hydrated users, threads, and permalinks are streamed as typed records (`slack.user`, `slack.thread`, `slack.permalink`) after the message lines. Previously they were only present with `--json` and silently dropped in ndjson.
|
|
21
|
+
|
|
3
22
|
## 0.1.12
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/main.js
CHANGED
|
@@ -25105,6 +25105,7 @@ const booleanFlags = /* @__PURE__ */ new Set([
|
|
|
25105
25105
|
"all",
|
|
25106
25106
|
"allow-write",
|
|
25107
25107
|
"help",
|
|
25108
|
+
"version",
|
|
25108
25109
|
"json",
|
|
25109
25110
|
"no-color",
|
|
25110
25111
|
"raw",
|
|
@@ -25521,9 +25522,143 @@ const pad = (value, width) => value + " ".repeat(Math.max(0, width - value.lengt
|
|
|
25521
25522
|
const widthFor = (column) => column === "text" ? 72 : 24;
|
|
25522
25523
|
const truncate = (value, width) => value.length > width ? `${value.slice(0, Math.max(0, width - 3))}...` : value;
|
|
25523
25524
|
//#endregion
|
|
25525
|
+
//#region src/output/normalize.ts
|
|
25526
|
+
const isRec = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25527
|
+
const asArray = (value) => Array.isArray(value) ? value : [];
|
|
25528
|
+
const str = (record, key) => typeof record[key] === "string" && record[key].length > 0 ? record[key] : void 0;
|
|
25529
|
+
const slimFile = (input) => {
|
|
25530
|
+
if (!isRec(input)) return input;
|
|
25531
|
+
const out = {
|
|
25532
|
+
id: input.id,
|
|
25533
|
+
name: input.name
|
|
25534
|
+
};
|
|
25535
|
+
if (typeof input.mimetype === "string") out.mimetype = input.mimetype;
|
|
25536
|
+
if (typeof input.size === "number") out.size = input.size;
|
|
25537
|
+
const permalink = str(input, "permalink");
|
|
25538
|
+
if (permalink) out.permalink = permalink;
|
|
25539
|
+
return out;
|
|
25540
|
+
};
|
|
25541
|
+
const slimMessage = (input) => {
|
|
25542
|
+
if (!isRec(input)) return input;
|
|
25543
|
+
const m = input;
|
|
25544
|
+
const out = {};
|
|
25545
|
+
if (typeof m.user === "string") out.user = m.user;
|
|
25546
|
+
else if (typeof m.bot_id === "string") out.bot_id = m.bot_id;
|
|
25547
|
+
const username = str(m, "username");
|
|
25548
|
+
if (username) out.username = username;
|
|
25549
|
+
const subtype = str(m, "subtype");
|
|
25550
|
+
if (subtype) out.subtype = subtype;
|
|
25551
|
+
if (typeof m.ts === "string") out.ts = m.ts;
|
|
25552
|
+
out.text = typeof m.text === "string" ? m.text : "";
|
|
25553
|
+
if (typeof m.thread_ts === "string" && m.thread_ts !== m.ts) out.thread_ts = m.thread_ts;
|
|
25554
|
+
if (typeof m.reply_count === "number") out.reply_count = m.reply_count;
|
|
25555
|
+
const reactions = asArray(m.reactions).filter(isRec).map((r) => ({
|
|
25556
|
+
name: r.name,
|
|
25557
|
+
count: r.count
|
|
25558
|
+
}));
|
|
25559
|
+
if (reactions.length > 0) out.reactions = reactions;
|
|
25560
|
+
const files = asArray(m.files).map(slimFile);
|
|
25561
|
+
if (files.length > 0) out.files = files;
|
|
25562
|
+
if (m.edited !== void 0 && m.edited !== null) out.edited = true;
|
|
25563
|
+
return out;
|
|
25564
|
+
};
|
|
25565
|
+
const slimUser = (input) => {
|
|
25566
|
+
if (!isRec(input)) return input;
|
|
25567
|
+
const u = input;
|
|
25568
|
+
const profile = isRec(u.profile) ? u.profile : {};
|
|
25569
|
+
const out = {
|
|
25570
|
+
id: u.id,
|
|
25571
|
+
name: u.name
|
|
25572
|
+
};
|
|
25573
|
+
const real = str(profile, "display_name") ?? str(u, "real_name") ?? str(profile, "real_name");
|
|
25574
|
+
if (real) out.real_name = real;
|
|
25575
|
+
if (u.is_bot === true) out.is_bot = true;
|
|
25576
|
+
if (u.deleted === true) out.deleted = true;
|
|
25577
|
+
const title = str(profile, "title");
|
|
25578
|
+
if (title) out.title = title;
|
|
25579
|
+
return out;
|
|
25580
|
+
};
|
|
25581
|
+
const slimConversation = (input) => {
|
|
25582
|
+
if (!isRec(input)) return input;
|
|
25583
|
+
const c = input;
|
|
25584
|
+
const out = {
|
|
25585
|
+
id: c.id,
|
|
25586
|
+
name: c.name
|
|
25587
|
+
};
|
|
25588
|
+
if (c.is_private === true) out.is_private = true;
|
|
25589
|
+
if (c.is_archived === true) out.is_archived = true;
|
|
25590
|
+
if (c.is_im === true) out.is_im = true;
|
|
25591
|
+
if (c.is_mpim === true) out.is_mpim = true;
|
|
25592
|
+
if (typeof c.is_member === "boolean") out.is_member = c.is_member;
|
|
25593
|
+
const topic = isRec(c.topic) ? str(c.topic, "value") : void 0;
|
|
25594
|
+
if (topic) out.topic = topic;
|
|
25595
|
+
const purpose = isRec(c.purpose) ? str(c.purpose, "value") : void 0;
|
|
25596
|
+
if (purpose) out.purpose = purpose;
|
|
25597
|
+
if (typeof c.num_members === "number") out.num_members = c.num_members;
|
|
25598
|
+
return out;
|
|
25599
|
+
};
|
|
25600
|
+
const slimTeam = (input) => {
|
|
25601
|
+
if (!isRec(input)) return input;
|
|
25602
|
+
const t = input;
|
|
25603
|
+
const out = {
|
|
25604
|
+
id: t.id,
|
|
25605
|
+
name: t.name
|
|
25606
|
+
};
|
|
25607
|
+
const domain = str(t, "domain");
|
|
25608
|
+
if (domain) out.domain = domain;
|
|
25609
|
+
const emailDomain = str(t, "email_domain");
|
|
25610
|
+
if (emailDomain) out.email_domain = emailDomain;
|
|
25611
|
+
const enterpriseId = str(t, "enterprise_id");
|
|
25612
|
+
if (enterpriseId) out.enterprise_id = enterpriseId;
|
|
25613
|
+
const enterpriseName = str(t, "enterprise_name");
|
|
25614
|
+
if (enterpriseName) out.enterprise_name = enterpriseName;
|
|
25615
|
+
return out;
|
|
25616
|
+
};
|
|
25617
|
+
const stripResponseEnvelope = (response) => {
|
|
25618
|
+
const { ok, response_metadata, ...rest } = response;
|
|
25619
|
+
return rest;
|
|
25620
|
+
};
|
|
25621
|
+
const dataKeyFor = (method) => {
|
|
25622
|
+
switch (method) {
|
|
25623
|
+
case "conversations.history":
|
|
25624
|
+
case "conversations.replies": return "messages";
|
|
25625
|
+
case "conversations.info": return "channel";
|
|
25626
|
+
case "conversations.list": return "channels";
|
|
25627
|
+
case "conversations.members": return "members";
|
|
25628
|
+
case "users.info":
|
|
25629
|
+
case "users.lookupByEmail": return "user";
|
|
25630
|
+
case "users.list": return "users";
|
|
25631
|
+
case "files.info": return "file";
|
|
25632
|
+
case "files.list": return "files";
|
|
25633
|
+
case "team.info": return "team";
|
|
25634
|
+
default: return;
|
|
25635
|
+
}
|
|
25636
|
+
};
|
|
25637
|
+
const normalizeResponse = (method, response) => {
|
|
25638
|
+
if (!isRec(response)) return response;
|
|
25639
|
+
const r = response;
|
|
25640
|
+
switch (method) {
|
|
25641
|
+
case "conversations.history":
|
|
25642
|
+
case "conversations.replies": return { messages: asArray(r.messages).map(slimMessage) };
|
|
25643
|
+
case "conversations.info": return { channel: slimConversation(r.channel) };
|
|
25644
|
+
case "conversations.list": return { channels: asArray(r.channels).map(slimConversation) };
|
|
25645
|
+
case "users.info":
|
|
25646
|
+
case "users.lookupByEmail": return { user: slimUser(r.user) };
|
|
25647
|
+
case "users.list": return { users: asArray(r.members).map(slimUser) };
|
|
25648
|
+
case "files.info": return { file: slimFile(r.file) };
|
|
25649
|
+
case "files.list": return { files: asArray(r.files).map(slimFile) };
|
|
25650
|
+
case "team.info": return { team: slimTeam(r.team) };
|
|
25651
|
+
case "reactions.get": return isRec(r.message) ? {
|
|
25652
|
+
...stripResponseEnvelope(r),
|
|
25653
|
+
message: slimMessage(r.message)
|
|
25654
|
+
} : stripResponseEnvelope(r);
|
|
25655
|
+
default: return stripResponseEnvelope(r);
|
|
25656
|
+
}
|
|
25657
|
+
};
|
|
25658
|
+
//#endregion
|
|
25524
25659
|
//#region src/cli/metadata.ts
|
|
25525
25660
|
createRequire(import.meta.url);
|
|
25526
|
-
const packageJson = { version: "0.1.
|
|
25661
|
+
const packageJson = { version: "0.1.14" };
|
|
25527
25662
|
const PRIMARY_COMMAND_NAME = "agent-slack";
|
|
25528
25663
|
const SHORT_COMMAND_NAME = "aslk";
|
|
25529
25664
|
const COMMAND_NAMES = [PRIMARY_COMMAND_NAME, SHORT_COMMAND_NAME];
|
|
@@ -25764,6 +25899,12 @@ const commandMetadata = [
|
|
|
25764
25899
|
{
|
|
25765
25900
|
path: ["conversation", "list"],
|
|
25766
25901
|
summary: "List conversations visible to the active profile.",
|
|
25902
|
+
flags: [
|
|
25903
|
+
"--types",
|
|
25904
|
+
"--limit",
|
|
25905
|
+
"--all",
|
|
25906
|
+
"--json"
|
|
25907
|
+
],
|
|
25767
25908
|
methods: ["conversations.list"],
|
|
25768
25909
|
scopes: [
|
|
25769
25910
|
"channels:read",
|
|
@@ -25773,12 +25914,21 @@ const commandMetadata = [
|
|
|
25773
25914
|
],
|
|
25774
25915
|
safety: "read",
|
|
25775
25916
|
output: "conversation list",
|
|
25776
|
-
examples: ["agent-slack conversation list --types public_channel,private_channel --json"]
|
|
25917
|
+
examples: ["agent-slack conversation list --types public_channel,private_channel --json", "agent-slack conversation list --all --json"]
|
|
25777
25918
|
},
|
|
25778
25919
|
{
|
|
25779
25920
|
path: ["conversation", "history"],
|
|
25780
25921
|
summary: "Read conversation history.",
|
|
25781
25922
|
args: ["CHANNEL_ID"],
|
|
25923
|
+
flags: [
|
|
25924
|
+
"--oldest",
|
|
25925
|
+
"--latest",
|
|
25926
|
+
"--since",
|
|
25927
|
+
"--inclusive",
|
|
25928
|
+
"--limit",
|
|
25929
|
+
"--all",
|
|
25930
|
+
"--json"
|
|
25931
|
+
],
|
|
25782
25932
|
methods: ["conversations.history"],
|
|
25783
25933
|
scopes: [
|
|
25784
25934
|
"channels:history",
|
|
@@ -25794,6 +25944,15 @@ const commandMetadata = [
|
|
|
25794
25944
|
path: ["conversation", "context"],
|
|
25795
25945
|
summary: "Build channel context for agents.",
|
|
25796
25946
|
args: ["CHANNEL_ID"],
|
|
25947
|
+
flags: [
|
|
25948
|
+
"--since",
|
|
25949
|
+
"--include",
|
|
25950
|
+
"--limit",
|
|
25951
|
+
"--all",
|
|
25952
|
+
"--full",
|
|
25953
|
+
"--format",
|
|
25954
|
+
"--json"
|
|
25955
|
+
],
|
|
25797
25956
|
methods: [
|
|
25798
25957
|
"conversations.history",
|
|
25799
25958
|
"conversations.replies",
|
|
@@ -25890,7 +26049,14 @@ const commandMetadata = [
|
|
|
25890
26049
|
output: "download status",
|
|
25891
26050
|
examples: ["agent-slack file download F123 --out ./artifact.pdf --json"]
|
|
25892
26051
|
}
|
|
25893
|
-
]
|
|
26052
|
+
].map((command) => {
|
|
26053
|
+
const method = command.methods?.[0];
|
|
26054
|
+
const dataKey = method === void 0 ? void 0 : dataKeyFor(method);
|
|
26055
|
+
return dataKey === void 0 ? command : {
|
|
26056
|
+
...command,
|
|
26057
|
+
dataKey
|
|
26058
|
+
};
|
|
26059
|
+
});
|
|
25894
26060
|
const describeAllCommands = () => ({
|
|
25895
26061
|
name: PRIMARY_COMMAND_NAME,
|
|
25896
26062
|
aliases: [SHORT_COMMAND_NAME],
|
|
@@ -25911,6 +26077,7 @@ const renderHumanHelp = (path) => {
|
|
|
25911
26077
|
command.summary,
|
|
25912
26078
|
"",
|
|
25913
26079
|
command.args === void 0 ? "" : `Usage: ${PRIMARY_COMMAND_NAME} ${command.path.join(" ")} ${command.args.join(" ")}`,
|
|
26080
|
+
command.flags === void 0 ? "" : `Flags: ${command.flags.join(" ")}`,
|
|
25914
26081
|
command.scopes === void 0 ? "" : `Scopes: ${command.scopes.join(", ")}`,
|
|
25915
26082
|
"",
|
|
25916
26083
|
"Examples:",
|
|
@@ -25977,123 +26144,6 @@ const renderCompletion = (shell) => {
|
|
|
25977
26144
|
};
|
|
25978
26145
|
const summaryFor = (path) => commandMetadata.find((command) => command.path.join(" ") === path)?.summary.replace(/'/g, "") ?? "";
|
|
25979
26146
|
//#endregion
|
|
25980
|
-
//#region src/output/normalize.ts
|
|
25981
|
-
const isRec = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25982
|
-
const asArray = (value) => Array.isArray(value) ? value : [];
|
|
25983
|
-
const str = (record, key) => typeof record[key] === "string" && record[key].length > 0 ? record[key] : void 0;
|
|
25984
|
-
const slimFile = (input) => {
|
|
25985
|
-
if (!isRec(input)) return input;
|
|
25986
|
-
const out = {
|
|
25987
|
-
id: input.id,
|
|
25988
|
-
name: input.name
|
|
25989
|
-
};
|
|
25990
|
-
if (typeof input.mimetype === "string") out.mimetype = input.mimetype;
|
|
25991
|
-
if (typeof input.size === "number") out.size = input.size;
|
|
25992
|
-
const permalink = str(input, "permalink");
|
|
25993
|
-
if (permalink) out.permalink = permalink;
|
|
25994
|
-
return out;
|
|
25995
|
-
};
|
|
25996
|
-
const slimMessage = (input) => {
|
|
25997
|
-
if (!isRec(input)) return input;
|
|
25998
|
-
const m = input;
|
|
25999
|
-
const out = {};
|
|
26000
|
-
if (typeof m.user === "string") out.user = m.user;
|
|
26001
|
-
else if (typeof m.bot_id === "string") out.bot_id = m.bot_id;
|
|
26002
|
-
const username = str(m, "username");
|
|
26003
|
-
if (username) out.username = username;
|
|
26004
|
-
const subtype = str(m, "subtype");
|
|
26005
|
-
if (subtype) out.subtype = subtype;
|
|
26006
|
-
if (typeof m.ts === "string") out.ts = m.ts;
|
|
26007
|
-
out.text = typeof m.text === "string" ? m.text : "";
|
|
26008
|
-
if (typeof m.thread_ts === "string" && m.thread_ts !== m.ts) out.thread_ts = m.thread_ts;
|
|
26009
|
-
if (typeof m.reply_count === "number") out.reply_count = m.reply_count;
|
|
26010
|
-
const reactions = asArray(m.reactions).filter(isRec).map((r) => ({
|
|
26011
|
-
name: r.name,
|
|
26012
|
-
count: r.count
|
|
26013
|
-
}));
|
|
26014
|
-
if (reactions.length > 0) out.reactions = reactions;
|
|
26015
|
-
const files = asArray(m.files).map(slimFile);
|
|
26016
|
-
if (files.length > 0) out.files = files;
|
|
26017
|
-
if (m.edited !== void 0 && m.edited !== null) out.edited = true;
|
|
26018
|
-
return out;
|
|
26019
|
-
};
|
|
26020
|
-
const slimUser = (input) => {
|
|
26021
|
-
if (!isRec(input)) return input;
|
|
26022
|
-
const u = input;
|
|
26023
|
-
const profile = isRec(u.profile) ? u.profile : {};
|
|
26024
|
-
const out = {
|
|
26025
|
-
id: u.id,
|
|
26026
|
-
name: u.name
|
|
26027
|
-
};
|
|
26028
|
-
const real = str(profile, "display_name") ?? str(u, "real_name") ?? str(profile, "real_name");
|
|
26029
|
-
if (real) out.real_name = real;
|
|
26030
|
-
if (u.is_bot === true) out.is_bot = true;
|
|
26031
|
-
if (u.deleted === true) out.deleted = true;
|
|
26032
|
-
const title = str(profile, "title");
|
|
26033
|
-
if (title) out.title = title;
|
|
26034
|
-
return out;
|
|
26035
|
-
};
|
|
26036
|
-
const slimConversation = (input) => {
|
|
26037
|
-
if (!isRec(input)) return input;
|
|
26038
|
-
const c = input;
|
|
26039
|
-
const out = {
|
|
26040
|
-
id: c.id,
|
|
26041
|
-
name: c.name
|
|
26042
|
-
};
|
|
26043
|
-
if (c.is_private === true) out.is_private = true;
|
|
26044
|
-
if (c.is_archived === true) out.is_archived = true;
|
|
26045
|
-
if (c.is_im === true) out.is_im = true;
|
|
26046
|
-
if (c.is_mpim === true) out.is_mpim = true;
|
|
26047
|
-
const topic = isRec(c.topic) ? str(c.topic, "value") : void 0;
|
|
26048
|
-
if (topic) out.topic = topic;
|
|
26049
|
-
const purpose = isRec(c.purpose) ? str(c.purpose, "value") : void 0;
|
|
26050
|
-
if (purpose) out.purpose = purpose;
|
|
26051
|
-
if (typeof c.num_members === "number") out.num_members = c.num_members;
|
|
26052
|
-
return out;
|
|
26053
|
-
};
|
|
26054
|
-
const slimTeam = (input) => {
|
|
26055
|
-
if (!isRec(input)) return input;
|
|
26056
|
-
const t = input;
|
|
26057
|
-
const out = {
|
|
26058
|
-
id: t.id,
|
|
26059
|
-
name: t.name
|
|
26060
|
-
};
|
|
26061
|
-
const domain = str(t, "domain");
|
|
26062
|
-
if (domain) out.domain = domain;
|
|
26063
|
-
const emailDomain = str(t, "email_domain");
|
|
26064
|
-
if (emailDomain) out.email_domain = emailDomain;
|
|
26065
|
-
const enterpriseId = str(t, "enterprise_id");
|
|
26066
|
-
if (enterpriseId) out.enterprise_id = enterpriseId;
|
|
26067
|
-
const enterpriseName = str(t, "enterprise_name");
|
|
26068
|
-
if (enterpriseName) out.enterprise_name = enterpriseName;
|
|
26069
|
-
return out;
|
|
26070
|
-
};
|
|
26071
|
-
const stripResponseEnvelope = (response) => {
|
|
26072
|
-
const { ok, response_metadata, ...rest } = response;
|
|
26073
|
-
return rest;
|
|
26074
|
-
};
|
|
26075
|
-
const normalizeResponse = (method, response) => {
|
|
26076
|
-
if (!isRec(response)) return response;
|
|
26077
|
-
const r = response;
|
|
26078
|
-
switch (method) {
|
|
26079
|
-
case "conversations.history":
|
|
26080
|
-
case "conversations.replies": return { messages: asArray(r.messages).map(slimMessage) };
|
|
26081
|
-
case "conversations.info": return { channel: slimConversation(r.channel) };
|
|
26082
|
-
case "conversations.list": return { channels: asArray(r.channels).map(slimConversation) };
|
|
26083
|
-
case "users.info":
|
|
26084
|
-
case "users.lookupByEmail": return { user: slimUser(r.user) };
|
|
26085
|
-
case "users.list": return { users: asArray(r.members).map(slimUser) };
|
|
26086
|
-
case "files.info": return { file: slimFile(r.file) };
|
|
26087
|
-
case "files.list": return { files: asArray(r.files).map(slimFile) };
|
|
26088
|
-
case "team.info": return { team: slimTeam(r.team) };
|
|
26089
|
-
case "reactions.get": return isRec(r.message) ? {
|
|
26090
|
-
...stripResponseEnvelope(r),
|
|
26091
|
-
message: slimMessage(r.message)
|
|
26092
|
-
} : stripResponseEnvelope(r);
|
|
26093
|
-
default: return stripResponseEnvelope(r);
|
|
26094
|
-
}
|
|
26095
|
-
};
|
|
26096
|
-
//#endregion
|
|
26097
26147
|
//#region src/output/projection.ts
|
|
26098
26148
|
const projectFields = (value, fields) => {
|
|
26099
26149
|
if (fields === void 0 || fields.trim() === "") return value;
|
|
@@ -26249,6 +26299,12 @@ const extractItems = (services, method, response) => {
|
|
|
26249
26299
|
const dispatch = async (parsed, services) => {
|
|
26250
26300
|
const pos = parsed.positionals;
|
|
26251
26301
|
const [first, second, third] = pos;
|
|
26302
|
+
if (flagBoolean(parsed, "version")) return {
|
|
26303
|
+
method: "version",
|
|
26304
|
+
profile: null,
|
|
26305
|
+
stdoutValue: null,
|
|
26306
|
+
rawStdout: `${CLI_VERSION}\n`
|
|
26307
|
+
};
|
|
26252
26308
|
if (flagBoolean(parsed, "help") && !flagBoolean(parsed, "json")) return {
|
|
26253
26309
|
method: "help",
|
|
26254
26310
|
profile: null,
|
|
@@ -26656,6 +26712,26 @@ const conversationContext = async (parsed, services) => {
|
|
|
26656
26712
|
response: history.response,
|
|
26657
26713
|
stdoutValue: context,
|
|
26658
26714
|
items: messages.map(shape),
|
|
26715
|
+
enrichmentRecords: [
|
|
26716
|
+
...recordsFromMap(context.users, (_, data) => ({
|
|
26717
|
+
type: "slack.user",
|
|
26718
|
+
data
|
|
26719
|
+
})),
|
|
26720
|
+
...recordsFromMap(context.threads, (ts, replies) => ({
|
|
26721
|
+
type: "slack.thread",
|
|
26722
|
+
data: {
|
|
26723
|
+
ts,
|
|
26724
|
+
replies
|
|
26725
|
+
}
|
|
26726
|
+
})),
|
|
26727
|
+
...recordsFromMap(context.permalinks, (ts, permalink) => ({
|
|
26728
|
+
type: "slack.permalink",
|
|
26729
|
+
data: {
|
|
26730
|
+
ts,
|
|
26731
|
+
permalink
|
|
26732
|
+
}
|
|
26733
|
+
}))
|
|
26734
|
+
],
|
|
26659
26735
|
...warnings.length > 0 ? { warnings } : {}
|
|
26660
26736
|
};
|
|
26661
26737
|
};
|
|
@@ -26736,6 +26812,16 @@ const threadGet = async (parsed, services) => {
|
|
|
26736
26812
|
response: result.response,
|
|
26737
26813
|
stdoutValue: data,
|
|
26738
26814
|
items: rawMessages.map(shape),
|
|
26815
|
+
enrichmentRecords: [...recordsFromMap(data.users, (_, user) => ({
|
|
26816
|
+
type: "slack.user",
|
|
26817
|
+
data: user
|
|
26818
|
+
})), ...recordsFromMap(data.permalinks, (ts, permalink) => ({
|
|
26819
|
+
type: "slack.permalink",
|
|
26820
|
+
data: {
|
|
26821
|
+
ts,
|
|
26822
|
+
permalink
|
|
26823
|
+
}
|
|
26824
|
+
}))],
|
|
26739
26825
|
...warnings.length > 0 ? { warnings } : {}
|
|
26740
26826
|
};
|
|
26741
26827
|
};
|
|
@@ -26844,7 +26930,7 @@ const methodCall = async (parsed, services, input, options = {}) => {
|
|
|
26844
26930
|
};
|
|
26845
26931
|
const renderDispatchResult = (parsed, result, options = {}) => {
|
|
26846
26932
|
if (result.rawStdout !== void 0) return result.rawStdout;
|
|
26847
|
-
if (flagString(parsed, "format") === "ndjson") return toNdjson(result.items ?? []);
|
|
26933
|
+
if (flagString(parsed, "format") === "ndjson") return toNdjson([...result.items ?? [], ...result.enrichmentRecords ?? []]);
|
|
26848
26934
|
const data = projectFields(result.stdoutValue, flagString(parsed, "fields"));
|
|
26849
26935
|
const envelope = successEnvelope({
|
|
26850
26936
|
method: result.method,
|
|
@@ -26901,6 +26987,7 @@ const stringField = (record, name) => typeof record[name] === "string" && record
|
|
|
26901
26987
|
const extractArray = (value) => Array.isArray(value) ? value : [];
|
|
26902
26988
|
const extractLooseRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
26903
26989
|
const uniqueStrings = (values) => [...new Set(values.filter((value) => value !== void 0))];
|
|
26990
|
+
const recordsFromMap = (value, toRecord) => Object.entries(extractLooseRecord(value)).map(([key, entry]) => toRecord(key, entry));
|
|
26904
26991
|
//#endregion
|
|
26905
26992
|
//#region src/application/execute.ts
|
|
26906
26993
|
const executeCli = async (argv, services, options = {}) => {
|