@unboundai/tb-ppt-mgagent 0.1.0 → 0.1.1
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 +26 -4
- package/build/index.js +19 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,9 @@ Built against the official Managed Agents docs (session creation, session operat
|
|
|
15
15
|
|
|
16
16
|
## What's still an assumption
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Every SDK call in `src/index.ts` (`sessions.create`, `sessions.events.send`, `sessions.retrieve`, `sessions.events.list`, `files.list`, `files.download`) is checked against `@anthropic-ai/sdk`'s own `.d.ts`/source (installed version, not just the docs prose) — that's how a real bug was caught in 0.1.0: the docs' TypeScript sample for downloading a file shows `content.writeToFile(path)`, but that method doesn't exist on the installed SDK. `files.download()` actually resolves to a plain `Response`; 0.1.1 fixes this by reading it with `.arrayBuffer()` and writing the bytes directly.
|
|
19
|
+
|
|
20
|
+
The one thing still **not** confirmed against a real response is the exact `filename`/path convention the Files API returns for a file the agent wrote to its outputs directory — the code guesses by matching `/outputs?[\/]/i` against the filename and falling back to any `.pptx` file on the session if nothing matches that pattern. If a real run's file list looks different, adjust the filter in `get_tb_powerpoint_result` in `src/index.ts`.
|
|
19
21
|
|
|
20
22
|
## Setup
|
|
21
23
|
|
|
@@ -37,13 +39,14 @@ Everything above matches the documented API and SDK method signatures verbatim (
|
|
|
37
39
|
- `TB_PPT_OUTPUT_DIR` — required for `get_tb_powerpoint_result`. Local folder that's synced to GCS by something outside this server; finished `.pptx` files are written here.
|
|
38
40
|
- `TB_PPT_PUBLIC_URL_BASE` — required for `get_tb_powerpoint_result`. Base URL the synced folder is served from (e.g. `https://storage.googleapis.com/bucket/prefix`), used to build the returned download link.
|
|
39
41
|
|
|
40
|
-
4. **Register with your MCP client** (Claude Desktop / TypingMind's local MCP connector — same pattern as this repo's siblings, e.g. `tb-gcs-assembly-mcp`):
|
|
42
|
+
4. **Register with your MCP client** (Claude Desktop / TypingMind's local MCP connector — same pattern as this repo's siblings, e.g. `tb-gcs-assembly-mcp`). Published to npm as [`@unboundai/tb-ppt-mgagent`](https://www.npmjs.com/package/@unboundai/tb-ppt-mgagent), so `npx` can run it without a local checkout:
|
|
41
43
|
|
|
42
44
|
```json
|
|
43
45
|
"tb-ppt-mgagent": {
|
|
44
|
-
"command": "
|
|
46
|
+
"command": "npx",
|
|
45
47
|
"args": [
|
|
46
|
-
"
|
|
48
|
+
"-y",
|
|
49
|
+
"@unboundai/tb-ppt-mgagent"
|
|
47
50
|
],
|
|
48
51
|
"env": {
|
|
49
52
|
"ANTHROPIC_API_KEY": "sk-ant-...",
|
|
@@ -55,6 +58,25 @@ Everything above matches the documented API and SDK method signatures verbatim (
|
|
|
55
58
|
}
|
|
56
59
|
```
|
|
57
60
|
|
|
61
|
+
Or, from a local checkout of this repo:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
"tb-ppt-mgagent": {
|
|
65
|
+
"command": "node",
|
|
66
|
+
"args": [
|
|
67
|
+
"/path/to/tb-ppt-mgAgent/build/index.js"
|
|
68
|
+
],
|
|
69
|
+
"env": { "...": "same as above" }
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Publishing a new version
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm version patch # or minor/major
|
|
77
|
+
npm publish # prepublishOnly rebuilds automatically; will prompt for a 2FA OTP
|
|
78
|
+
```
|
|
79
|
+
|
|
58
80
|
## Development
|
|
59
81
|
|
|
60
82
|
```bash
|
package/build/index.js
CHANGED
|
@@ -19,11 +19,13 @@
|
|
|
19
19
|
* automatically for session endpoints. The Files API additionally takes an
|
|
20
20
|
* explicit `betas` array on list/download, per the docs' own example.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
22
|
+
* Every call here is checked against @anthropic-ai/sdk's own .d.ts/source
|
|
23
|
+
* (v0.120.0, the latest published at the time of writing) rather than taken
|
|
24
|
+
* on faith from the docs prose - the docs' TypeScript sample for downloading
|
|
25
|
+
* a file shows `content.writeToFile(path)`, but that method does not exist
|
|
26
|
+
* on the installed SDK: `files.download()` resolves to a plain `Response`,
|
|
27
|
+
* read with `.arrayBuffer()` below. If a future SDK version reintroduces a
|
|
28
|
+
* writeToFile-style helper, this can simplify back down.
|
|
27
29
|
*
|
|
28
30
|
* Environment variables:
|
|
29
31
|
* - ANTHROPIC_API_KEY: required. Anthropic API key with Managed Agents access.
|
|
@@ -218,16 +220,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
218
220
|
};
|
|
219
221
|
}
|
|
220
222
|
// Find the most recent session.status_idle event to read its stop_reason.
|
|
221
|
-
// (Its exact field shape isn't pinned down in our TS types yet - see file header.)
|
|
222
223
|
let latestIdleEvent = null;
|
|
223
224
|
for await (const event of client.beta.sessions.events.list(sessionId)) {
|
|
224
225
|
if (event.type === "session.status_idle") {
|
|
225
|
-
if (!latestIdleEvent ||
|
|
226
|
+
if (!latestIdleEvent || event.processed_at > latestIdleEvent.processed_at) {
|
|
226
227
|
latestIdleEvent = event;
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
230
|
}
|
|
230
|
-
const stopReasonType = latestIdleEvent?.stop_reason
|
|
231
|
+
const stopReasonType = latestIdleEvent?.stop_reason.type;
|
|
231
232
|
if (stopReasonType !== "end_turn") {
|
|
232
233
|
return {
|
|
233
234
|
content: [{
|
|
@@ -246,9 +247,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
246
247
|
scope_id: sessionId,
|
|
247
248
|
betas: [MANAGED_AGENTS_BETA]
|
|
248
249
|
});
|
|
249
|
-
const fileList = files.data
|
|
250
|
-
const pptxFiles = fileList.filter((f) => /\.pptx$/i.test(f.filename
|
|
251
|
-
const outputPptxFiles = pptxFiles.filter((f) => /outputs?[\\/]/i.test(f.filename
|
|
250
|
+
const fileList = files.data;
|
|
251
|
+
const pptxFiles = fileList.filter((f) => /\.pptx$/i.test(f.filename));
|
|
252
|
+
const outputPptxFiles = pptxFiles.filter((f) => /outputs?[\\/]/i.test(f.filename));
|
|
252
253
|
const chosen = outputPptxFiles[0] ?? pptxFiles[0];
|
|
253
254
|
if (!chosen) {
|
|
254
255
|
return {
|
|
@@ -267,9 +268,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
267
268
|
const { outputDir, publicUrlBase } = requireOutputConfig();
|
|
268
269
|
const safeName = path.basename(chosen.filename || `${sessionId}.pptx`);
|
|
269
270
|
const destPath = path.join(outputDir, safeName);
|
|
271
|
+
// files.download() resolves to a plain Response on this SDK version - no
|
|
272
|
+
// writeToFile() helper (see file header). Read the bytes and write them ourselves.
|
|
273
|
+
const response = await client.beta.files.download(chosen.id, {
|
|
274
|
+
betas: [MANAGED_AGENTS_BETA]
|
|
275
|
+
});
|
|
276
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
270
277
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
271
|
-
|
|
272
|
-
await content.writeToFile(destPath);
|
|
278
|
+
fs.writeFileSync(destPath, Buffer.from(arrayBuffer));
|
|
273
279
|
const downloadUrl = `${publicUrlBase.replace(/\/$/, "")}/${encodeURIComponent(safeName)}`;
|
|
274
280
|
return {
|
|
275
281
|
content: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unboundai/tb-ppt-mgagent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "MCP server that hands a presentation outline to the Traffic Builders PowerPoint Managed Agent, then retrieves the finished .pptx",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"bin": {
|