@integrity-labs/agt-cli 0.28.150 → 0.28.151
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-LCKA5XPX.js → chunk-SZX4F3O5.js} +54 -10
- package/dist/chunk-SZX4F3O5.js.map +1 -0
- package/dist/lib/manager-worker.js +8 -3
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/remote-oauth-proxy.js +168 -0
- package/package.json +2 -2
- package/dist/chunk-LCKA5XPX.js.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __augmentedCreateRequire } from 'module';
|
|
3
|
+
globalThis.require ??= __augmentedCreateRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
// src/remote-oauth-proxy.ts
|
|
6
|
+
import { createInterface } from "readline";
|
|
7
|
+
import { readFileSync } from "fs";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
import { resolve as resolvePath } from "path";
|
|
10
|
+
var URL_ENV = "AGT_REMOTE_MCP_URL";
|
|
11
|
+
var TOKEN_FILE_ENV = "AGT_REMOTE_MCP_TOKEN_FILE";
|
|
12
|
+
var TOKEN_VAR_ENV = "AGT_REMOTE_MCP_TOKEN_VAR";
|
|
13
|
+
var REMOTE_FETCH_TIMEOUT_MS = 3e4;
|
|
14
|
+
var remoteUrl = process.env[URL_ENV] ?? "";
|
|
15
|
+
var tokenFile = process.env[TOKEN_FILE_ENV] ?? "";
|
|
16
|
+
var tokenVar = process.env[TOKEN_VAR_ENV] ?? "";
|
|
17
|
+
var label = process.env["AGT_REMOTE_MCP_LABEL"] || tokenVar || "remote-oauth";
|
|
18
|
+
function logErr(msg) {
|
|
19
|
+
process.stderr.write(`[remote-oauth-proxy:${label}] ${msg}
|
|
20
|
+
`);
|
|
21
|
+
}
|
|
22
|
+
function readCurrentToken(file, varName) {
|
|
23
|
+
let raw;
|
|
24
|
+
try {
|
|
25
|
+
raw = readFileSync(file, "utf8");
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
let value = null;
|
|
30
|
+
for (const line of raw.split("\n")) {
|
|
31
|
+
const trimmed = line.trim();
|
|
32
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
33
|
+
const eq = trimmed.indexOf("=");
|
|
34
|
+
if (eq < 0) continue;
|
|
35
|
+
const key = trimmed.slice(0, eq).replace(/^export\s+/, "").trim();
|
|
36
|
+
if (key !== varName) continue;
|
|
37
|
+
let v = trimmed.slice(eq + 1).trim();
|
|
38
|
+
if (v.length >= 2 && (v[0] === '"' && v[v.length - 1] === '"' || v[0] === "'" && v[v.length - 1] === "'")) {
|
|
39
|
+
v = v.slice(1, -1);
|
|
40
|
+
}
|
|
41
|
+
value = v;
|
|
42
|
+
}
|
|
43
|
+
return value && value.length > 0 ? value : null;
|
|
44
|
+
}
|
|
45
|
+
function jsonRpcError(id, code, message) {
|
|
46
|
+
return JSON.stringify({ jsonrpc: "2.0", id: id ?? null, error: { code, message } });
|
|
47
|
+
}
|
|
48
|
+
function extractJsonRpcMessages(contentType, body) {
|
|
49
|
+
const ct = (contentType || "").toLowerCase();
|
|
50
|
+
const out = [];
|
|
51
|
+
if (ct.includes("text/event-stream")) {
|
|
52
|
+
for (const line of body.split("\n")) {
|
|
53
|
+
const t = line.trimEnd();
|
|
54
|
+
if (!t.startsWith("data:")) continue;
|
|
55
|
+
const payload = t.slice(5).trim();
|
|
56
|
+
if (!payload || payload === "[DONE]") continue;
|
|
57
|
+
try {
|
|
58
|
+
JSON.parse(payload);
|
|
59
|
+
out.push(payload);
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
const trimmed = body.trim();
|
|
66
|
+
if (!trimmed) return out;
|
|
67
|
+
try {
|
|
68
|
+
JSON.parse(trimmed);
|
|
69
|
+
out.push(trimmed);
|
|
70
|
+
} catch {
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
async function forward(line, id, isNotification) {
|
|
75
|
+
const token = readCurrentToken(tokenFile, tokenVar);
|
|
76
|
+
if (!token) {
|
|
77
|
+
logErr(`no token in ${tokenFile} (var ${tokenVar})`);
|
|
78
|
+
return isNotification ? [] : [jsonRpcError(id, -32e3, `${label}: no current access token available (reconnect the integration)`)];
|
|
79
|
+
}
|
|
80
|
+
let res;
|
|
81
|
+
try {
|
|
82
|
+
res = await fetch(remoteUrl, {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: {
|
|
85
|
+
"Content-Type": "application/json",
|
|
86
|
+
Accept: "application/json, text/event-stream",
|
|
87
|
+
Authorization: `Bearer ${token}`
|
|
88
|
+
},
|
|
89
|
+
body: line,
|
|
90
|
+
signal: AbortSignal.timeout(REMOTE_FETCH_TIMEOUT_MS)
|
|
91
|
+
});
|
|
92
|
+
} catch (err) {
|
|
93
|
+
logErr(`fetch failed: ${err.message}`);
|
|
94
|
+
return isNotification ? [] : [jsonRpcError(id, -32001, `${label}: transport error contacting MCP server`)];
|
|
95
|
+
}
|
|
96
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
97
|
+
let body = "";
|
|
98
|
+
try {
|
|
99
|
+
body = await res.text();
|
|
100
|
+
} catch {
|
|
101
|
+
body = "";
|
|
102
|
+
}
|
|
103
|
+
if (isNotification) return [];
|
|
104
|
+
const messages = extractJsonRpcMessages(ct, body);
|
|
105
|
+
if (messages.length > 0) return messages;
|
|
106
|
+
const detail = body.slice(0, 300).replace(/\s+/g, " ").trim();
|
|
107
|
+
return [jsonRpcError(id, -32002, `${label}: MCP server returned HTTP ${res.status}${detail ? ` (${detail})` : ""}`)];
|
|
108
|
+
}
|
|
109
|
+
function isMissingConfig() {
|
|
110
|
+
if (!remoteUrl) return URL_ENV;
|
|
111
|
+
if (!tokenFile) return TOKEN_FILE_ENV;
|
|
112
|
+
if (!tokenVar) return TOKEN_VAR_ENV;
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
async function main() {
|
|
116
|
+
const missing = isMissingConfig();
|
|
117
|
+
if (missing) {
|
|
118
|
+
logErr(`missing required env ${missing}; exiting`);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
const rl = createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
122
|
+
let writeLock = Promise.resolve();
|
|
123
|
+
const writeReplies = (replies) => {
|
|
124
|
+
writeLock = writeLock.then(() => {
|
|
125
|
+
for (const reply of replies) process.stdout.write(reply + "\n");
|
|
126
|
+
});
|
|
127
|
+
return writeLock;
|
|
128
|
+
};
|
|
129
|
+
const inflight = /* @__PURE__ */ new Set();
|
|
130
|
+
rl.on("line", (line) => {
|
|
131
|
+
const text = line.trim();
|
|
132
|
+
if (!text) return;
|
|
133
|
+
let parsed;
|
|
134
|
+
try {
|
|
135
|
+
parsed = JSON.parse(text);
|
|
136
|
+
} catch {
|
|
137
|
+
logErr("dropping non-JSON stdin line");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const isNotification = !("id" in parsed);
|
|
141
|
+
const id = parsed.id;
|
|
142
|
+
const task = forward(text, id, isNotification).then(writeReplies).catch((err) => {
|
|
143
|
+
logErr(`handler error: ${err.message}`);
|
|
144
|
+
});
|
|
145
|
+
inflight.add(task);
|
|
146
|
+
void task.finally(() => inflight.delete(task));
|
|
147
|
+
});
|
|
148
|
+
await new Promise((resolve) => rl.on("close", () => resolve()));
|
|
149
|
+
await Promise.all([...inflight]);
|
|
150
|
+
await writeLock;
|
|
151
|
+
}
|
|
152
|
+
var invokedDirectly = (() => {
|
|
153
|
+
try {
|
|
154
|
+
const entry = process.argv[1];
|
|
155
|
+
if (!entry) return false;
|
|
156
|
+
return fileURLToPath(import.meta.url) === resolvePath(entry);
|
|
157
|
+
} catch {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
})();
|
|
161
|
+
if (invokedDirectly) {
|
|
162
|
+
void main();
|
|
163
|
+
}
|
|
164
|
+
export {
|
|
165
|
+
extractJsonRpcMessages,
|
|
166
|
+
main,
|
|
167
|
+
readCurrentToken
|
|
168
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@integrity-labs/agt-cli",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.151",
|
|
4
4
|
"description": "Augmented Team CLI — agent provisioning and management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsup && npm run build:mcp-assets && npm run build:cli-assets",
|
|
26
|
-
"build:mcp-assets": "mkdir -p dist/mcp && cp ../../packages/mcp/dist/index.js dist/mcp/index.js && cp ../../packages/mcp/dist/slack-channel.js dist/mcp/slack-channel.js && cp ../../packages/mcp/dist/direct-chat-channel.js dist/mcp/direct-chat-channel.js && cp ../../packages/mcp/dist/telegram-channel.js dist/mcp/telegram-channel.js && cp ../../packages/mcp/dist/teams-channel.js dist/mcp/teams-channel.js && cp ../../packages/mcp/dist/whatsapp-channel.js dist/mcp/whatsapp-channel.js && cp ../../packages/mcp/dist/whatsapp-link.js dist/mcp/whatsapp-link.js && cp ../../packages/augmented-admin-mcp/dist/index.js dist/mcp/augmented-admin.js",
|
|
26
|
+
"build:mcp-assets": "mkdir -p dist/mcp && cp ../../packages/mcp/dist/index.js dist/mcp/index.js && cp ../../packages/mcp/dist/slack-channel.js dist/mcp/slack-channel.js && cp ../../packages/mcp/dist/direct-chat-channel.js dist/mcp/direct-chat-channel.js && cp ../../packages/mcp/dist/telegram-channel.js dist/mcp/telegram-channel.js && cp ../../packages/mcp/dist/teams-channel.js dist/mcp/teams-channel.js && cp ../../packages/mcp/dist/whatsapp-channel.js dist/mcp/whatsapp-channel.js && cp ../../packages/mcp/dist/whatsapp-link.js dist/mcp/whatsapp-link.js && cp ../../packages/mcp/dist/remote-oauth-proxy.js dist/mcp/remote-oauth-proxy.js && cp ../../packages/augmented-admin-mcp/dist/index.js dist/mcp/augmented-admin.js",
|
|
27
27
|
"build:cli-assets": "mkdir -p dist/assets && cp assets/impersonate-statusline.sh dist/assets/impersonate-statusline.sh && chmod +x dist/assets/impersonate-statusline.sh",
|
|
28
28
|
"dev": "tsx watch src/bin/agt.ts",
|
|
29
29
|
"test": "vitest run",
|