eve-hub 0.14.5 → 0.14.6
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/CHANGELOG.md +6 -0
- package/kit-modules.json +1 -0
- package/package.json +1 -1
- package/stubs.mjs +2 -1
- package/tools/fetch_upload.d.ts +18 -0
- package/tools/fetch_upload.js +40 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# eve-hub
|
|
2
2
|
|
|
3
|
+
## 0.14.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- New `fetch_upload` tool: a bot copies a file another bot shared as a `hub://upload/<id>` link into its sandbox (for example a patch to `git apply`), with the hub credential its kit tools already send. A shell can't fetch these links: the hosted hub's Deployment Protection sends it to a login page.
|
|
8
|
+
|
|
3
9
|
## 0.14.5
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/kit-modules.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve-hub",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.6",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Bot-side code shared by every hub agent: registry tools, the roster hook, the eve channel, the host sandbox and browser, and model helpers.",
|
|
6
6
|
"type": "module",
|
package/stubs.mjs
CHANGED
|
@@ -10,6 +10,7 @@ export const KIT_FILES = {
|
|
|
10
10
|
"tools/react.ts": ["React to a message with an emoji."],
|
|
11
11
|
"tools/show.ts": ["Move the human's screen to a thread, DM, or message, or open a page or file beside the thread."],
|
|
12
12
|
"tools/browser.ts": ["Its own headless browser, watched live in the Computer view."],
|
|
13
|
+
"tools/fetch_upload.ts": ["Copies a file another bot shared (hub://upload/<id>) into the sandbox."],
|
|
13
14
|
"tools/view_image.ts": ["Shows the bot an image (a sandbox file or a browser screenshot) so it can see it."],
|
|
14
15
|
"tools/update_thread.ts": ["Update a thread this bot is in: title, track, domain and summary."],
|
|
15
16
|
"tools/list_threads.ts": ["Every workspace thread, from any session."],
|
|
@@ -57,7 +58,7 @@ export const DEPLOYED_KIT_FILES = new Set([
|
|
|
57
58
|
"schedules/dash.ts",
|
|
58
59
|
"skills/onboarding-profile.ts",
|
|
59
60
|
"tools/onboarding_scripts.ts",
|
|
60
|
-
...["react", "show", "update_thread", "list_threads", "read_thread", "post_message"].map((t) => `tools/${t}.ts`),
|
|
61
|
+
...["react", "show", "fetch_upload", "update_thread", "list_threads", "read_thread", "post_message"].map((t) => `tools/${t}.ts`),
|
|
61
62
|
"memory/team.ts",
|
|
62
63
|
"skills/forms.ts",
|
|
63
64
|
...["create_thread", "set_summary", "move_path", "archive_thread", "unarchive_thread", "list_agents", "create_agent", "remove_agent", "restart_agent", "tag_threads", "dash_update", "apply_tags"].map((t) => `tools/${t}.ts`),
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare const _default: import("eve/tools").ToolDefinition<{
|
|
2
|
+
uri: string;
|
|
3
|
+
path?: string | undefined;
|
|
4
|
+
}, {
|
|
5
|
+
path: string;
|
|
6
|
+
size: number;
|
|
7
|
+
mediaType: string | null;
|
|
8
|
+
}> & {
|
|
9
|
+
execute(input: {
|
|
10
|
+
uri: string;
|
|
11
|
+
path?: string | undefined;
|
|
12
|
+
}, ctx: import("eve/tools").ToolContext): Promise<{
|
|
13
|
+
path: string;
|
|
14
|
+
size: number;
|
|
15
|
+
mediaType: string | null;
|
|
16
|
+
}>;
|
|
17
|
+
};
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// The `fetch_upload` tool: copies a file another bot shared (`hub://upload/<id>`, what
|
|
2
|
+
// `show(path)` returns on a hosted hub) into this bot's sandbox, e.g. a patch to `git apply`.
|
|
3
|
+
// A shell can't fetch it: the hosted hub's Deployment Protection and its auth take only the bot
|
|
4
|
+
// credential that registryFetch sends (registry-fetch.mjs).
|
|
5
|
+
import { defineTool } from "eve/tools";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { registryFetch } from "../registry-fetch.mjs";
|
|
8
|
+
const UPLOAD = /^hub:\/\/upload\/([0-9a-f]{64}\.[a-z0-9]{1,10})$/;
|
|
9
|
+
export default defineTool({
|
|
10
|
+
description: "Fetch a file another bot shared as a hub://upload/<id> link (e.g. a patch, a log, a brief) into your sandbox, then read or apply it there. Your shell can't fetch these links; this tool sends your hub credential. Returns the path it wrote, the size in bytes and the media type.",
|
|
11
|
+
inputSchema: z.object({
|
|
12
|
+
uri: z.string().describe("The hub://upload/<id> link."),
|
|
13
|
+
path: z.string().optional().describe("Where to write it in your sandbox. Default /tmp/uploads/<id>."),
|
|
14
|
+
}),
|
|
15
|
+
async execute({ uri, path }, ctx) {
|
|
16
|
+
const id = UPLOAD.exec(uri.trim())?.[1];
|
|
17
|
+
if (!id)
|
|
18
|
+
throw new Error(`not a hub://upload/<id> link: ${uri}`);
|
|
19
|
+
// A redirect is Deployment Protection sending the request to a login page: an error, not the file.
|
|
20
|
+
const res = await registryFetch(`/api/uploads/${id}`, { redirect: "manual", signal: AbortSignal.timeout(30_000) });
|
|
21
|
+
if (!res.ok) {
|
|
22
|
+
const text = await res.text();
|
|
23
|
+
// Deployment Protection answers with a whole HTML page: name the redirect, or keep the body short.
|
|
24
|
+
const error = (() => { try {
|
|
25
|
+
return JSON.parse(text).error;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return undefined;
|
|
29
|
+
} })();
|
|
30
|
+
const location = res.headers.get("location");
|
|
31
|
+
const why = error ?? (location ? `redirected to ${location}` : text.slice(0, 200));
|
|
32
|
+
throw new Error(`fetch_upload failed: ${res.status} ${why}`.trim());
|
|
33
|
+
}
|
|
34
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
35
|
+
const sandbox = await ctx.getSandbox();
|
|
36
|
+
const target = path ?? `/tmp/uploads/${id}`;
|
|
37
|
+
await sandbox.writeBinaryFile({ path: target, content: bytes });
|
|
38
|
+
return { path: sandbox.resolvePath(target), size: bytes.length, mediaType: res.headers.get("content-type") };
|
|
39
|
+
},
|
|
40
|
+
});
|