@integrity-labs/agt-cli 0.19.21 → 0.19.23
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/bin/agt.js +3 -3
- package/dist/{chunk-5WDQ5G5M.js → chunk-EPYGSR3M.js} +305 -39
- package/dist/chunk-EPYGSR3M.js.map +1 -0
- package/dist/lib/manager-worker.js +101 -11
- package/dist/lib/manager-worker.js.map +1 -1
- package/mcp/slack-channel.js +248 -141
- package/package.json +1 -1
- package/dist/chunk-5WDQ5G5M.js.map +0 -1
package/mcp/slack-channel.js
CHANGED
|
@@ -6801,24 +6801,7 @@ var require_dist = __commonJS({
|
|
|
6801
6801
|
}
|
|
6802
6802
|
});
|
|
6803
6803
|
|
|
6804
|
-
// src/
|
|
6805
|
-
var slack_block_kit_runtime_exports = {};
|
|
6806
|
-
__export(slack_block_kit_runtime_exports, {
|
|
6807
|
-
buildAskUserBlocks: () => buildAskUserBlocks,
|
|
6808
|
-
buildRatingActionsBlock: () => buildRatingActionsBlock,
|
|
6809
|
-
createPendingInteraction: () => createPendingInteraction,
|
|
6810
|
-
decodeActionId: () => decodeActionId,
|
|
6811
|
-
defaultRatingLabels: () => defaultRatingLabels,
|
|
6812
|
-
encodeActionId: () => encodeActionId,
|
|
6813
|
-
generateOptionToken: () => generateOptionToken,
|
|
6814
|
-
ratingValuesForScale: () => ratingValuesForScale,
|
|
6815
|
-
recordSlackDelivery: () => recordSlackDelivery,
|
|
6816
|
-
resolveInteractive: () => resolveInteractive,
|
|
6817
|
-
updatePendingInteractionMessageTs: () => updatePendingInteractionMessageTs,
|
|
6818
|
-
validateAskUserOptions: () => validateAskUserOptions,
|
|
6819
|
-
validateSlackBlocks: () => validateSlackBlocks,
|
|
6820
|
-
waitForResolution: () => waitForResolution
|
|
6821
|
-
});
|
|
6804
|
+
// src/ask-user-runtime.ts
|
|
6822
6805
|
async function getAuthToken(cfg) {
|
|
6823
6806
|
if (auth.token && Date.now() < auth.expiresAtEpochMs) return auth.token;
|
|
6824
6807
|
const res = await fetch(`${cfg.apiHost}/host/exchange`, {
|
|
@@ -6872,13 +6855,17 @@ async function createPendingInteraction(cfg, input) {
|
|
|
6872
6855
|
}
|
|
6873
6856
|
}
|
|
6874
6857
|
async function updatePendingInteractionMessageTs(cfg, callbackId, messageTs) {
|
|
6875
|
-
const res = await apiCall(
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6858
|
+
const res = await apiCall(
|
|
6859
|
+
cfg,
|
|
6860
|
+
"PATCH",
|
|
6861
|
+
`/host/pending-interactions/${encodeURIComponent(callbackId)}`,
|
|
6862
|
+
{ agent_id: cfg.agentId, message_ts: messageTs }
|
|
6863
|
+
);
|
|
6879
6864
|
if (!res.ok) {
|
|
6880
6865
|
const body = await res.text().catch(() => "");
|
|
6881
|
-
throw new Error(
|
|
6866
|
+
throw new Error(
|
|
6867
|
+
`updatePendingInteractionMessageTs failed (${res.status}): ${body.slice(0, 200)}`
|
|
6868
|
+
);
|
|
6882
6869
|
}
|
|
6883
6870
|
}
|
|
6884
6871
|
async function waitForResolution(cfg, callbackId, opts) {
|
|
@@ -6929,6 +6916,80 @@ function generateOptionToken() {
|
|
|
6929
6916
|
const out = Buffer.from(bytes).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
6930
6917
|
return out;
|
|
6931
6918
|
}
|
|
6919
|
+
function validateAskUserOptions(options, limits = DEFAULT_ASK_USER_LIMITS) {
|
|
6920
|
+
const errors = [];
|
|
6921
|
+
if (!Array.isArray(options)) {
|
|
6922
|
+
return { ok: false, errors: [{ path: "options", message: "must be an array" }] };
|
|
6923
|
+
}
|
|
6924
|
+
if (options.length === 0) {
|
|
6925
|
+
errors.push({ path: "options", message: "must contain at least one option" });
|
|
6926
|
+
}
|
|
6927
|
+
if (options.length > limits.maxOptions) {
|
|
6928
|
+
errors.push({
|
|
6929
|
+
path: "options",
|
|
6930
|
+
message: `max ${limits.maxOptions} options`
|
|
6931
|
+
});
|
|
6932
|
+
}
|
|
6933
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
6934
|
+
const seenValues = /* @__PURE__ */ new Set();
|
|
6935
|
+
options.forEach((opt, i) => {
|
|
6936
|
+
const o = opt;
|
|
6937
|
+
const path = `options[${i}]`;
|
|
6938
|
+
if (typeof o?.label !== "string" || o.label.length === 0) {
|
|
6939
|
+
errors.push({ path: `${path}.label`, message: "required string" });
|
|
6940
|
+
} else {
|
|
6941
|
+
if (o.label.length > limits.maxLabelChars) {
|
|
6942
|
+
errors.push({ path: `${path}.label`, message: `max ${limits.maxLabelChars} chars` });
|
|
6943
|
+
}
|
|
6944
|
+
if (seenLabels.has(o.label)) errors.push({ path: `${path}.label`, message: "duplicate label" });
|
|
6945
|
+
seenLabels.add(o.label);
|
|
6946
|
+
}
|
|
6947
|
+
if (typeof o?.value !== "string" || o.value.length === 0) {
|
|
6948
|
+
errors.push({ path: `${path}.value`, message: "required string" });
|
|
6949
|
+
} else {
|
|
6950
|
+
if (o.value.length > limits.maxValueChars) {
|
|
6951
|
+
errors.push({ path: `${path}.value`, message: `max ${limits.maxValueChars} chars` });
|
|
6952
|
+
}
|
|
6953
|
+
if (seenValues.has(o.value)) errors.push({ path: `${path}.value`, message: "duplicate value" });
|
|
6954
|
+
seenValues.add(o.value);
|
|
6955
|
+
}
|
|
6956
|
+
});
|
|
6957
|
+
return { ok: errors.length === 0, errors };
|
|
6958
|
+
}
|
|
6959
|
+
var auth, API_FETCH_TIMEOUT_MS, DEFAULT_ASK_USER_LIMITS;
|
|
6960
|
+
var init_ask_user_runtime = __esm({
|
|
6961
|
+
"src/ask-user-runtime.ts"() {
|
|
6962
|
+
"use strict";
|
|
6963
|
+
auth = { token: null, expiresAtEpochMs: 0 };
|
|
6964
|
+
API_FETCH_TIMEOUT_MS = 1e4;
|
|
6965
|
+
DEFAULT_ASK_USER_LIMITS = {
|
|
6966
|
+
maxOptions: 5,
|
|
6967
|
+
maxLabelChars: 75,
|
|
6968
|
+
maxValueChars: 2e3
|
|
6969
|
+
};
|
|
6970
|
+
}
|
|
6971
|
+
});
|
|
6972
|
+
|
|
6973
|
+
// src/slack-block-kit-runtime.ts
|
|
6974
|
+
var slack_block_kit_runtime_exports = {};
|
|
6975
|
+
__export(slack_block_kit_runtime_exports, {
|
|
6976
|
+
DEFAULT_ASK_USER_LIMITS: () => DEFAULT_ASK_USER_LIMITS,
|
|
6977
|
+
apiCall: () => apiCall,
|
|
6978
|
+
buildAskUserBlocks: () => buildAskUserBlocks,
|
|
6979
|
+
buildRatingActionsBlock: () => buildRatingActionsBlock,
|
|
6980
|
+
createPendingInteraction: () => createPendingInteraction,
|
|
6981
|
+
decodeActionId: () => decodeActionId,
|
|
6982
|
+
defaultRatingLabels: () => defaultRatingLabels,
|
|
6983
|
+
encodeActionId: () => encodeActionId,
|
|
6984
|
+
generateOptionToken: () => generateOptionToken,
|
|
6985
|
+
ratingValuesForScale: () => ratingValuesForScale,
|
|
6986
|
+
recordSlackDelivery: () => recordSlackDelivery,
|
|
6987
|
+
resolveInteractive: () => resolveInteractive,
|
|
6988
|
+
updatePendingInteractionMessageTs: () => updatePendingInteractionMessageTs,
|
|
6989
|
+
validateAskUserOptions: () => validateAskUserOptions,
|
|
6990
|
+
validateSlackBlocks: () => validateSlackBlocks,
|
|
6991
|
+
waitForResolution: () => waitForResolution
|
|
6992
|
+
});
|
|
6932
6993
|
function validateSlackBlocks(blocks) {
|
|
6933
6994
|
const errors = [];
|
|
6934
6995
|
const cap = 10;
|
|
@@ -6949,161 +7010,121 @@ function validateSlackBlocks(blocks) {
|
|
|
6949
7010
|
const path = `blocks[${i}]`;
|
|
6950
7011
|
const type = block?.type;
|
|
6951
7012
|
if (typeof type !== "string") {
|
|
6952
|
-
push(path, "
|
|
7013
|
+
push(path, "`type` is required and must be a string");
|
|
6953
7014
|
continue;
|
|
6954
7015
|
}
|
|
6955
7016
|
if (!SUPPORTED_BLOCK_TYPES.includes(type)) {
|
|
6956
|
-
push(path, `block type
|
|
7017
|
+
push(path, `unsupported block type "${type}" \u2014 supported: ${SUPPORTED_BLOCK_TYPES.join(", ")}`);
|
|
6957
7018
|
continue;
|
|
6958
7019
|
}
|
|
6959
|
-
if (typeof block.block_id === "string" && block.block_id.length > SLACK_LIMITS.identifierChars) {
|
|
7020
|
+
if ("block_id" in block && typeof block.block_id === "string" && block.block_id.length > SLACK_LIMITS.identifierChars) {
|
|
6960
7021
|
push(`${path}.block_id`, `max ${SLACK_LIMITS.identifierChars} chars`);
|
|
6961
7022
|
}
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
6966
|
-
case "section":
|
|
6967
|
-
validateSectionBlock(block, path, push);
|
|
6968
|
-
break;
|
|
6969
|
-
case "context":
|
|
6970
|
-
validateContextBlock(block, path, push);
|
|
6971
|
-
break;
|
|
6972
|
-
case "actions":
|
|
6973
|
-
validateActionsBlock(block, path, push);
|
|
6974
|
-
break;
|
|
6975
|
-
}
|
|
7023
|
+
if (type === "header") validateHeaderBlock(block, path, push);
|
|
7024
|
+
else if (type === "section") validateSectionBlock(block, path, push);
|
|
7025
|
+
else if (type === "context") validateContextBlock(block, path, push);
|
|
7026
|
+
else if (type === "actions") validateActionsBlock(block, path, push);
|
|
6976
7027
|
}
|
|
6977
7028
|
return { ok: errors.length === 0, errors };
|
|
6978
7029
|
}
|
|
6979
7030
|
function validateHeaderBlock(b, path, push) {
|
|
6980
7031
|
const text = b.text;
|
|
6981
|
-
if (!text
|
|
6982
|
-
push(`${path}.text`, "header
|
|
7032
|
+
if (!text) {
|
|
7033
|
+
push(`${path}.text`, "header requires a text object");
|
|
6983
7034
|
return;
|
|
6984
7035
|
}
|
|
6985
|
-
|
|
6986
|
-
push(`${path}.text.text`, `max ${SLACK_LIMITS.headerTextChars} chars`);
|
|
6987
|
-
}
|
|
7036
|
+
validateTextObject(text, `${path}.text`, SLACK_LIMITS.headerTextChars, ["plain_text"], push);
|
|
6988
7037
|
}
|
|
6989
7038
|
function validateSectionBlock(b, path, push) {
|
|
6990
|
-
const
|
|
6991
|
-
const
|
|
6992
|
-
if (!
|
|
6993
|
-
push(path, "section
|
|
7039
|
+
const text = b.text;
|
|
7040
|
+
const fields = b.fields;
|
|
7041
|
+
if (!text && !fields) {
|
|
7042
|
+
push(path, "section must have at least one of `text` or `fields`");
|
|
6994
7043
|
return;
|
|
6995
7044
|
}
|
|
6996
|
-
if (
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
if (
|
|
7003
|
-
push(`${path}.fields`, `max ${SLACK_LIMITS.sectionFields} fields
|
|
7045
|
+
if (text) {
|
|
7046
|
+
validateTextObject(text, `${path}.text`, SLACK_LIMITS.sectionTextChars, ["plain_text", "mrkdwn"], push);
|
|
7047
|
+
}
|
|
7048
|
+
if (fields) {
|
|
7049
|
+
if (!Array.isArray(fields)) {
|
|
7050
|
+
push(`${path}.fields`, "`fields` must be an array");
|
|
7051
|
+
} else if (fields.length > SLACK_LIMITS.sectionFields) {
|
|
7052
|
+
push(`${path}.fields`, `max ${SLACK_LIMITS.sectionFields} fields`);
|
|
7053
|
+
} else {
|
|
7054
|
+
fields.forEach((f, i) => {
|
|
7055
|
+
validateTextObject(f, `${path}.fields[${i}]`, SLACK_LIMITS.sectionFieldChars, ["plain_text", "mrkdwn"], push);
|
|
7056
|
+
});
|
|
7004
7057
|
}
|
|
7005
|
-
b.fields.forEach(
|
|
7006
|
-
(f, i) => validateTextObject(f, `${path}.fields[${i}]`, push, SLACK_LIMITS.sectionFieldChars)
|
|
7007
|
-
);
|
|
7008
7058
|
}
|
|
7009
7059
|
}
|
|
7010
7060
|
function validateContextBlock(b, path, push) {
|
|
7011
|
-
|
|
7012
|
-
|
|
7061
|
+
const elements = b.elements;
|
|
7062
|
+
if (!Array.isArray(elements) || elements.length === 0) {
|
|
7063
|
+
push(`${path}.elements`, "context requires non-empty `elements` array");
|
|
7013
7064
|
return;
|
|
7014
7065
|
}
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
);
|
|
7066
|
+
elements.forEach((el, i) => {
|
|
7067
|
+
validateTextObject(el, `${path}.elements[${i}]`, SLACK_LIMITS.sectionTextChars, ["plain_text", "mrkdwn"], push);
|
|
7068
|
+
});
|
|
7018
7069
|
}
|
|
7019
7070
|
function validateActionsBlock(b, path, push) {
|
|
7020
|
-
|
|
7021
|
-
|
|
7071
|
+
const elements = b.elements;
|
|
7072
|
+
if (!Array.isArray(elements) || elements.length === 0) {
|
|
7073
|
+
push(`${path}.elements`, "actions requires non-empty `elements` array");
|
|
7022
7074
|
return;
|
|
7023
7075
|
}
|
|
7024
|
-
if (
|
|
7025
|
-
push(`${path}.elements`, `max ${SLACK_LIMITS.actionElements}
|
|
7076
|
+
if (elements.length > SLACK_LIMITS.actionElements) {
|
|
7077
|
+
push(`${path}.elements`, `max ${SLACK_LIMITS.actionElements} elements`);
|
|
7026
7078
|
}
|
|
7027
|
-
|
|
7028
|
-
const
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
push(elPath, "element.type is required");
|
|
7079
|
+
elements.forEach((el, i) => {
|
|
7080
|
+
const type = el?.type;
|
|
7081
|
+
if (typeof type !== "string") {
|
|
7082
|
+
push(`${path}.elements[${i}]`, "each element must have a `type`");
|
|
7032
7083
|
return;
|
|
7033
7084
|
}
|
|
7034
|
-
if (!SUPPORTED_ACTION_ELEMENTS.includes(
|
|
7035
|
-
push(
|
|
7085
|
+
if (!SUPPORTED_ACTION_ELEMENTS.includes(type)) {
|
|
7086
|
+
push(`${path}.elements[${i}]`, `unsupported action element "${type}" \u2014 supported: ${SUPPORTED_ACTION_ELEMENTS.join(", ")}`);
|
|
7036
7087
|
return;
|
|
7037
7088
|
}
|
|
7038
|
-
if (
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7089
|
+
if (type === "button") {
|
|
7090
|
+
const text = el.text;
|
|
7091
|
+
if (!text) {
|
|
7092
|
+
push(`${path}.elements[${i}].text`, "button requires a text object");
|
|
7093
|
+
} else {
|
|
7094
|
+
validateTextObject(text, `${path}.elements[${i}].text`, SLACK_LIMITS.buttonLabelChars, ["plain_text"], push);
|
|
7095
|
+
}
|
|
7096
|
+
const actionId = el.action_id;
|
|
7097
|
+
if (typeof actionId !== "string" || actionId.length === 0) {
|
|
7098
|
+
push(`${path}.elements[${i}].action_id`, "button requires a non-empty `action_id`");
|
|
7099
|
+
} else if (actionId.length > SLACK_LIMITS.identifierChars) {
|
|
7100
|
+
push(`${path}.elements[${i}].action_id`, `max ${SLACK_LIMITS.identifierChars} chars`);
|
|
7101
|
+
}
|
|
7102
|
+
const value = el.value;
|
|
7103
|
+
if (value !== void 0) {
|
|
7104
|
+
if (typeof value !== "string") {
|
|
7105
|
+
push(`${path}.elements[${i}].value`, "`value` must be a string");
|
|
7106
|
+
} else if (value.length > SLACK_LIMITS.optionValueChars) {
|
|
7107
|
+
push(`${path}.elements[${i}].value`, `max ${SLACK_LIMITS.optionValueChars} chars`);
|
|
7108
|
+
}
|
|
7049
7109
|
}
|
|
7050
7110
|
}
|
|
7051
7111
|
});
|
|
7052
7112
|
}
|
|
7053
|
-
function validateTextObject(
|
|
7054
|
-
if (!
|
|
7055
|
-
push(path, "must be
|
|
7113
|
+
function validateTextObject(text, path, maxChars, allowedTypes, push) {
|
|
7114
|
+
if (!text || typeof text !== "object") {
|
|
7115
|
+
push(path, "must be an object with `type` and `text`");
|
|
7056
7116
|
return;
|
|
7057
7117
|
}
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
}
|
|
7062
|
-
if (typeof obj.text !== "string") {
|
|
7063
|
-
push(`${path}.text`, "must be a string");
|
|
7064
|
-
return;
|
|
7118
|
+
const t = text;
|
|
7119
|
+
if (typeof t.type !== "string" || !allowedTypes.includes(t.type)) {
|
|
7120
|
+
push(`${path}.type`, `must be one of: ${allowedTypes.join(", ")}`);
|
|
7065
7121
|
}
|
|
7066
|
-
if (
|
|
7067
|
-
push(`${path}.text`,
|
|
7122
|
+
if (typeof t.text !== "string" || t.text.length === 0) {
|
|
7123
|
+
push(`${path}.text`, "required non-empty string");
|
|
7124
|
+
} else if (t.text.length > maxChars) {
|
|
7125
|
+
push(`${path}.text`, `max ${maxChars} chars`);
|
|
7068
7126
|
}
|
|
7069
7127
|
}
|
|
7070
|
-
function validateAskUserOptions(options) {
|
|
7071
|
-
const errors = [];
|
|
7072
|
-
if (!Array.isArray(options)) {
|
|
7073
|
-
return { ok: false, errors: [{ path: "options", message: "must be an array" }] };
|
|
7074
|
-
}
|
|
7075
|
-
if (options.length === 0) {
|
|
7076
|
-
errors.push({ path: "options", message: "must contain at least one option" });
|
|
7077
|
-
}
|
|
7078
|
-
if (options.length > SLACK_LIMITS.actionElements) {
|
|
7079
|
-
errors.push({ path: "options", message: `max ${SLACK_LIMITS.actionElements} options (one Slack actions block)` });
|
|
7080
|
-
}
|
|
7081
|
-
const seenLabels = /* @__PURE__ */ new Set();
|
|
7082
|
-
const seenValues = /* @__PURE__ */ new Set();
|
|
7083
|
-
options.forEach((opt, i) => {
|
|
7084
|
-
const o = opt;
|
|
7085
|
-
const path = `options[${i}]`;
|
|
7086
|
-
if (typeof o?.label !== "string" || o.label.length === 0) {
|
|
7087
|
-
errors.push({ path: `${path}.label`, message: "required string" });
|
|
7088
|
-
} else {
|
|
7089
|
-
if (o.label.length > SLACK_LIMITS.buttonLabelChars) {
|
|
7090
|
-
errors.push({ path: `${path}.label`, message: `max ${SLACK_LIMITS.buttonLabelChars} chars` });
|
|
7091
|
-
}
|
|
7092
|
-
if (seenLabels.has(o.label)) errors.push({ path: `${path}.label`, message: "duplicate label" });
|
|
7093
|
-
seenLabels.add(o.label);
|
|
7094
|
-
}
|
|
7095
|
-
if (typeof o?.value !== "string" || o.value.length === 0) {
|
|
7096
|
-
errors.push({ path: `${path}.value`, message: "required string" });
|
|
7097
|
-
} else {
|
|
7098
|
-
if (o.value.length > SLACK_LIMITS.optionValueChars) {
|
|
7099
|
-
errors.push({ path: `${path}.value`, message: `max ${SLACK_LIMITS.optionValueChars} chars` });
|
|
7100
|
-
}
|
|
7101
|
-
if (seenValues.has(o.value)) errors.push({ path: `${path}.value`, message: "duplicate value" });
|
|
7102
|
-
seenValues.add(o.value);
|
|
7103
|
-
}
|
|
7104
|
-
});
|
|
7105
|
-
return { ok: errors.length === 0, errors };
|
|
7106
|
-
}
|
|
7107
7128
|
function encodeActionId(callbackId, token) {
|
|
7108
7129
|
return `aug:${callbackId}:${token}`;
|
|
7109
7130
|
}
|
|
@@ -7174,12 +7195,12 @@ async function recordSlackDelivery(cfg, input) {
|
|
|
7174
7195
|
throw new Error(`recordSlackDelivery failed (${res.status}): ${body.slice(0, 200)}`);
|
|
7175
7196
|
}
|
|
7176
7197
|
}
|
|
7177
|
-
var
|
|
7198
|
+
var SLACK_LIMITS, SUPPORTED_BLOCK_TYPES, SUPPORTED_ACTION_ELEMENTS, ACTION_ID_RE;
|
|
7178
7199
|
var init_slack_block_kit_runtime = __esm({
|
|
7179
7200
|
"src/slack-block-kit-runtime.ts"() {
|
|
7180
7201
|
"use strict";
|
|
7181
|
-
|
|
7182
|
-
|
|
7202
|
+
init_ask_user_runtime();
|
|
7203
|
+
init_ask_user_runtime();
|
|
7183
7204
|
SLACK_LIMITS = {
|
|
7184
7205
|
blocksPerMessage: 50,
|
|
7185
7206
|
sectionTextChars: 3e3,
|
|
@@ -14930,6 +14951,81 @@ function createCrossTeamPeerAuditClient(args) {
|
|
|
14930
14951
|
};
|
|
14931
14952
|
}
|
|
14932
14953
|
|
|
14954
|
+
// src/slack-bot-user-id-client.ts
|
|
14955
|
+
var REQUEST_TIMEOUT_MS2 = 1e4;
|
|
14956
|
+
function createSlackBotUserIdClient(args) {
|
|
14957
|
+
if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
|
|
14958
|
+
const fetchImpl = args.fetchImpl ?? fetch;
|
|
14959
|
+
const log = args.log ?? (() => {
|
|
14960
|
+
});
|
|
14961
|
+
const base = args.agtHost.replace(/\/+$/, "");
|
|
14962
|
+
const agentId = args.agentId;
|
|
14963
|
+
const apiKey = args.agtApiKey;
|
|
14964
|
+
let reportedFor = null;
|
|
14965
|
+
let cachedToken = null;
|
|
14966
|
+
let cachedTokenExpiresAt = 0;
|
|
14967
|
+
async function getToken() {
|
|
14968
|
+
if (cachedToken && Date.now() < cachedTokenExpiresAt) return cachedToken;
|
|
14969
|
+
const resp = await fetchImpl(`${base}/host/exchange`, {
|
|
14970
|
+
method: "POST",
|
|
14971
|
+
headers: { "Content-Type": "application/json" },
|
|
14972
|
+
body: JSON.stringify({ host_key: apiKey }),
|
|
14973
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
14974
|
+
});
|
|
14975
|
+
if (!resp.ok) {
|
|
14976
|
+
const body = await resp.text().catch(() => "");
|
|
14977
|
+
throw new Error(`/host/exchange failed (${resp.status}): ${body.slice(0, 200)}`);
|
|
14978
|
+
}
|
|
14979
|
+
const data = await resp.json();
|
|
14980
|
+
cachedToken = data.token;
|
|
14981
|
+
cachedTokenExpiresAt = data.expires_at ? new Date(data.expires_at).getTime() - 12e4 : Date.now() + 55 * 6e4;
|
|
14982
|
+
return cachedToken;
|
|
14983
|
+
}
|
|
14984
|
+
async function postOnce(botUserId2) {
|
|
14985
|
+
const token = await getToken();
|
|
14986
|
+
return fetchImpl(`${base}/host/slack-bot-user-id`, {
|
|
14987
|
+
method: "POST",
|
|
14988
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
14989
|
+
body: JSON.stringify({ agent_id: agentId, bot_user_id: botUserId2 }),
|
|
14990
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
14991
|
+
});
|
|
14992
|
+
}
|
|
14993
|
+
async function emitAsync(botUserId2) {
|
|
14994
|
+
try {
|
|
14995
|
+
let resp = await postOnce(botUserId2);
|
|
14996
|
+
if (resp.status === 401) {
|
|
14997
|
+
cachedToken = null;
|
|
14998
|
+
cachedTokenExpiresAt = 0;
|
|
14999
|
+
resp = await postOnce(botUserId2);
|
|
15000
|
+
}
|
|
15001
|
+
if (!resp.ok) {
|
|
15002
|
+
const body = await resp.text().catch(() => "");
|
|
15003
|
+
log(
|
|
15004
|
+
`slack-bot-user-id: POST failed (${resp.status}) user=${botUserId2}: ${body.slice(0, 200)}`
|
|
15005
|
+
);
|
|
15006
|
+
return false;
|
|
15007
|
+
}
|
|
15008
|
+
return true;
|
|
15009
|
+
} catch (err) {
|
|
15010
|
+
log(`slack-bot-user-id: emit threw user=${botUserId2}: ${err.message}`);
|
|
15011
|
+
return false;
|
|
15012
|
+
}
|
|
15013
|
+
}
|
|
15014
|
+
return {
|
|
15015
|
+
report(botUserId2) {
|
|
15016
|
+
if (reportedFor === botUserId2) return;
|
|
15017
|
+
const snapshot = botUserId2;
|
|
15018
|
+
reportedFor = snapshot;
|
|
15019
|
+
void emitAsync(botUserId2).then((ok) => {
|
|
15020
|
+
if (ok) return;
|
|
15021
|
+
if (reportedFor === snapshot) {
|
|
15022
|
+
reportedFor = null;
|
|
15023
|
+
}
|
|
15024
|
+
});
|
|
15025
|
+
}
|
|
15026
|
+
};
|
|
15027
|
+
}
|
|
15028
|
+
|
|
14933
15029
|
// src/slack-channel.ts
|
|
14934
15030
|
var BOT_TOKEN = process.env.SLACK_BOT_TOKEN;
|
|
14935
15031
|
var APP_TOKEN = process.env.SLACK_APP_TOKEN;
|
|
@@ -15658,6 +15754,14 @@ var botUserId = await resolveBotUserIdOrThrow();
|
|
|
15658
15754
|
var botUserIdForLog = `${botUserId.slice(0, 2)}***${botUserId.slice(-2)}`;
|
|
15659
15755
|
process.stderr.write(`slack-channel: Bot user ID resolved (${botUserIdForLog})
|
|
15660
15756
|
`);
|
|
15757
|
+
var slackBotUserIdClient = createSlackBotUserIdClient({
|
|
15758
|
+
agtHost: AGT_HOST,
|
|
15759
|
+
agtApiKey: AGT_API_KEY,
|
|
15760
|
+
agentId: AGT_AGENT_ID,
|
|
15761
|
+
log: (line) => process.stderr.write(`slack-channel: ${line}
|
|
15762
|
+
`)
|
|
15763
|
+
});
|
|
15764
|
+
slackBotUserIdClient?.report(botUserId);
|
|
15661
15765
|
var selfIdentityInstruction = `Your own Slack user_id is ${botUserId}. Treat <@${botUserId}> mentions as directed at you, even inside auto_followed threads.`;
|
|
15662
15766
|
var mcp = new Server(
|
|
15663
15767
|
{ name: "slack", version: "0.1.0" },
|
|
@@ -16372,6 +16476,9 @@ function askUserToolAvailable() {
|
|
|
16372
16476
|
function interactiveHostAvailable() {
|
|
16373
16477
|
return blockKitToolsAvailable() && Boolean(AGT_HOST && AGT_API_KEY && AGT_AGENT_ID);
|
|
16374
16478
|
}
|
|
16479
|
+
function forwardingHostAvailable() {
|
|
16480
|
+
return Boolean(AGT_HOST && AGT_API_KEY && AGT_AGENT_ID);
|
|
16481
|
+
}
|
|
16375
16482
|
async function postSlackMessageWithTs(payload) {
|
|
16376
16483
|
try {
|
|
16377
16484
|
const res = await fetch("https://slack.com/api/chat.postMessage", {
|
|
@@ -16856,9 +16963,9 @@ async function connectSocketMode() {
|
|
|
16856
16963
|
return;
|
|
16857
16964
|
}
|
|
16858
16965
|
if (msg.type === "interactive" && msg.payload?.type === "block_actions") {
|
|
16859
|
-
if (!
|
|
16966
|
+
if (!forwardingHostAvailable()) {
|
|
16860
16967
|
process.stderr.write(
|
|
16861
|
-
`slack-channel(${AGENT_CODE_NAME}): block_actions received but
|
|
16968
|
+
`slack-channel(${AGENT_CODE_NAME}): block_actions received but host MCP wiring missing (AGT_HOST/AGT_API_KEY/AGT_AGENT_ID) \u2014 dropping
|
|
16862
16969
|
`
|
|
16863
16970
|
);
|
|
16864
16971
|
return;
|