@integrity-labs/agt-cli 0.28.833 → 0.28.835
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/assets/review/obiwan-auth.mjs +215 -0
- package/dist/assets/review/post-review-findings.mjs +539 -0
- package/dist/bin/agt.js +3 -3
- package/dist/{chunk-LGVB4OTX.js → chunk-REBHUZ7N.js} +2 -2
- package/dist/lib/manager-worker.js +400 -347
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/computer-use-proxy.js +285 -0
- package/package.json +3 -3
- /package/dist/{chunk-LGVB4OTX.js.map → chunk-REBHUZ7N.js.map} +0 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __augmentedCreateRequire } from 'module';
|
|
3
|
+
globalThis.require ??= __augmentedCreateRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
// src/computer-use-proxy.ts
|
|
6
|
+
import { createInterface } from "readline";
|
|
7
|
+
import { spawn } from "child_process";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
import { resolve as resolvePath } from "path";
|
|
10
|
+
var INCLUDE_SCREENSHOT_PARAM = "include_screenshot";
|
|
11
|
+
var STRIPPED_IMAGE_STUB = `[screenshot omitted to save tokens \u2014 pass ${INCLUDE_SCREENSHOT_PARAM}: true to receive it. Element indices in the accessibility tree above are usually enough to act.]`;
|
|
12
|
+
var RELIABILITY_NOTE = `
|
|
13
|
+
|
|
14
|
+
IMPORTANT: isError:false does NOT mean this action took effect. Some key combinations are silently ignored (super+n opens a window; super+a returns the same isError:false and does nothing). Verify by comparing the accessibility tree in this response against what you expected \u2014 it reflects the state after the action. set_value with an empty string is a no-op.`;
|
|
15
|
+
function isImageBlock(block) {
|
|
16
|
+
return typeof block === "object" && block !== null && block.type === "image";
|
|
17
|
+
}
|
|
18
|
+
var WINDOW_FURNITURE_ROLES = [
|
|
19
|
+
"container",
|
|
20
|
+
"standard window",
|
|
21
|
+
"close button",
|
|
22
|
+
"minimise button",
|
|
23
|
+
"minimize button",
|
|
24
|
+
"zoom button",
|
|
25
|
+
"full screen button",
|
|
26
|
+
"menu bar"
|
|
27
|
+
];
|
|
28
|
+
function treeHasActionableContent(text) {
|
|
29
|
+
if (typeof text !== "string") return false;
|
|
30
|
+
let skipDeeperThan = null;
|
|
31
|
+
for (const raw of text.split("\n")) {
|
|
32
|
+
const m = /^(\s*)(\d+) (.+)$/.exec(raw);
|
|
33
|
+
if (!m) continue;
|
|
34
|
+
const indent = m[1].length;
|
|
35
|
+
const rest = m[3].toLowerCase();
|
|
36
|
+
if (skipDeeperThan !== null) {
|
|
37
|
+
if (indent > skipDeeperThan) continue;
|
|
38
|
+
skipDeeperThan = null;
|
|
39
|
+
}
|
|
40
|
+
if (rest.startsWith("menu bar")) {
|
|
41
|
+
skipDeeperThan = indent;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (WINDOW_FURNITURE_ROLES.some((role) => rest.startsWith(role))) continue;
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
function stripImages(result) {
|
|
50
|
+
if (typeof result !== "object" || result === null) return { result, stripped: 0 };
|
|
51
|
+
const content = result.content;
|
|
52
|
+
if (!Array.isArray(content)) return { result, stripped: 0 };
|
|
53
|
+
if (!content.some(isImageBlock)) return { result, stripped: 0 };
|
|
54
|
+
const next = [];
|
|
55
|
+
let stripped = 0;
|
|
56
|
+
for (const block of content) {
|
|
57
|
+
if (isImageBlock(block)) {
|
|
58
|
+
stripped += 1;
|
|
59
|
+
next.push({ type: "text", text: STRIPPED_IMAGE_STUB });
|
|
60
|
+
} else {
|
|
61
|
+
next.push(block);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { result: { ...result, content: next }, stripped };
|
|
65
|
+
}
|
|
66
|
+
function decorateToolsList(result) {
|
|
67
|
+
if (typeof result !== "object" || result === null) return result;
|
|
68
|
+
const tools = result.tools;
|
|
69
|
+
if (!Array.isArray(tools)) return result;
|
|
70
|
+
const decorated = tools.map((tool) => {
|
|
71
|
+
if (typeof tool !== "object" || tool === null) return tool;
|
|
72
|
+
const t = tool;
|
|
73
|
+
const schema = t["inputSchema"] ?? {};
|
|
74
|
+
const props = schema["properties"] ?? {};
|
|
75
|
+
return {
|
|
76
|
+
...t,
|
|
77
|
+
description: `${typeof t["description"] === "string" ? t["description"] : ""}${RELIABILITY_NOTE}`,
|
|
78
|
+
inputSchema: {
|
|
79
|
+
...schema,
|
|
80
|
+
type: schema["type"] ?? "object",
|
|
81
|
+
properties: {
|
|
82
|
+
...props,
|
|
83
|
+
[INCLUDE_SCREENSHOT_PARAM]: {
|
|
84
|
+
type: "boolean",
|
|
85
|
+
description: "Return the screenshot for this call. Omitted by default: it is ~99% of the response and element indices in the accessibility tree are usually enough to act on."
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
return { ...result, tools: decorated };
|
|
92
|
+
}
|
|
93
|
+
function takeIncludeScreenshot(params) {
|
|
94
|
+
if (typeof params !== "object" || params === null) return { include: false, params };
|
|
95
|
+
const p = params;
|
|
96
|
+
if (typeof p.arguments !== "object" || p.arguments === null) {
|
|
97
|
+
return { include: false, params };
|
|
98
|
+
}
|
|
99
|
+
const args = p.arguments;
|
|
100
|
+
if (!(INCLUDE_SCREENSHOT_PARAM in args)) return { include: false, params };
|
|
101
|
+
const { [INCLUDE_SCREENSHOT_PARAM]: raw, ...rest } = args;
|
|
102
|
+
return { include: raw === true, params: { ...params, arguments: rest } };
|
|
103
|
+
}
|
|
104
|
+
function logErr(msg) {
|
|
105
|
+
process.stderr.write(`[computer-use-proxy] ${msg}
|
|
106
|
+
`);
|
|
107
|
+
}
|
|
108
|
+
var allowAll = async () => null;
|
|
109
|
+
function createProxy(deps) {
|
|
110
|
+
const beforeForward = deps.beforeForward ?? allowAll;
|
|
111
|
+
const pending = /* @__PURE__ */ new Map();
|
|
112
|
+
async function handleDownstream(line) {
|
|
113
|
+
const text = line.trim();
|
|
114
|
+
if (!text) return [];
|
|
115
|
+
let frame;
|
|
116
|
+
try {
|
|
117
|
+
frame = JSON.parse(text);
|
|
118
|
+
} catch {
|
|
119
|
+
logErr("dropping non-JSON frame from client");
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
if (frame.method !== "tools/call") {
|
|
123
|
+
return [text];
|
|
124
|
+
}
|
|
125
|
+
const isRequest = "id" in frame;
|
|
126
|
+
const { include, params } = takeIncludeScreenshot(frame.params);
|
|
127
|
+
const toolName = typeof params?.name === "string" ? params.name : "";
|
|
128
|
+
const args = params?.arguments;
|
|
129
|
+
const short = await beforeForward(toolName, args);
|
|
130
|
+
if (short) {
|
|
131
|
+
if (!isRequest) {
|
|
132
|
+
logErr(`short-circuited notification tools/call ${toolName} (no reply sent)`);
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
return [JSON.stringify({ jsonrpc: "2.0", id: frame.id, result: short })];
|
|
136
|
+
}
|
|
137
|
+
if (isRequest) {
|
|
138
|
+
pending.set(String(frame.id), { method: "tools/call", includeScreenshot: include });
|
|
139
|
+
}
|
|
140
|
+
return [JSON.stringify({ ...frame, params })];
|
|
141
|
+
}
|
|
142
|
+
async function handleUpstream(line) {
|
|
143
|
+
const text = line.trim();
|
|
144
|
+
if (!text) return [];
|
|
145
|
+
let frame;
|
|
146
|
+
try {
|
|
147
|
+
frame = JSON.parse(text);
|
|
148
|
+
} catch {
|
|
149
|
+
logErr("dropping non-JSON frame from upstream");
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
if (!("id" in frame)) return [text];
|
|
153
|
+
const key = String(frame.id);
|
|
154
|
+
if (frame.result === void 0) {
|
|
155
|
+
pending.delete(key);
|
|
156
|
+
return [text];
|
|
157
|
+
}
|
|
158
|
+
const p = pending.get(key);
|
|
159
|
+
if (!p) {
|
|
160
|
+
const decorated = decorateToolsList(frame.result);
|
|
161
|
+
if (decorated !== frame.result) {
|
|
162
|
+
return [JSON.stringify({ ...frame, result: decorated })];
|
|
163
|
+
}
|
|
164
|
+
return [text];
|
|
165
|
+
}
|
|
166
|
+
pending.delete(key);
|
|
167
|
+
if (p.includeScreenshot) return [text];
|
|
168
|
+
const firstText = frame.result?.content;
|
|
169
|
+
if (Array.isArray(firstText)) {
|
|
170
|
+
const treeBlock = firstText.find(
|
|
171
|
+
(b) => typeof b === "object" && b !== null && b.type === "text"
|
|
172
|
+
);
|
|
173
|
+
if (treeBlock && !treeHasActionableContent(treeBlock.text)) {
|
|
174
|
+
logErr("tree carries no actionable content; keeping screenshot");
|
|
175
|
+
return [text];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const { result, stripped } = stripImages(frame.result);
|
|
179
|
+
if (stripped === 0) return [text];
|
|
180
|
+
return [JSON.stringify({ ...frame, result })];
|
|
181
|
+
}
|
|
182
|
+
return { handleDownstream, handleUpstream };
|
|
183
|
+
}
|
|
184
|
+
function createWriter(sink) {
|
|
185
|
+
let lock = Promise.resolve();
|
|
186
|
+
return (lines) => {
|
|
187
|
+
lock = lock.then(async () => {
|
|
188
|
+
try {
|
|
189
|
+
for (const line of lines) {
|
|
190
|
+
if (!sink.write(line + "\n")) {
|
|
191
|
+
await new Promise((res) => sink.once("drain", res));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
} catch (err) {
|
|
195
|
+
logErr(`write failed: ${err.message}`);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
return lock;
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async function wirePump(deps) {
|
|
202
|
+
const { child, clientIn, clientOut, proxy } = deps;
|
|
203
|
+
const exit = deps.onExit ?? ((code) => process.exit(code));
|
|
204
|
+
const toUpstream = createWriter(child.stdin);
|
|
205
|
+
const toClient = createWriter(clientOut);
|
|
206
|
+
child.stdin.on("error", (err) => {
|
|
207
|
+
logErr(`upstream stdin: ${err.message}`);
|
|
208
|
+
});
|
|
209
|
+
return new Promise((resolve) => {
|
|
210
|
+
let settled = false;
|
|
211
|
+
const finish = async (code) => {
|
|
212
|
+
if (settled) return;
|
|
213
|
+
settled = true;
|
|
214
|
+
await toClient([]);
|
|
215
|
+
exit(code);
|
|
216
|
+
resolve();
|
|
217
|
+
};
|
|
218
|
+
child.on("error", (err) => {
|
|
219
|
+
logErr(`upstream error: ${err.message}`);
|
|
220
|
+
void finish(1);
|
|
221
|
+
});
|
|
222
|
+
child.on("exit", (code) => {
|
|
223
|
+
logErr(`upstream exited with code ${code ?? "null"}`);
|
|
224
|
+
void finish(code ?? 1);
|
|
225
|
+
});
|
|
226
|
+
createInterface({ input: clientIn, crlfDelay: Infinity }).on("line", (line) => {
|
|
227
|
+
void proxy.handleDownstream(line).then(toUpstream).catch((err) => logErr(`downstream handler: ${err.message}`));
|
|
228
|
+
}).on("close", () => {
|
|
229
|
+
logErr("client disconnected; terminating upstream");
|
|
230
|
+
child.kill("SIGTERM");
|
|
231
|
+
void finish(0);
|
|
232
|
+
});
|
|
233
|
+
createInterface({ input: child.stdout, crlfDelay: Infinity }).on("line", (line) => {
|
|
234
|
+
void proxy.handleUpstream(line).then(toClient).catch((err) => logErr(`upstream handler: ${err.message}`));
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
async function main(argv = process.argv) {
|
|
239
|
+
const sep = argv.indexOf("--");
|
|
240
|
+
const upstream = sep >= 0 ? argv.slice(sep + 1) : [];
|
|
241
|
+
if (upstream.length === 0) {
|
|
242
|
+
logErr("no upstream command; usage: computer-use-proxy -- <cmd> [args...]");
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
let child;
|
|
246
|
+
try {
|
|
247
|
+
child = spawn(upstream[0], upstream.slice(1), { stdio: ["pipe", "pipe", "inherit"] });
|
|
248
|
+
} catch (err) {
|
|
249
|
+
logErr(`failed to spawn upstream: ${err.message}`);
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
await wirePump({
|
|
253
|
+
child,
|
|
254
|
+
clientIn: process.stdin,
|
|
255
|
+
clientOut: process.stdout,
|
|
256
|
+
proxy: createProxy({ upstream })
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
var invokedDirectly = (() => {
|
|
260
|
+
try {
|
|
261
|
+
const entry = process.argv[1];
|
|
262
|
+
if (!entry) return false;
|
|
263
|
+
return fileURLToPath(import.meta.url) === resolvePath(entry);
|
|
264
|
+
} catch {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
})();
|
|
268
|
+
if (invokedDirectly) {
|
|
269
|
+
void main();
|
|
270
|
+
}
|
|
271
|
+
export {
|
|
272
|
+
INCLUDE_SCREENSHOT_PARAM,
|
|
273
|
+
RELIABILITY_NOTE,
|
|
274
|
+
STRIPPED_IMAGE_STUB,
|
|
275
|
+
allowAll,
|
|
276
|
+
createProxy,
|
|
277
|
+
createWriter,
|
|
278
|
+
decorateToolsList,
|
|
279
|
+
isImageBlock,
|
|
280
|
+
main,
|
|
281
|
+
stripImages,
|
|
282
|
+
takeIncludeScreenshot,
|
|
283
|
+
treeHasActionableContent,
|
|
284
|
+
wirePump
|
|
285
|
+
};
|
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.835",
|
|
4
4
|
"description": "Augmented Team CLI — agent provisioning and management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -23,8 +23,8 @@
|
|
|
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/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 && cp ../../packages/augmented-support-mcp/dist/index.js dist/mcp/augmented-support.js && cp ../../packages/augmented-help-kb-mcp/dist/index.js dist/mcp/augmented-help-kb.js && cp ../../packages/origami-mcp-server/dist/index.js dist/mcp/origami.js && cp ../../packages/xero-mcp-server/dist/index.js dist/mcp/xero.js",
|
|
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",
|
|
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/mcp/dist/computer-use-proxy.js dist/mcp/computer-use-proxy.js && cp ../../packages/augmented-admin-mcp/dist/index.js dist/mcp/augmented-admin.js && cp ../../packages/augmented-support-mcp/dist/index.js dist/mcp/augmented-support.js && cp ../../packages/augmented-help-kb-mcp/dist/index.js dist/mcp/augmented-help-kb.js && cp ../../packages/origami-mcp-server/dist/index.js dist/mcp/origami.js && cp ../../packages/xero-mcp-server/dist/index.js dist/mcp/xero.js",
|
|
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 && mkdir -p dist/assets/review && cp assets/review/post-review-findings.mjs dist/assets/review/post-review-findings.mjs && cp assets/review/obiwan-auth.mjs dist/assets/review/obiwan-auth.mjs && chmod +x dist/assets/review/post-review-findings.mjs",
|
|
28
28
|
"dev": "tsx watch src/bin/agt.ts",
|
|
29
29
|
"test": "vitest run",
|
|
30
30
|
"typecheck": "bash ../../scripts/typecheck-guard.sh tsc --noEmit",
|
|
File without changes
|