@fdcn/sourcefed 0.3.1 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/chunk-BNLZQKEB.js +962 -0
- package/dist/{chunk-QPDTUNFA.js → chunk-X3BZSHKZ.js} +55 -45
- package/dist/cli.js +104 -96
- package/dist/daemon.js +341 -1271
- package/dist/data/core/references/commands.md +1 -1
- package/dist/mcp.js +1 -1
- package/dist/opencode.js +124 -37
- package/dist/pi.js +5 -4
- package/dist/tui-compiled.mjs +6 -6
- package/dist.dts/adapters/opencode/bridge.d.ts +18 -2
- package/dist.dts/adapters/opencode/bridge.test.d.ts +1 -0
- package/dist.dts/adapters/opencode/tui/sidebar.d.ts +1 -1
- package/dist.dts/packages/cli/src/utils/flags.d.ts +2 -0
- package/dist.dts/packages/cli/src/utils/flags.test.d.ts +1 -0
- package/dist.dts/packages/daemon/src/daemon.d.ts +5 -0
- package/dist.dts/packages/daemon/src/forward.test.d.ts +1 -0
- package/dist.dts/packages/daemon/src/gate.test.d.ts +1 -0
- package/dist.dts/packages/daemon/src/utils/forward.d.ts +32 -0
- package/dist.dts/packages/daemon/src/utils/gate.d.ts +33 -0
- package/dist.dts/providers/slack/src/poll/utils/slack-api.d.ts +12 -4
- package/dist.dts/providers/slack/src/poll/utils/slack-api.test.d.ts +1 -0
- package/package.json +2 -2
|
@@ -11034,7 +11034,7 @@ function parseSlackReadResult(result, cursorRaw, location = "thread") {
|
|
|
11034
11034
|
messageIds: previous.messageIds ?? [],
|
|
11035
11035
|
latestTs: previous.latestTs
|
|
11036
11036
|
};
|
|
11037
|
-
const
|
|
11037
|
+
const users2 = new Map((result.users ?? []).map((user) => [user.id, user.real_name ?? user.name ?? user.id ?? "someone"]));
|
|
11038
11038
|
const messages = (result.messages ?? []).filter((message) => message.ts);
|
|
11039
11039
|
const freshMessages = messages.filter((message) => {
|
|
11040
11040
|
if (cursor.messageIds.includes(message.ts)) return false;
|
|
@@ -11046,7 +11046,7 @@ function parseSlackReadResult(result, cursorRaw, location = "thread") {
|
|
|
11046
11046
|
events = freshMessages.map((message) => {
|
|
11047
11047
|
let text = "[message without text]";
|
|
11048
11048
|
if (message.text?.trim()) text = message.text.trim();
|
|
11049
|
-
let author =
|
|
11049
|
+
let author = users2.get(message.user);
|
|
11050
11050
|
if (!author) author = message.user;
|
|
11051
11051
|
if (!author) author = "someone";
|
|
11052
11052
|
return {
|
|
@@ -11069,10 +11069,9 @@ function parseSlackReadResult(result, cursorRaw, location = "thread") {
|
|
|
11069
11069
|
return { events, cursor };
|
|
11070
11070
|
}
|
|
11071
11071
|
var SLACK_API = "https://slack.com/api";
|
|
11072
|
-
var
|
|
11073
|
-
|
|
11074
|
-
|
|
11075
|
-
}
|
|
11072
|
+
var USERS_TTL_MS = 60 * 60 * 1e3;
|
|
11073
|
+
var users;
|
|
11074
|
+
var refreshing;
|
|
11076
11075
|
async function fetchSlackThread(channelId, threadTs) {
|
|
11077
11076
|
return fetchSlackMessages("conversations.replies", { channel: channelId, ts: threadTs, inclusive: "false" });
|
|
11078
11077
|
}
|
|
@@ -11082,61 +11081,57 @@ async function fetchSlackDm(channelId) {
|
|
|
11082
11081
|
async function fetchSlackMessages(method, params) {
|
|
11083
11082
|
const messages = [];
|
|
11084
11083
|
let cursor = "";
|
|
11085
|
-
let received = false;
|
|
11086
11084
|
do {
|
|
11087
|
-
const page = await slackApi(method, {
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
}
|
|
11092
|
-
if (
|
|
11093
|
-
|
|
11094
|
-
if (Array.isArray(page.messages)) messages.push(...page.messages);
|
|
11095
|
-
cursor = page.response_metadata?.next_cursor ?? "";
|
|
11085
|
+
const page = await slackApi(method, { ...params, limit: "1000", ...cursor ? { cursor } : {} });
|
|
11086
|
+
if (!page.ok) {
|
|
11087
|
+
if (messages.length > 0) break;
|
|
11088
|
+
throw new Error(`slack ${method} failed: ${page.error}`);
|
|
11089
|
+
}
|
|
11090
|
+
if (Array.isArray(page.result.messages)) messages.push(...page.result.messages);
|
|
11091
|
+
cursor = page.result.response_metadata?.next_cursor ?? "";
|
|
11096
11092
|
if (messages.length >= 1e4) break;
|
|
11097
11093
|
} while (cursor);
|
|
11098
|
-
|
|
11099
|
-
|
|
11100
|
-
|
|
11094
|
+
return { messages, users: await slackUsers() };
|
|
11095
|
+
}
|
|
11096
|
+
async function slackUsers() {
|
|
11097
|
+
if (users && Date.now() - users.fetchedAt < USERS_TTL_MS) return users.list;
|
|
11098
|
+
refreshing ??= refreshUsers().finally(() => {
|
|
11099
|
+
refreshing = void 0;
|
|
11100
|
+
});
|
|
11101
|
+
return refreshing;
|
|
11102
|
+
}
|
|
11103
|
+
async function refreshUsers() {
|
|
11104
|
+
const list = [];
|
|
11105
|
+
let cursor = "";
|
|
11101
11106
|
do {
|
|
11102
|
-
const page = await slackApi("users.list", { limit: "200", ...
|
|
11103
|
-
if (!page)
|
|
11104
|
-
if (Array.isArray(page.members)) {
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
usersCursor = page.response_metadata?.next_cursor ?? "";
|
|
11112
|
-
} while (usersCursor);
|
|
11113
|
-
return { messages, users };
|
|
11107
|
+
const page = await slackApi("users.list", { limit: "200", ...cursor ? { cursor } : {} });
|
|
11108
|
+
if (!page.ok) return users?.list ?? list;
|
|
11109
|
+
if (Array.isArray(page.result.members)) {
|
|
11110
|
+
list.push(...page.result.members.map((member) => ({ id: member.id, name: member.name, real_name: member.real_name })));
|
|
11111
|
+
}
|
|
11112
|
+
cursor = page.result.response_metadata?.next_cursor ?? "";
|
|
11113
|
+
} while (cursor);
|
|
11114
|
+
users = { list, fetchedAt: Date.now() };
|
|
11115
|
+
return list;
|
|
11114
11116
|
}
|
|
11115
11117
|
async function slackApi(method, params) {
|
|
11116
|
-
const token =
|
|
11117
|
-
if (!token) {
|
|
11118
|
-
if (!warnedMissingToken2) {
|
|
11119
|
-
warnedMissingToken2 = true;
|
|
11120
|
-
console.warn("[sourcefed] SOURCEFED_SLACK_TOKEN is not set; Slack monitors will not poll");
|
|
11121
|
-
}
|
|
11122
|
-
return void 0;
|
|
11123
|
-
}
|
|
11118
|
+
const token = process.env.SOURCEFED_SLACK_TOKEN;
|
|
11119
|
+
if (!token) return { ok: false, error: "SOURCEFED_SLACK_TOKEN is not set" };
|
|
11124
11120
|
try {
|
|
11125
11121
|
const response = await fetch(`${SLACK_API}/${method}`, {
|
|
11126
11122
|
method: "POST",
|
|
11127
11123
|
headers: { authorization: `Bearer ${token}`, "content-type": "application/x-www-form-urlencoded" },
|
|
11128
11124
|
body: new URLSearchParams(params)
|
|
11129
11125
|
});
|
|
11130
|
-
const result = await response.json();
|
|
11131
|
-
if (
|
|
11132
|
-
return result;
|
|
11133
|
-
} catch {
|
|
11134
|
-
return
|
|
11126
|
+
const result = await response.json().catch(() => void 0);
|
|
11127
|
+
if (response.ok && result?.ok === true) return { ok: true, result };
|
|
11128
|
+
return { ok: false, error: result?.error ?? `HTTP ${response.status}` };
|
|
11129
|
+
} catch (error) {
|
|
11130
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
11135
11131
|
}
|
|
11136
11132
|
}
|
|
11137
11133
|
async function pollSlack(source, cursorRaw) {
|
|
11138
11134
|
const result = source.threadTs ? await fetchSlackThread(source.channelId, source.threadTs) : await fetchSlackDm(source.channelId);
|
|
11139
|
-
if (!result) throw new Error("slack API request failed; check SOURCEFED_SLACK_TOKEN");
|
|
11140
11135
|
const parsed = parseSlackReadResult(result, cursorRaw, source.threadTs ? "thread" : "DM");
|
|
11141
11136
|
return { ...parsed, terminal: false };
|
|
11142
11137
|
}
|
|
@@ -11595,6 +11590,18 @@ var SourcefedDaemon = class {
|
|
|
11595
11590
|
const monitors = (await this.service.list()).filter((monitor) => sameTarget(monitor.target, target));
|
|
11596
11591
|
return { ok: true, monitors: monitors.map(monitorView) };
|
|
11597
11592
|
}
|
|
11593
|
+
/**
|
|
11594
|
+
* Every target of `kind` with an enabled monitor, so a host that restarts can
|
|
11595
|
+
* resubscribe the sessions whose monitors outlived it.
|
|
11596
|
+
*/
|
|
11597
|
+
async listTargets(kind) {
|
|
11598
|
+
const targets = /* @__PURE__ */ new Map();
|
|
11599
|
+
for (const monitor of await this.service.list()) {
|
|
11600
|
+
if (!monitor.enabled || monitor.target.kind !== kind) continue;
|
|
11601
|
+
targets.set(targetKey(monitor.target), { kind: monitor.target.kind, id: monitor.target.id });
|
|
11602
|
+
}
|
|
11603
|
+
return [...targets.values()];
|
|
11604
|
+
}
|
|
11598
11605
|
async getMonitor(target, id) {
|
|
11599
11606
|
const monitor = await ownedMonitor(this.service, id, target);
|
|
11600
11607
|
if (!monitor) return { ok: false, error: `monitor ${id} was not found for this target` };
|
|
@@ -11961,6 +11968,9 @@ async function dispatchDaemonRequest(daemon, method, params) {
|
|
|
11961
11968
|
return daemon.createMonitor(createTarget(params), createCreateInput(params));
|
|
11962
11969
|
case "monitor.list":
|
|
11963
11970
|
return daemon.listMonitors(createTarget(params));
|
|
11971
|
+
case "monitor.targets":
|
|
11972
|
+
if (typeof params.kind !== "string" || !params.kind) throw new Error("monitor.targets requires params.kind");
|
|
11973
|
+
return { targets: await daemon.listTargets(params.kind) };
|
|
11964
11974
|
case "monitor.status":
|
|
11965
11975
|
return daemon.getMonitor(createTarget(params), String(params.id));
|
|
11966
11976
|
case "monitor.stop":
|
package/dist/cli.js
CHANGED
|
@@ -11040,7 +11040,7 @@ function parseSlackReadResult(result, cursorRaw, location = "thread") {
|
|
|
11040
11040
|
messageIds: previous.messageIds ?? [],
|
|
11041
11041
|
latestTs: previous.latestTs
|
|
11042
11042
|
};
|
|
11043
|
-
const
|
|
11043
|
+
const users22 = new Map((result.users ?? []).map((user) => [user.id, user.real_name ?? user.name ?? user.id ?? "someone"]));
|
|
11044
11044
|
const messages = (result.messages ?? []).filter((message) => message.ts);
|
|
11045
11045
|
const freshMessages = messages.filter((message) => {
|
|
11046
11046
|
if (cursor.messageIds.includes(message.ts)) return false;
|
|
@@ -11052,7 +11052,7 @@ function parseSlackReadResult(result, cursorRaw, location = "thread") {
|
|
|
11052
11052
|
events2 = freshMessages.map((message) => {
|
|
11053
11053
|
let text = "[message without text]";
|
|
11054
11054
|
if (message.text?.trim()) text = message.text.trim();
|
|
11055
|
-
let author =
|
|
11055
|
+
let author = users22.get(message.user);
|
|
11056
11056
|
if (!author) author = message.user;
|
|
11057
11057
|
if (!author) author = "someone";
|
|
11058
11058
|
return {
|
|
@@ -11075,10 +11075,9 @@ function parseSlackReadResult(result, cursorRaw, location = "thread") {
|
|
|
11075
11075
|
return { events: events2, cursor };
|
|
11076
11076
|
}
|
|
11077
11077
|
var SLACK_API = "https://slack.com/api";
|
|
11078
|
-
var
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
}
|
|
11078
|
+
var USERS_TTL_MS = 60 * 60 * 1e3;
|
|
11079
|
+
var users;
|
|
11080
|
+
var refreshing;
|
|
11082
11081
|
async function fetchSlackThread(channelId, threadTs) {
|
|
11083
11082
|
return fetchSlackMessages("conversations.replies", { channel: channelId, ts: threadTs, inclusive: "false" });
|
|
11084
11083
|
}
|
|
@@ -11088,61 +11087,57 @@ async function fetchSlackDm(channelId) {
|
|
|
11088
11087
|
async function fetchSlackMessages(method, params) {
|
|
11089
11088
|
const messages = [];
|
|
11090
11089
|
let cursor = "";
|
|
11091
|
-
let received = false;
|
|
11092
11090
|
do {
|
|
11093
|
-
const page = await slackApi(method, {
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
}
|
|
11098
|
-
if (
|
|
11099
|
-
|
|
11100
|
-
if (Array.isArray(page.messages)) messages.push(...page.messages);
|
|
11101
|
-
cursor = page.response_metadata?.next_cursor ?? "";
|
|
11091
|
+
const page = await slackApi(method, { ...params, limit: "1000", ...cursor ? { cursor } : {} });
|
|
11092
|
+
if (!page.ok) {
|
|
11093
|
+
if (messages.length > 0) break;
|
|
11094
|
+
throw new Error(`slack ${method} failed: ${page.error}`);
|
|
11095
|
+
}
|
|
11096
|
+
if (Array.isArray(page.result.messages)) messages.push(...page.result.messages);
|
|
11097
|
+
cursor = page.result.response_metadata?.next_cursor ?? "";
|
|
11102
11098
|
if (messages.length >= 1e4) break;
|
|
11103
11099
|
} while (cursor);
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11100
|
+
return { messages, users: await slackUsers() };
|
|
11101
|
+
}
|
|
11102
|
+
async function slackUsers() {
|
|
11103
|
+
if (users && Date.now() - users.fetchedAt < USERS_TTL_MS) return users.list;
|
|
11104
|
+
refreshing ??= refreshUsers().finally(() => {
|
|
11105
|
+
refreshing = void 0;
|
|
11106
|
+
});
|
|
11107
|
+
return refreshing;
|
|
11108
|
+
}
|
|
11109
|
+
async function refreshUsers() {
|
|
11110
|
+
const list2 = [];
|
|
11111
|
+
let cursor = "";
|
|
11107
11112
|
do {
|
|
11108
|
-
const page = await slackApi("users.list", { limit: "200", ...
|
|
11109
|
-
if (!page)
|
|
11110
|
-
if (Array.isArray(page.members)) {
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
usersCursor = page.response_metadata?.next_cursor ?? "";
|
|
11118
|
-
} while (usersCursor);
|
|
11119
|
-
return { messages, users };
|
|
11113
|
+
const page = await slackApi("users.list", { limit: "200", ...cursor ? { cursor } : {} });
|
|
11114
|
+
if (!page.ok) return users?.list ?? list2;
|
|
11115
|
+
if (Array.isArray(page.result.members)) {
|
|
11116
|
+
list2.push(...page.result.members.map((member) => ({ id: member.id, name: member.name, real_name: member.real_name })));
|
|
11117
|
+
}
|
|
11118
|
+
cursor = page.result.response_metadata?.next_cursor ?? "";
|
|
11119
|
+
} while (cursor);
|
|
11120
|
+
users = { list: list2, fetchedAt: Date.now() };
|
|
11121
|
+
return list2;
|
|
11120
11122
|
}
|
|
11121
11123
|
async function slackApi(method, params) {
|
|
11122
|
-
const token =
|
|
11123
|
-
if (!token) {
|
|
11124
|
-
if (!warnedMissingToken2) {
|
|
11125
|
-
warnedMissingToken2 = true;
|
|
11126
|
-
console.warn("[sourcefed] SOURCEFED_SLACK_TOKEN is not set; Slack monitors will not poll");
|
|
11127
|
-
}
|
|
11128
|
-
return void 0;
|
|
11129
|
-
}
|
|
11124
|
+
const token = process.env.SOURCEFED_SLACK_TOKEN;
|
|
11125
|
+
if (!token) return { ok: false, error: "SOURCEFED_SLACK_TOKEN is not set" };
|
|
11130
11126
|
try {
|
|
11131
11127
|
const response = await fetch(`${SLACK_API}/${method}`, {
|
|
11132
11128
|
method: "POST",
|
|
11133
11129
|
headers: { authorization: `Bearer ${token}`, "content-type": "application/x-www-form-urlencoded" },
|
|
11134
11130
|
body: new URLSearchParams(params)
|
|
11135
11131
|
});
|
|
11136
|
-
const result = await response.json();
|
|
11137
|
-
if (
|
|
11138
|
-
return result;
|
|
11139
|
-
} catch {
|
|
11140
|
-
return
|
|
11132
|
+
const result = await response.json().catch(() => void 0);
|
|
11133
|
+
if (response.ok && result?.ok === true) return { ok: true, result };
|
|
11134
|
+
return { ok: false, error: result?.error ?? `HTTP ${response.status}` };
|
|
11135
|
+
} catch (error2) {
|
|
11136
|
+
return { ok: false, error: error2 instanceof Error ? error2.message : String(error2) };
|
|
11141
11137
|
}
|
|
11142
11138
|
}
|
|
11143
11139
|
async function pollSlack(source, cursorRaw) {
|
|
11144
11140
|
const result = source.threadTs ? await fetchSlackThread(source.channelId, source.threadTs) : await fetchSlackDm(source.channelId);
|
|
11145
|
-
if (!result) throw new Error("slack API request failed; check SOURCEFED_SLACK_TOKEN");
|
|
11146
11141
|
const parsed = parseSlackReadResult(result, cursorRaw, source.threadTs ? "thread" : "DM");
|
|
11147
11142
|
return { ...parsed, terminal: false };
|
|
11148
11143
|
}
|
|
@@ -11518,6 +11513,18 @@ var SourcefedDaemon = class {
|
|
|
11518
11513
|
const monitors = (await this.service.list()).filter((monitor) => sameTarget(monitor.target, target));
|
|
11519
11514
|
return { ok: true, monitors: monitors.map(monitorView) };
|
|
11520
11515
|
}
|
|
11516
|
+
/**
|
|
11517
|
+
* Every target of `kind` with an enabled monitor, so a host that restarts can
|
|
11518
|
+
* resubscribe the sessions whose monitors outlived it.
|
|
11519
|
+
*/
|
|
11520
|
+
async listTargets(kind) {
|
|
11521
|
+
const targets = /* @__PURE__ */ new Map();
|
|
11522
|
+
for (const monitor of await this.service.list()) {
|
|
11523
|
+
if (!monitor.enabled || monitor.target.kind !== kind) continue;
|
|
11524
|
+
targets.set(targetKey(monitor.target), { kind: monitor.target.kind, id: monitor.target.id });
|
|
11525
|
+
}
|
|
11526
|
+
return [...targets.values()];
|
|
11527
|
+
}
|
|
11521
11528
|
async getMonitor(target, id) {
|
|
11522
11529
|
const monitor = await ownedMonitor(this.service, id, target);
|
|
11523
11530
|
if (!monitor) return { ok: false, error: `monitor ${id} was not found for this target` };
|
|
@@ -11884,6 +11891,9 @@ async function dispatchDaemonRequest(daemon, method, params) {
|
|
|
11884
11891
|
return daemon.createMonitor(createTarget(params), createCreateInput(params));
|
|
11885
11892
|
case "monitor.list":
|
|
11886
11893
|
return daemon.listMonitors(createTarget(params));
|
|
11894
|
+
case "monitor.targets":
|
|
11895
|
+
if (typeof params.kind !== "string" || !params.kind) throw new Error("monitor.targets requires params.kind");
|
|
11896
|
+
return { targets: await daemon.listTargets(params.kind) };
|
|
11887
11897
|
case "monitor.status":
|
|
11888
11898
|
return daemon.getMonitor(createTarget(params), String(params.id));
|
|
11889
11899
|
case "monitor.stop":
|
|
@@ -12002,6 +12012,9 @@ function flag(args, name) {
|
|
|
12002
12012
|
const index = args.indexOf(`--${name}`);
|
|
12003
12013
|
return index >= 0 ? args[index + 1] : void 0;
|
|
12004
12014
|
}
|
|
12015
|
+
function flags(args, name) {
|
|
12016
|
+
return args.flatMap((arg, index) => arg === `--${name}` && index + 1 < args.length ? [args[index + 1]] : []);
|
|
12017
|
+
}
|
|
12005
12018
|
|
|
12006
12019
|
// packages/cli/src/utils/net.ts
|
|
12007
12020
|
function isLoopback(hostname) {
|
|
@@ -27008,7 +27021,7 @@ var require_core$3 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
27008
27021
|
const util_1 = require_util();
|
|
27009
27022
|
const $dataRefSchema = require_data();
|
|
27010
27023
|
const uri_1 = require_uri();
|
|
27011
|
-
const defaultRegExp = (str,
|
|
27024
|
+
const defaultRegExp = (str, flags2) => new RegExp(str, flags2);
|
|
27012
27025
|
defaultRegExp.code = "new RegExp";
|
|
27013
27026
|
const META_IGNORE_OPTIONS = [
|
|
27014
27027
|
"removeAdditional",
|
|
@@ -41681,7 +41694,7 @@ function emptyGithubCursor2() {
|
|
|
41681
41694
|
prState: ""
|
|
41682
41695
|
};
|
|
41683
41696
|
}
|
|
41684
|
-
var
|
|
41697
|
+
var warnedMissingToken2 = false;
|
|
41685
41698
|
async function pollGithub2(repo, prNumber, cursorRaw) {
|
|
41686
41699
|
const parsedCursor = /* @__PURE__ */ safeParse2222(GithubCursorSchema2, cursorRaw);
|
|
41687
41700
|
let cursor = emptyGithubCursor2();
|
|
@@ -41689,8 +41702,8 @@ async function pollGithub2(repo, prNumber, cursorRaw) {
|
|
|
41689
41702
|
const events2 = [];
|
|
41690
41703
|
const ref = `#${prNumber}`;
|
|
41691
41704
|
if (!githubToken2()) {
|
|
41692
|
-
if (!
|
|
41693
|
-
|
|
41705
|
+
if (!warnedMissingToken2) {
|
|
41706
|
+
warnedMissingToken2 = true;
|
|
41694
41707
|
console.warn("[sourcefed] GH_TOKEN or GITHUB_TOKEN is not set; GitHub monitors will not poll");
|
|
41695
41708
|
}
|
|
41696
41709
|
return { events: events2, cursor, terminal: false };
|
|
@@ -43553,7 +43566,7 @@ function parseSlackReadResult2(result, cursorRaw, location = "thread") {
|
|
|
43553
43566
|
messageIds: previous.messageIds ?? [],
|
|
43554
43567
|
latestTs: previous.latestTs
|
|
43555
43568
|
};
|
|
43556
|
-
const
|
|
43569
|
+
const users22 = new Map((result.users ?? []).map((user) => [user.id, user.real_name ?? user.name ?? user.id ?? "someone"]));
|
|
43557
43570
|
const messages = (result.messages ?? []).filter((message) => message.ts);
|
|
43558
43571
|
const freshMessages = messages.filter((message) => {
|
|
43559
43572
|
if (cursor.messageIds.includes(message.ts)) return false;
|
|
@@ -43565,7 +43578,7 @@ function parseSlackReadResult2(result, cursorRaw, location = "thread") {
|
|
|
43565
43578
|
events2 = freshMessages.map((message) => {
|
|
43566
43579
|
let text = "[message without text]";
|
|
43567
43580
|
if (message.text?.trim()) text = message.text.trim();
|
|
43568
|
-
let author =
|
|
43581
|
+
let author = users22.get(message.user);
|
|
43569
43582
|
if (!author) author = message.user;
|
|
43570
43583
|
if (!author) author = "someone";
|
|
43571
43584
|
return {
|
|
@@ -43588,10 +43601,9 @@ function parseSlackReadResult2(result, cursorRaw, location = "thread") {
|
|
|
43588
43601
|
return { events: events2, cursor };
|
|
43589
43602
|
}
|
|
43590
43603
|
var SLACK_API2 = "https://slack.com/api";
|
|
43591
|
-
var
|
|
43592
|
-
|
|
43593
|
-
|
|
43594
|
-
}
|
|
43604
|
+
var USERS_TTL_MS2 = 60 * 60 * 1e3;
|
|
43605
|
+
var users2;
|
|
43606
|
+
var refreshing2;
|
|
43595
43607
|
async function fetchSlackThread2(channelId, threadTs) {
|
|
43596
43608
|
return fetchSlackMessages2("conversations.replies", { channel: channelId, ts: threadTs, inclusive: "false" });
|
|
43597
43609
|
}
|
|
@@ -43601,61 +43613,57 @@ async function fetchSlackDm2(channelId) {
|
|
|
43601
43613
|
async function fetchSlackMessages2(method, params) {
|
|
43602
43614
|
const messages = [];
|
|
43603
43615
|
let cursor = "";
|
|
43604
|
-
let received = false;
|
|
43605
43616
|
do {
|
|
43606
|
-
const page = await slackApi2(method, {
|
|
43607
|
-
|
|
43608
|
-
|
|
43609
|
-
|
|
43610
|
-
}
|
|
43611
|
-
if (
|
|
43612
|
-
|
|
43613
|
-
if (Array.isArray(page.messages)) messages.push(...page.messages);
|
|
43614
|
-
cursor = page.response_metadata?.next_cursor ?? "";
|
|
43617
|
+
const page = await slackApi2(method, { ...params, limit: "1000", ...cursor ? { cursor } : {} });
|
|
43618
|
+
if (!page.ok) {
|
|
43619
|
+
if (messages.length > 0) break;
|
|
43620
|
+
throw new Error(`slack ${method} failed: ${page.error}`);
|
|
43621
|
+
}
|
|
43622
|
+
if (Array.isArray(page.result.messages)) messages.push(...page.result.messages);
|
|
43623
|
+
cursor = page.result.response_metadata?.next_cursor ?? "";
|
|
43615
43624
|
if (messages.length >= 1e4) break;
|
|
43616
43625
|
} while (cursor);
|
|
43617
|
-
|
|
43618
|
-
|
|
43619
|
-
|
|
43626
|
+
return { messages, users: await slackUsers2() };
|
|
43627
|
+
}
|
|
43628
|
+
async function slackUsers2() {
|
|
43629
|
+
if (users2 && Date.now() - users2.fetchedAt < USERS_TTL_MS2) return users2.list;
|
|
43630
|
+
refreshing2 ??= refreshUsers2().finally(() => {
|
|
43631
|
+
refreshing2 = void 0;
|
|
43632
|
+
});
|
|
43633
|
+
return refreshing2;
|
|
43634
|
+
}
|
|
43635
|
+
async function refreshUsers2() {
|
|
43636
|
+
const list2 = [];
|
|
43637
|
+
let cursor = "";
|
|
43620
43638
|
do {
|
|
43621
|
-
const page = await slackApi2("users.list", { limit: "200", ...
|
|
43622
|
-
if (!page)
|
|
43623
|
-
if (Array.isArray(page.members)) {
|
|
43624
|
-
|
|
43625
|
-
|
|
43626
|
-
|
|
43627
|
-
|
|
43628
|
-
|
|
43629
|
-
|
|
43630
|
-
usersCursor = page.response_metadata?.next_cursor ?? "";
|
|
43631
|
-
} while (usersCursor);
|
|
43632
|
-
return { messages, users };
|
|
43639
|
+
const page = await slackApi2("users.list", { limit: "200", ...cursor ? { cursor } : {} });
|
|
43640
|
+
if (!page.ok) return users2?.list ?? list2;
|
|
43641
|
+
if (Array.isArray(page.result.members)) {
|
|
43642
|
+
list2.push(...page.result.members.map((member) => ({ id: member.id, name: member.name, real_name: member.real_name })));
|
|
43643
|
+
}
|
|
43644
|
+
cursor = page.result.response_metadata?.next_cursor ?? "";
|
|
43645
|
+
} while (cursor);
|
|
43646
|
+
users2 = { list: list2, fetchedAt: Date.now() };
|
|
43647
|
+
return list2;
|
|
43633
43648
|
}
|
|
43634
43649
|
async function slackApi2(method, params) {
|
|
43635
|
-
const token =
|
|
43636
|
-
if (!token) {
|
|
43637
|
-
if (!warnedMissingToken22) {
|
|
43638
|
-
warnedMissingToken22 = true;
|
|
43639
|
-
console.warn("[sourcefed] SOURCEFED_SLACK_TOKEN is not set; Slack monitors will not poll");
|
|
43640
|
-
}
|
|
43641
|
-
return void 0;
|
|
43642
|
-
}
|
|
43650
|
+
const token = process.env.SOURCEFED_SLACK_TOKEN;
|
|
43651
|
+
if (!token) return { ok: false, error: "SOURCEFED_SLACK_TOKEN is not set" };
|
|
43643
43652
|
try {
|
|
43644
43653
|
const response = await fetch(`${SLACK_API2}/${method}`, {
|
|
43645
43654
|
method: "POST",
|
|
43646
43655
|
headers: { authorization: `Bearer ${token}`, "content-type": "application/x-www-form-urlencoded" },
|
|
43647
43656
|
body: new URLSearchParams(params)
|
|
43648
43657
|
});
|
|
43649
|
-
const result = await response.json();
|
|
43650
|
-
if (
|
|
43651
|
-
return result;
|
|
43652
|
-
} catch {
|
|
43653
|
-
return
|
|
43658
|
+
const result = await response.json().catch(() => void 0);
|
|
43659
|
+
if (response.ok && result?.ok === true) return { ok: true, result };
|
|
43660
|
+
return { ok: false, error: result?.error ?? `HTTP ${response.status}` };
|
|
43661
|
+
} catch (error2) {
|
|
43662
|
+
return { ok: false, error: error2 instanceof Error ? error2.message : String(error2) };
|
|
43654
43663
|
}
|
|
43655
43664
|
}
|
|
43656
43665
|
async function pollSlack2(source, cursorRaw) {
|
|
43657
43666
|
const result = source.threadTs ? await fetchSlackThread2(source.channelId, source.threadTs) : await fetchSlackDm2(source.channelId);
|
|
43658
|
-
if (!result) throw new Error("slack API request failed; check SOURCEFED_SLACK_TOKEN");
|
|
43659
43667
|
const parsed = parseSlackReadResult2(result, cursorRaw, source.threadTs ? "thread" : "DM");
|
|
43660
43668
|
return { ...parsed, terminal: false };
|
|
43661
43669
|
}
|
|
@@ -44043,8 +44051,8 @@ function dim(text) {
|
|
|
44043
44051
|
|
|
44044
44052
|
// packages/cli/src/commands/monitor/ack.ts
|
|
44045
44053
|
async function ack(context) {
|
|
44046
|
-
const eventIDs = (
|
|
44047
|
-
if (eventIDs.length === 0) throw new Error("ack requires --event-id <id>
|
|
44054
|
+
const eventIDs = flags(context.args, "event-id").filter(Boolean);
|
|
44055
|
+
if (eventIDs.length === 0) throw new Error("ack requires --event-id <id> (repeat it for several events)");
|
|
44048
44056
|
printResult(await context.client.request("monitor.ack", { target: context.target, eventIDs }));
|
|
44049
44057
|
}
|
|
44050
44058
|
|