@gaunt-sloth/tools 0.0.1 → 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 +8 -0
- package/dist/middleware/frontendImageInjectionMiddleware.d.ts +15 -0
- package/dist/middleware/frontendImageInjectionMiddleware.js +72 -0
- package/dist/middleware/frontendImageInjectionMiddleware.js.map +1 -0
- package/dist/tools/captureImageTool.d.ts +2 -0
- package/dist/tools/captureImageTool.js +16 -0
- package/dist/tools/captureImageTool.js.map +1 -0
- package/package.json +20 -4
package/README.md
CHANGED
|
@@ -23,3 +23,11 @@ Tools and middleware for Gaunt Sloth.
|
|
|
23
23
|
import { builtInToolsConfig } from '@gaunt-sloth/tools/builtInToolsConfig.js';
|
|
24
24
|
import { resolveMiddleware } from '@gaunt-sloth/tools/middleware/registry.js';
|
|
25
25
|
```
|
|
26
|
+
|
|
27
|
+
## Related packages
|
|
28
|
+
|
|
29
|
+
- [`@gaunt-sloth/core`](../core) — Core utilities, config, and agent infrastructure
|
|
30
|
+
- [`@gaunt-sloth/tools`](../tools) — Built-in tools, filesystem toolkit, and middleware registry (this package)
|
|
31
|
+
- [`@gaunt-sloth/api`](../api) — API server, AG-UI, MCP, and A2A integration
|
|
32
|
+
- [`@gaunt-sloth/review`](../review) — Review and Q&A modules with standalone CLI
|
|
33
|
+
- [`gaunt-sloth-assistant`](../assistant) — Main CLI application
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* Middleware to inject camera frames (images) as HumanMessage.
|
|
4
|
+
*
|
|
5
|
+
* This middleware:
|
|
6
|
+
* 1. Detects the capture_image tool calls
|
|
7
|
+
* 2. Parses the JSON payload from ToolMessage content
|
|
8
|
+
* 3. Injects HumanMessage with image blocks before next model call
|
|
9
|
+
*/
|
|
10
|
+
import { type AgentMiddleware } from 'langchain';
|
|
11
|
+
import type { GthConfig } from '@gaunt-sloth/core/config.js';
|
|
12
|
+
export interface FrontendImageInjectionMiddlewareSettings {
|
|
13
|
+
name?: 'frontend-image-injection';
|
|
14
|
+
}
|
|
15
|
+
export declare function createFrontendImageInjectionMiddleware(_settings: FrontendImageInjectionMiddlewareSettings, _gthConfig: GthConfig): Promise<AgentMiddleware>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* Middleware to inject camera frames (images) as HumanMessage.
|
|
4
|
+
*
|
|
5
|
+
* This middleware:
|
|
6
|
+
* 1. Detects the capture_image tool calls
|
|
7
|
+
* 2. Parses the JSON payload from ToolMessage content
|
|
8
|
+
* 3. Injects HumanMessage with image blocks before next model call
|
|
9
|
+
*/
|
|
10
|
+
import { createMiddleware } from 'langchain';
|
|
11
|
+
import { debugLog } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
12
|
+
import { ToolMessage, HumanMessage } from '@langchain/core/messages';
|
|
13
|
+
export function createFrontendImageInjectionMiddleware(_settings, _gthConfig) {
|
|
14
|
+
debugLog('Creating frontend image injection middleware');
|
|
15
|
+
return Promise.resolve(createMiddleware({
|
|
16
|
+
name: 'frontend-image-injection',
|
|
17
|
+
beforeModel: async (state) => {
|
|
18
|
+
const messages = state.messages || [];
|
|
19
|
+
// Find recent ToolMessages from capture_image
|
|
20
|
+
const imageMessages = [];
|
|
21
|
+
for (let i = messages.length - 1; i >= Math.max(0, messages.length - 5); i--) {
|
|
22
|
+
const msg = messages[i];
|
|
23
|
+
if (msg instanceof ToolMessage &&
|
|
24
|
+
msg.name === 'capture_image' &&
|
|
25
|
+
typeof msg.content === 'string') {
|
|
26
|
+
try {
|
|
27
|
+
const payload = JSON.parse(msg.content);
|
|
28
|
+
imageMessages.push({ message: msg, payload });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Ignore invalid JSON
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// If we found image content, inject HumanMessage(s)
|
|
36
|
+
if (imageMessages.length > 0) {
|
|
37
|
+
debugLog(`Injecting ${imageMessages.length} HumanMessage(s) from capture_image`);
|
|
38
|
+
const newMessages = [...messages];
|
|
39
|
+
for (const { payload } of imageMessages) {
|
|
40
|
+
if (payload.error) {
|
|
41
|
+
newMessages.push(new HumanMessage({
|
|
42
|
+
content: `Camera unavailable: ${payload.error}`
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
else if (payload.mimeType && payload.data) {
|
|
46
|
+
const contentBlock = {
|
|
47
|
+
type: 'image',
|
|
48
|
+
source_type: 'base64',
|
|
49
|
+
mime_type: payload.mimeType,
|
|
50
|
+
data: payload.data,
|
|
51
|
+
};
|
|
52
|
+
const humanMessage = new HumanMessage({
|
|
53
|
+
content: [
|
|
54
|
+
{
|
|
55
|
+
type: 'text',
|
|
56
|
+
text: `Camera frame captured:`,
|
|
57
|
+
},
|
|
58
|
+
contentBlock,
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
newMessages.push(humanMessage);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (newMessages.length > messages.length) {
|
|
65
|
+
return { messages: newMessages };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
},
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=frontendImageInjectionMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontendImageInjectionMiddleware.js","sourceRoot":"","sources":["../../src/middleware/frontendImageInjectionMiddleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,gBAAgB,EAAwB,MAAM,WAAW,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAOrE,MAAM,UAAU,sCAAsC,CACpD,SAAmD,EACnD,UAAqB;IAErB,QAAQ,CAAC,8CAA8C,CAAC,CAAC;IAEzD,OAAO,OAAO,CAAC,OAAO,CACpB,gBAAgB,CAAC;QACf,IAAI,EAAE,0BAA0B;QAEhC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;YAEtC,8CAA8C;YAC9C,MAAM,aAAa,GAAkD,EAAE,CAAC;YAExE,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7E,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACxB,IACE,GAAG,YAAY,WAAW;oBAC1B,GAAG,CAAC,IAAI,KAAK,eAAe;oBAC5B,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAC/B,CAAC;oBACD,IAAI,CAAC;wBACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;wBACxC,aAAa,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;oBAChD,CAAC;oBAAC,MAAM,CAAC;wBACP,sBAAsB;oBACxB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,oDAAoD;YACpD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,QAAQ,CAAC,aAAa,aAAa,CAAC,MAAM,qCAAqC,CAAC,CAAC;gBAEjF,MAAM,WAAW,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;gBAElC,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,EAAE,CAAC;oBACxC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;wBAClB,WAAW,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC;4BAChC,OAAO,EAAE,uBAAuB,OAAO,CAAC,KAAK,EAAE;yBAChD,CAAC,CAAC,CAAC;oBACN,CAAC;yBAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;wBAC5C,MAAM,YAAY,GAAG;4BACnB,IAAI,EAAE,OAAO;4BACb,WAAW,EAAE,QAAQ;4BACrB,SAAS,EAAE,OAAO,CAAC,QAAQ;4BAC3B,IAAI,EAAE,OAAO,CAAC,IAAI;yBACnB,CAAC;wBAEF,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC;4BACpC,OAAO,EAAE;gCACP;oCACE,IAAI,EAAE,MAAM;oCACZ,IAAI,EAAE,wBAAwB;iCAC/B;gCACD,YAAY;6BACK;yBACpB,CAAC,CAAC;wBAEH,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;oBACjC,CAAC;gBACH,CAAC;gBAED,IAAI,WAAW,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;oBACzC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;gBACnC,CAAC;YACH,CAAC;YAED,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { tool } from '@langchain/core/tools';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
export function get() {
|
|
4
|
+
const t = tool(async () => {
|
|
5
|
+
// This is a stub that will be overridden by GthLangChainAgent for client: true tools
|
|
6
|
+
return 'Client tool stub executed on server';
|
|
7
|
+
}, {
|
|
8
|
+
name: 'capture_image',
|
|
9
|
+
description: 'Capture a photo from the robot webcam. Returns a base64 encoded image frame.',
|
|
10
|
+
schema: z.object({}),
|
|
11
|
+
});
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
t.metadata = { client: true };
|
|
14
|
+
return t;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=captureImageTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captureImageTool.js","sourceRoot":"","sources":["../../src/tools/captureImageTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,UAAU,GAAG;IACjB,MAAM,CAAC,GAAG,IAAI,CACZ,KAAK,IAAI,EAAE;QACT,qFAAqF;QACrF,OAAO,qCAAqC,CAAC;IAC/C,CAAC,EACD;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,8EAA8E;QAC3F,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;KACrB,CACF,CAAC;IACF,8DAA8D;IAC7D,CAAS,CAAC,QAAQ,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACvC,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaunt-sloth/tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Tools and middleware for Gaunt Sloth",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Andrew Kondratev",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Galvanized-Pukeko/gaunt-sloth-assistant.git",
|
|
10
|
+
"directory": "packages/tools"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Galvanized-Pukeko/gaunt-sloth-assistant/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/Galvanized-Pukeko/gaunt-sloth-assistant/tree/main/packages/tools#readme",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"agent",
|
|
19
|
+
"llm",
|
|
20
|
+
"tools",
|
|
21
|
+
"middleware"
|
|
22
|
+
],
|
|
7
23
|
"type": "module",
|
|
8
24
|
"main": "dist/index.js",
|
|
9
25
|
"types": "dist/index.d.ts",
|
|
@@ -18,9 +34,9 @@
|
|
|
18
34
|
"#src/*.js": "./dist/*.js"
|
|
19
35
|
},
|
|
20
36
|
"dependencies": {
|
|
21
|
-
"@gaunt-sloth/core": "
|
|
22
|
-
"diff": "^
|
|
23
|
-
"langchain": "^1.
|
|
37
|
+
"@gaunt-sloth/core": "0.1.1",
|
|
38
|
+
"diff": "^9.0.0",
|
|
39
|
+
"langchain": "^1.3.5"
|
|
24
40
|
},
|
|
25
41
|
"files": [
|
|
26
42
|
"./dist/*"
|