@byted-las/contextlake-openclaw 1.0.9 → 1.0.14
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/index.js +1 -1
- package/dist/src/commands/cli.d.ts +3 -0
- package/dist/src/commands/cli.js +88 -0
- package/dist/src/commands/index.js +51 -0
- package/dist/src/commands/slashcmd.d.ts +9 -0
- package/dist/src/commands/slashcmd.js +108 -0
- package/index.ts +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -3
- package/src/commands/cli.ts +95 -0
- package/src/commands/index.ts +70 -11
- package/src/commands/slashcmd.ts +119 -0
- package/src/commands/tools.ts +16 -11
- package/src/lib/actions/las-tools.ts +9 -0
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const commands_1 = require("./src/commands");
|
|
|
4
4
|
const plugin = {
|
|
5
5
|
id: 'contextlake-openclaw',
|
|
6
6
|
name: 'ContextLake',
|
|
7
|
-
version: '1.0.
|
|
7
|
+
version: '1.0.12',
|
|
8
8
|
description: 'A lightweight knowledge base plugin for OpenClaw using LanceDB and TOS, with data profiling support',
|
|
9
9
|
configSchema: {
|
|
10
10
|
type: 'object',
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { ContextLakeConfig } from '../utils/config';
|
|
2
2
|
export declare function getCliCommands(pluginConfig: ContextLakeConfig, logger: any): {
|
|
3
|
+
listS3ObjectsAction: (url: string, options: any) => Promise<void>;
|
|
4
|
+
readS3ObjectAction: (url: string, options: any) => Promise<void>;
|
|
5
|
+
generatePresignedUrlAction: (url: string, options: any) => Promise<void>;
|
|
3
6
|
searchAction: (query: any, options: any) => Promise<void>;
|
|
4
7
|
listAction: (options: any) => Promise<void>;
|
|
5
8
|
deleteAction: (options: any) => Promise<void>;
|
package/dist/src/commands/cli.js
CHANGED
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getCliCommands = getCliCommands;
|
|
4
4
|
const retrieve_1 = require("../lib/actions/retrieve");
|
|
5
5
|
const manage_1 = require("../lib/actions/manage");
|
|
6
|
+
const las_tools_1 = require("../lib/actions/las-tools");
|
|
7
|
+
const s3_tools_1 = require("../lib/actions/s3-tools");
|
|
6
8
|
const credentials_1 = require("../utils/credentials");
|
|
7
9
|
function parseOptionalInt(value, fallback) {
|
|
8
10
|
const parsed = Number.parseInt(String(value), 10);
|
|
@@ -30,7 +32,93 @@ function parseMetadata(metadata) {
|
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
function getCliCommands(pluginConfig, logger) {
|
|
35
|
+
const lasTools = (0, las_tools_1.getLasTools)(pluginConfig, logger);
|
|
36
|
+
const lasActions = {};
|
|
37
|
+
for (const tool of lasTools) {
|
|
38
|
+
lasActions[`${tool.name}Action`] = async (dataStr) => {
|
|
39
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI ${tool.name} started`);
|
|
40
|
+
try {
|
|
41
|
+
let data = {};
|
|
42
|
+
try {
|
|
43
|
+
data = JSON.parse(dataStr);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
// if it's not valid JSON and the tool accepts a simple string/url, try to handle it.
|
|
47
|
+
// But LAS tools typically require a data object.
|
|
48
|
+
data = { url: dataStr };
|
|
49
|
+
}
|
|
50
|
+
let params = tool.name === 'las_bare_image_text_embedding'
|
|
51
|
+
? data
|
|
52
|
+
: { data };
|
|
53
|
+
const result = await tool.execute('cli', params);
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.log(JSON.stringify(result, null, 2));
|
|
56
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI ${tool.name} success`);
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
console.error('Error:', e.message);
|
|
60
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] CLI ${tool.name} failed`, { error: e.message, stack: e.stack });
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
33
64
|
return {
|
|
65
|
+
...lasActions,
|
|
66
|
+
listS3ObjectsAction: async (url, options) => {
|
|
67
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI list-s3-objects started`, { url, options });
|
|
68
|
+
try {
|
|
69
|
+
// Parse prefix from URL if present
|
|
70
|
+
let prefix = '';
|
|
71
|
+
if (url && !url.startsWith('file://')) {
|
|
72
|
+
try {
|
|
73
|
+
const parsedUrl = new URL(url);
|
|
74
|
+
prefix = parsedUrl.pathname.replace(/^\//, '');
|
|
75
|
+
// Reconstruct url without path to pass to listS3Objects as base url
|
|
76
|
+
url = `${parsedUrl.protocol}//${parsedUrl.host}`;
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
// ignore, leave url as is
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const result = await (0, s3_tools_1.listS3Objects)({ url }, prefix, parseOptionalInt(options.maxKeys, 1000), options.continuationToken);
|
|
83
|
+
// eslint-disable-next-line no-console
|
|
84
|
+
console.log(JSON.stringify(result, null, 2));
|
|
85
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI list-s3-objects success`);
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
console.error('Error:', e.message);
|
|
89
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] CLI list-s3-objects failed`, { error: e.message, stack: e.stack });
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
readS3ObjectAction: async (url, options) => {
|
|
93
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI read-s3-object started`, { url, options });
|
|
94
|
+
try {
|
|
95
|
+
const parsedUrl = new URL(url);
|
|
96
|
+
const key = parsedUrl.pathname.replace(/^\//, '');
|
|
97
|
+
const result = await (0, s3_tools_1.readS3Object)({ url }, key, options.maxBytes ? parseOptionalInt(options.maxBytes, 0) : undefined);
|
|
98
|
+
// eslint-disable-next-line no-console
|
|
99
|
+
console.log(result.toString('utf-8'));
|
|
100
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI read-s3-object success`);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
console.error('Error:', e.message);
|
|
104
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] CLI read-s3-object failed`, { error: e.message, stack: e.stack });
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
generatePresignedUrlAction: async (url, options) => {
|
|
108
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI generate-presigned-url started`, { url, options });
|
|
109
|
+
try {
|
|
110
|
+
const parsedUrl = new URL(url);
|
|
111
|
+
const key = parsedUrl.pathname.replace(/^\//, '');
|
|
112
|
+
const result = await (0, s3_tools_1.getPresignedUrl)({ url }, key, parseOptionalInt(options.expiresIn, 3600));
|
|
113
|
+
// eslint-disable-next-line no-console
|
|
114
|
+
console.log(result);
|
|
115
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI generate-presigned-url success`);
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
console.error('Error:', e.message);
|
|
119
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] CLI generate-presigned-url failed`, { error: e.message, stack: e.stack });
|
|
120
|
+
}
|
|
121
|
+
},
|
|
34
122
|
searchAction: async (query, options) => {
|
|
35
123
|
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI search started`, { query, options });
|
|
36
124
|
try {
|
|
@@ -67,6 +67,29 @@ function registerAll(ctx, logger) {
|
|
|
67
67
|
contextlake.command('onboard')
|
|
68
68
|
.description('Configure credentials for ContextLake')
|
|
69
69
|
.action(commands.onboardAction);
|
|
70
|
+
// S3 Tools
|
|
71
|
+
contextlake.command('list-s3-objects <url>')
|
|
72
|
+
.description('List objects in an S3-compatible bucket or local directory')
|
|
73
|
+
.option('--max-keys <number>', 'Maximum number of keys to return', '1000')
|
|
74
|
+
.option('--continuation-token <string>', 'Continuation token for pagination')
|
|
75
|
+
.action(commands.listS3ObjectsAction);
|
|
76
|
+
contextlake.command('read-s3-object <url>')
|
|
77
|
+
.description('Read the contents of an S3 object')
|
|
78
|
+
.option('--max-bytes <number>', 'Maximum number of bytes to read')
|
|
79
|
+
.action(commands.readS3ObjectAction);
|
|
80
|
+
contextlake.command('generate-presigned-url <url>')
|
|
81
|
+
.description('Generate a presigned HTTP URL for an S3/TOS object')
|
|
82
|
+
.option('--expires-in <number>', 'Expiration time in seconds', '3600')
|
|
83
|
+
.action(commands.generatePresignedUrlAction);
|
|
84
|
+
// LAS Tools
|
|
85
|
+
const tools = (0, tools_1.getAgentTools)(pluginConfig, logger);
|
|
86
|
+
const lasTools = tools.lasTools;
|
|
87
|
+
for (const tool of lasTools) {
|
|
88
|
+
const cmdName = tool.name.replace(/_/g, '-');
|
|
89
|
+
contextlake.command(`${cmdName} <data>`)
|
|
90
|
+
.description(tool.label)
|
|
91
|
+
.action(commands[`${tool.name}Action`]);
|
|
92
|
+
}
|
|
70
93
|
}, { commands: ['contextlake'] });
|
|
71
94
|
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI commands registered`);
|
|
72
95
|
}
|
|
@@ -105,6 +128,34 @@ function registerAll(ctx, logger) {
|
|
|
105
128
|
acceptsArgs: false,
|
|
106
129
|
handler: slashCommands.listDatasourceHandler
|
|
107
130
|
});
|
|
131
|
+
ctx.registerCommand({
|
|
132
|
+
name: 'contextlake-list-s3-objects',
|
|
133
|
+
description: 'List objects in an S3-compatible bucket or local directory',
|
|
134
|
+
acceptsArgs: true,
|
|
135
|
+
handler: slashCommands.listS3ObjectsHandler
|
|
136
|
+
});
|
|
137
|
+
ctx.registerCommand({
|
|
138
|
+
name: 'contextlake-read-s3-object',
|
|
139
|
+
description: 'Read the contents of an S3 object',
|
|
140
|
+
acceptsArgs: true,
|
|
141
|
+
handler: slashCommands.readS3ObjectHandler
|
|
142
|
+
});
|
|
143
|
+
ctx.registerCommand({
|
|
144
|
+
name: 'contextlake-generate-presigned-url',
|
|
145
|
+
description: 'Generate a presigned HTTP URL for an S3/TOS object',
|
|
146
|
+
acceptsArgs: true,
|
|
147
|
+
handler: slashCommands.generatePresignedUrlHandler
|
|
148
|
+
});
|
|
149
|
+
const tools = (0, tools_1.getAgentTools)(pluginConfig, logger);
|
|
150
|
+
for (const tool of tools.lasTools) {
|
|
151
|
+
const cmdName = tool.name.replace(/_/g, '-');
|
|
152
|
+
ctx.registerCommand({
|
|
153
|
+
name: `contextlake-${cmdName}`,
|
|
154
|
+
description: tool.label,
|
|
155
|
+
acceptsArgs: true,
|
|
156
|
+
handler: slashCommands[`${tool.name}Handler`]
|
|
157
|
+
});
|
|
158
|
+
}
|
|
108
159
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash commands registered`);
|
|
109
160
|
}
|
|
110
161
|
catch (error) {
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { ContextLakeConfig } from '../utils/config';
|
|
2
2
|
export declare function getSlashCommands(pluginConfig: ContextLakeConfig, logger: any): {
|
|
3
|
+
listS3ObjectsHandler: (commandCtx: any) => Promise<{
|
|
4
|
+
text: string;
|
|
5
|
+
}>;
|
|
6
|
+
readS3ObjectHandler: (commandCtx: any) => Promise<{
|
|
7
|
+
text: string;
|
|
8
|
+
}>;
|
|
9
|
+
generatePresignedUrlHandler: (commandCtx: any) => Promise<{
|
|
10
|
+
text: string;
|
|
11
|
+
}>;
|
|
3
12
|
listHandler: (commandCtx: any) => Promise<{
|
|
4
13
|
text: string;
|
|
5
14
|
}>;
|
|
@@ -4,8 +4,116 @@ exports.getSlashCommands = getSlashCommands;
|
|
|
4
4
|
const retrieve_1 = require("../lib/actions/retrieve");
|
|
5
5
|
const manage_1 = require("../lib/actions/manage");
|
|
6
6
|
const profiler_1 = require("../lib/actions/profiler");
|
|
7
|
+
const las_tools_1 = require("../lib/actions/las-tools");
|
|
8
|
+
const s3_tools_1 = require("../lib/actions/s3-tools");
|
|
9
|
+
function parseOptionalInt(value, fallback) {
|
|
10
|
+
const parsed = Number.parseInt(String(value), 10);
|
|
11
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
12
|
+
}
|
|
7
13
|
function getSlashCommands(pluginConfig, logger) {
|
|
14
|
+
const lasTools = (0, las_tools_1.getLasTools)(pluginConfig, logger);
|
|
15
|
+
const lasHandlers = {};
|
|
16
|
+
for (const tool of lasTools) {
|
|
17
|
+
lasHandlers[`${tool.name}Handler`] = async (commandCtx) => {
|
|
18
|
+
const rawArgs = commandCtx.args || "";
|
|
19
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command ${tool.name} started`, { args: rawArgs });
|
|
20
|
+
try {
|
|
21
|
+
if (!rawArgs.trim()) {
|
|
22
|
+
return { text: `**Error:** Missing arguments. Please provide JSON data or URL.` };
|
|
23
|
+
}
|
|
24
|
+
let data = {};
|
|
25
|
+
try {
|
|
26
|
+
data = JSON.parse(rawArgs);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
data = { url: rawArgs.trim() };
|
|
30
|
+
}
|
|
31
|
+
let params = tool.name === 'las_bare_image_text_embedding'
|
|
32
|
+
? data
|
|
33
|
+
: { data };
|
|
34
|
+
const result = await tool.execute('slash', params);
|
|
35
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command ${tool.name} completed`);
|
|
36
|
+
return { text: `**${tool.label} Results:**\n\`\`\`json\n${JSON.stringify(result, null, 2)}\n\`\`\`` };
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
logger.error(`[ContextLake] Slash ${tool.name} failed`, { error: e.message });
|
|
40
|
+
return { text: `**Error executing ${tool.label}:** ${e.message}` };
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
8
44
|
return {
|
|
45
|
+
...lasHandlers,
|
|
46
|
+
listS3ObjectsHandler: async (commandCtx) => {
|
|
47
|
+
const rawArgs = commandCtx.args || "";
|
|
48
|
+
const args = rawArgs.split(' ').filter((arg) => arg.trim() !== '');
|
|
49
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command list-s3-objects started`, { args });
|
|
50
|
+
try {
|
|
51
|
+
if (args.length === 0) {
|
|
52
|
+
return { text: `**Error:** Missing URL. Usage: /contextlake-list-s3-objects <url> [maxKeys]` };
|
|
53
|
+
}
|
|
54
|
+
let url = args[0];
|
|
55
|
+
const maxKeys = args.length > 1 ? parseOptionalInt(args[1], 1000) : 1000;
|
|
56
|
+
let prefix = '';
|
|
57
|
+
if (url && !url.startsWith('file://')) {
|
|
58
|
+
try {
|
|
59
|
+
const parsedUrl = new URL(url);
|
|
60
|
+
prefix = parsedUrl.pathname.replace(/^\//, '');
|
|
61
|
+
// Reconstruct url without path to pass to listS3Objects as base url
|
|
62
|
+
url = `${parsedUrl.protocol}//${parsedUrl.host}`;
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
// ignore, leave url as is
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const result = await (0, s3_tools_1.listS3Objects)({ url }, prefix, maxKeys);
|
|
69
|
+
return { text: `**List S3 Objects Results:**\n\`\`\`json\n${JSON.stringify(result, null, 2)}\n\`\`\`` };
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
logger.error(`[ContextLake] Slash list-s3-objects failed`, { error: e.message });
|
|
73
|
+
return { text: `**Error executing list-s3-objects:** ${e.message}` };
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
readS3ObjectHandler: async (commandCtx) => {
|
|
77
|
+
const rawArgs = commandCtx.args || "";
|
|
78
|
+
const args = rawArgs.split(' ').filter((arg) => arg.trim() !== '');
|
|
79
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command read-s3-object started`, { args });
|
|
80
|
+
try {
|
|
81
|
+
if (args.length === 0) {
|
|
82
|
+
return { text: `**Error:** Missing URL. Usage: /contextlake-read-s3-object <url> [maxBytes]` };
|
|
83
|
+
}
|
|
84
|
+
const url = args[0];
|
|
85
|
+
const parsedUrl = new URL(url);
|
|
86
|
+
const key = parsedUrl.pathname.replace(/^\//, '');
|
|
87
|
+
const maxBytes = args.length > 1 ? parseOptionalInt(args[1], 0) : undefined;
|
|
88
|
+
const result = await (0, s3_tools_1.readS3Object)({ url }, key, maxBytes);
|
|
89
|
+
// Return base64 or string based on content? Returning string for simplicity in slash commands.
|
|
90
|
+
return { text: `**Read S3 Object Results:**\n\`\`\`\n${result.toString('utf-8')}\n\`\`\`` };
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
logger.error(`[ContextLake] Slash read-s3-object failed`, { error: e.message });
|
|
94
|
+
return { text: `**Error executing read-s3-object:** ${e.message}` };
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
generatePresignedUrlHandler: async (commandCtx) => {
|
|
98
|
+
const rawArgs = commandCtx.args || "";
|
|
99
|
+
const args = rawArgs.split(' ').filter((arg) => arg.trim() !== '');
|
|
100
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command generate-presigned-url started`, { args });
|
|
101
|
+
try {
|
|
102
|
+
if (args.length === 0) {
|
|
103
|
+
return { text: `**Error:** Missing URL. Usage: /contextlake-generate-presigned-url <url> [expiresIn]` };
|
|
104
|
+
}
|
|
105
|
+
const url = args[0];
|
|
106
|
+
const parsedUrl = new URL(url);
|
|
107
|
+
const key = parsedUrl.pathname.replace(/^\//, '');
|
|
108
|
+
const expiresIn = args.length > 1 ? parseOptionalInt(args[1], 3600) : 3600;
|
|
109
|
+
const result = await (0, s3_tools_1.getPresignedUrl)({ url }, key, expiresIn);
|
|
110
|
+
return { text: `**Presigned URL:**\n${result}` };
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
logger.error(`[ContextLake] Slash generate-presigned-url failed`, { error: e.message });
|
|
114
|
+
return { text: `**Error executing generate-presigned-url:** ${e.message}` };
|
|
115
|
+
}
|
|
116
|
+
},
|
|
9
117
|
listHandler: async (commandCtx) => {
|
|
10
118
|
const rawArgs = commandCtx.args || "";
|
|
11
119
|
const args = rawArgs.split(' ').filter((arg) => arg.trim() !== '');
|
package/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { registerAll } from './src/commands';
|
|
|
5
5
|
const plugin = {
|
|
6
6
|
id: 'contextlake-openclaw',
|
|
7
7
|
name: 'ContextLake',
|
|
8
|
-
version: '1.0.
|
|
8
|
+
version: '1.0.12',
|
|
9
9
|
description: 'A lightweight knowledge base plugin for OpenClaw using LanceDB and TOS, with data profiling support',
|
|
10
10
|
configSchema: {
|
|
11
11
|
type: 'object',
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "contextlake-openclaw",
|
|
3
3
|
"name": "ContextLake",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.12",
|
|
5
5
|
"description": "A lightweight knowledge base plugin for OpenClaw using LanceDB and TOS, with data profiling support",
|
|
6
6
|
"skills": ["./src/skills"],
|
|
7
7
|
"configSchema": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byted-las/contextlake-openclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "ContextLake OpenClaw Plugin for managing knowledge base",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"files": [
|
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
"build": "tsc && npm run copy-assets",
|
|
19
19
|
"copy-assets": "mkdir -p dist/src/skills && cp -r src/skills/* dist/src/skills/ 2>/dev/null || true && mkdir -p dist/src/lib/scripts && cp src/lib/scripts/*.py dist/src/lib/scripts/ 2>/dev/null || true",
|
|
20
20
|
"test": "vitest --reporter verbose",
|
|
21
|
-
"test:local": "npx ts-node scripts/local-test.ts",
|
|
22
|
-
"test:profiler": "npx ts-node scripts/local-profiler-test.ts",
|
|
23
21
|
"cli": "npx ts-node scripts/cli.ts"
|
|
24
22
|
},
|
|
25
23
|
"keywords": [
|
package/src/commands/cli.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { ingestSource } from '../lib/actions/ingest';
|
|
|
3
3
|
import { retrieveAssets } from '../lib/actions/retrieve';
|
|
4
4
|
import { listAssets, deleteAssets } from '../lib/actions/manage';
|
|
5
5
|
import { connectDataSource, ConnectParams } from '../lib/actions/profiler';
|
|
6
|
+
import { getLasTools } from '../lib/actions/las-tools';
|
|
7
|
+
import { listS3Objects, readS3Object, getPresignedUrl } from '../lib/actions/s3-tools';
|
|
6
8
|
import { loadCredentials, saveCredentials, promptForInput } from '../utils/credentials';
|
|
7
9
|
import { ContextLakeConfig } from '../utils/config';
|
|
8
10
|
|
|
@@ -36,7 +38,100 @@ function parseMetadata(metadata: any): Record<string, any> {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export function getCliCommands(pluginConfig: ContextLakeConfig, logger: any) {
|
|
41
|
+
const lasTools = getLasTools(pluginConfig, logger);
|
|
42
|
+
const lasActions: Record<string, any> = {};
|
|
43
|
+
|
|
44
|
+
for (const tool of lasTools) {
|
|
45
|
+
lasActions[`${tool.name}Action`] = async (dataStr: string) => {
|
|
46
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI ${tool.name} started`);
|
|
47
|
+
try {
|
|
48
|
+
let data = {};
|
|
49
|
+
try {
|
|
50
|
+
data = JSON.parse(dataStr);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
// if it's not valid JSON and the tool accepts a simple string/url, try to handle it.
|
|
53
|
+
// But LAS tools typically require a data object.
|
|
54
|
+
data = { url: dataStr };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let params = tool.name === 'las_bare_image_text_embedding'
|
|
58
|
+
? data
|
|
59
|
+
: { data };
|
|
60
|
+
|
|
61
|
+
const result = await tool.execute('cli', params);
|
|
62
|
+
// eslint-disable-next-line no-console
|
|
63
|
+
console.log(JSON.stringify(result, null, 2));
|
|
64
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI ${tool.name} success`);
|
|
65
|
+
} catch (e: any) {
|
|
66
|
+
console.error('Error:', e.message);
|
|
67
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] CLI ${tool.name} failed`, { error: e.message, stack: e.stack });
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
39
72
|
return {
|
|
73
|
+
...lasActions,
|
|
74
|
+
|
|
75
|
+
listS3ObjectsAction: async (url: string, options: any) => {
|
|
76
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI list-s3-objects started`, { url, options });
|
|
77
|
+
try {
|
|
78
|
+
// Parse prefix from URL if present
|
|
79
|
+
let prefix = '';
|
|
80
|
+
if (url && !url.startsWith('file://')) {
|
|
81
|
+
try {
|
|
82
|
+
const parsedUrl = new URL(url);
|
|
83
|
+
prefix = parsedUrl.pathname.replace(/^\//, '');
|
|
84
|
+
// Reconstruct url without path to pass to listS3Objects as base url
|
|
85
|
+
url = `${parsedUrl.protocol}//${parsedUrl.host}`;
|
|
86
|
+
} catch (e) {
|
|
87
|
+
// ignore, leave url as is
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const result = await listS3Objects(
|
|
92
|
+
{ url },
|
|
93
|
+
prefix,
|
|
94
|
+
parseOptionalInt(options.maxKeys, 1000),
|
|
95
|
+
options.continuationToken
|
|
96
|
+
);
|
|
97
|
+
// eslint-disable-next-line no-console
|
|
98
|
+
console.log(JSON.stringify(result, null, 2));
|
|
99
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI list-s3-objects success`);
|
|
100
|
+
} catch (e: any) {
|
|
101
|
+
console.error('Error:', e.message);
|
|
102
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] CLI list-s3-objects failed`, { error: e.message, stack: e.stack });
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
readS3ObjectAction: async (url: string, options: any) => {
|
|
107
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI read-s3-object started`, { url, options });
|
|
108
|
+
try {
|
|
109
|
+
const parsedUrl = new URL(url);
|
|
110
|
+
const key = parsedUrl.pathname.replace(/^\//, '');
|
|
111
|
+
const result = await readS3Object({ url }, key, options.maxBytes ? parseOptionalInt(options.maxBytes, 0) : undefined);
|
|
112
|
+
// eslint-disable-next-line no-console
|
|
113
|
+
console.log(result.toString('utf-8'));
|
|
114
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI read-s3-object success`);
|
|
115
|
+
} catch (e: any) {
|
|
116
|
+
console.error('Error:', e.message);
|
|
117
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] CLI read-s3-object failed`, { error: e.message, stack: e.stack });
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
generatePresignedUrlAction: async (url: string, options: any) => {
|
|
122
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI generate-presigned-url started`, { url, options });
|
|
123
|
+
try {
|
|
124
|
+
const parsedUrl = new URL(url);
|
|
125
|
+
const key = parsedUrl.pathname.replace(/^\//, '');
|
|
126
|
+
const result = await getPresignedUrl({ url }, key, parseOptionalInt(options.expiresIn, 3600));
|
|
127
|
+
// eslint-disable-next-line no-console
|
|
128
|
+
console.log(result);
|
|
129
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI generate-presigned-url success`);
|
|
130
|
+
} catch (e: any) {
|
|
131
|
+
console.error('Error:', e.message);
|
|
132
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] CLI generate-presigned-url failed`, { error: e.message, stack: e.stack });
|
|
133
|
+
}
|
|
134
|
+
},
|
|
40
135
|
searchAction: async (query: any, options: any) => {
|
|
41
136
|
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI search started`, { query, options });
|
|
42
137
|
try {
|
package/src/commands/index.ts
CHANGED
|
@@ -12,35 +12,35 @@ export function registerAll(ctx: OpenClawPluginApi, logger: PluginLogger) {
|
|
|
12
12
|
try {
|
|
13
13
|
const tools = getAgentTools(pluginConfig, logger);
|
|
14
14
|
|
|
15
|
-
ctx.registerTool(tools.retrieveTool );
|
|
15
|
+
ctx.registerTool(tools.retrieveTool, { name: tools.retrieveTool.name });
|
|
16
16
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.retrieveTool.name}`);
|
|
17
17
|
|
|
18
|
-
ctx.registerTool(tools.listTool );
|
|
18
|
+
ctx.registerTool(tools.listTool, { name: tools.listTool.name });
|
|
19
19
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.listTool.name}`);
|
|
20
20
|
|
|
21
|
-
ctx.registerTool(tools.deleteTool );
|
|
21
|
+
ctx.registerTool(tools.deleteTool, { name: tools.deleteTool.name });
|
|
22
22
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.deleteTool.name}`);
|
|
23
23
|
|
|
24
|
-
ctx.registerTool(tools.listS3ObjectsTool );
|
|
24
|
+
ctx.registerTool(tools.listS3ObjectsTool, { name: tools.listS3ObjectsTool.name });
|
|
25
25
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.listS3ObjectsTool.name}`);
|
|
26
26
|
|
|
27
|
-
ctx.registerTool(tools.readS3ObjectTool );
|
|
27
|
+
ctx.registerTool(tools.readS3ObjectTool, { name: tools.readS3ObjectTool.name });
|
|
28
28
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.readS3ObjectTool.name}`);
|
|
29
29
|
|
|
30
|
-
ctx.registerTool(tools.writeLanceCatalogTool );
|
|
30
|
+
ctx.registerTool(tools.writeLanceCatalogTool, { name: tools.writeLanceCatalogTool.name });
|
|
31
31
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.writeLanceCatalogTool.name}`);
|
|
32
32
|
|
|
33
|
-
ctx.registerTool(tools.readLanceCatalogTool );
|
|
33
|
+
ctx.registerTool(tools.readLanceCatalogTool, { name: tools.readLanceCatalogTool.name });
|
|
34
34
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.readLanceCatalogTool.name}`);
|
|
35
35
|
|
|
36
|
-
ctx.registerTool(tools.generatePresignedUrlTool );
|
|
36
|
+
ctx.registerTool(tools.generatePresignedUrlTool, { name: tools.generatePresignedUrlTool.name });
|
|
37
37
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.generatePresignedUrlTool.name}`);
|
|
38
38
|
|
|
39
|
-
ctx.registerTool(tools.listDatasourceTool );
|
|
39
|
+
ctx.registerTool(tools.listDatasourceTool, { name: tools.listDatasourceTool.name });
|
|
40
40
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${tools.listDatasourceTool.name}`);
|
|
41
41
|
|
|
42
42
|
for (const lasTool of tools.lasTools) {
|
|
43
|
-
ctx.registerTool(lasTool);
|
|
43
|
+
ctx.registerTool(lasTool, { name: lasTool.name });
|
|
44
44
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Tool registered: ${lasTool.name}`);
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -57,7 +57,7 @@ export function registerAll(ctx: OpenClawPluginApi, logger: PluginLogger) {
|
|
|
57
57
|
const contextlake = program.command('contextlake')
|
|
58
58
|
.description('Manage ContextLake knowledge base');
|
|
59
59
|
|
|
60
|
-
const commands = getCliCommands(pluginConfig, logger)
|
|
60
|
+
const commands = getCliCommands(pluginConfig, logger) as Record<string, any>;
|
|
61
61
|
|
|
62
62
|
// Search
|
|
63
63
|
contextlake.command('search <query>')
|
|
@@ -85,6 +85,33 @@ export function registerAll(ctx: OpenClawPluginApi, logger: PluginLogger) {
|
|
|
85
85
|
.description('Configure credentials for ContextLake')
|
|
86
86
|
.action(commands.onboardAction);
|
|
87
87
|
|
|
88
|
+
// S3 Tools
|
|
89
|
+
contextlake.command('list-s3-objects <url>')
|
|
90
|
+
.description('List objects in an S3-compatible bucket or local directory')
|
|
91
|
+
.option('--max-keys <number>', 'Maximum number of keys to return', '1000')
|
|
92
|
+
.option('--continuation-token <string>', 'Continuation token for pagination')
|
|
93
|
+
.action(commands.listS3ObjectsAction);
|
|
94
|
+
|
|
95
|
+
contextlake.command('read-s3-object <url>')
|
|
96
|
+
.description('Read the contents of an S3 object')
|
|
97
|
+
.option('--max-bytes <number>', 'Maximum number of bytes to read')
|
|
98
|
+
.action(commands.readS3ObjectAction);
|
|
99
|
+
|
|
100
|
+
contextlake.command('generate-presigned-url <url>')
|
|
101
|
+
.description('Generate a presigned HTTP URL for an S3/TOS object')
|
|
102
|
+
.option('--expires-in <number>', 'Expiration time in seconds', '3600')
|
|
103
|
+
.action(commands.generatePresignedUrlAction);
|
|
104
|
+
|
|
105
|
+
// LAS Tools
|
|
106
|
+
const tools = getAgentTools(pluginConfig, logger);
|
|
107
|
+
const lasTools = tools.lasTools;
|
|
108
|
+
for (const tool of lasTools) {
|
|
109
|
+
const cmdName = tool.name.replace(/_/g, '-');
|
|
110
|
+
contextlake.command(`${cmdName} <data>`)
|
|
111
|
+
.description(tool.label)
|
|
112
|
+
.action(commands[`${tool.name}Action`]);
|
|
113
|
+
}
|
|
114
|
+
|
|
88
115
|
}, { commands: ['contextlake'] });
|
|
89
116
|
logger.info(`[${new Date().toISOString()}] [ContextLake] CLI commands registered`);
|
|
90
117
|
} catch (error: any) {
|
|
@@ -129,6 +156,38 @@ export function registerAll(ctx: OpenClawPluginApi, logger: PluginLogger) {
|
|
|
129
156
|
handler: slashCommands.listDatasourceHandler
|
|
130
157
|
});
|
|
131
158
|
|
|
159
|
+
ctx.registerCommand({
|
|
160
|
+
name: 'contextlake-list-s3-objects',
|
|
161
|
+
description: 'List objects in an S3-compatible bucket or local directory',
|
|
162
|
+
acceptsArgs: true,
|
|
163
|
+
handler: (slashCommands as any).listS3ObjectsHandler
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
ctx.registerCommand({
|
|
167
|
+
name: 'contextlake-read-s3-object',
|
|
168
|
+
description: 'Read the contents of an S3 object',
|
|
169
|
+
acceptsArgs: true,
|
|
170
|
+
handler: (slashCommands as any).readS3ObjectHandler
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
ctx.registerCommand({
|
|
174
|
+
name: 'contextlake-generate-presigned-url',
|
|
175
|
+
description: 'Generate a presigned HTTP URL for an S3/TOS object',
|
|
176
|
+
acceptsArgs: true,
|
|
177
|
+
handler: (slashCommands as any).generatePresignedUrlHandler
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const tools = getAgentTools(pluginConfig, logger);
|
|
181
|
+
for (const tool of tools.lasTools) {
|
|
182
|
+
const cmdName = tool.name.replace(/_/g, '-');
|
|
183
|
+
ctx.registerCommand({
|
|
184
|
+
name: `contextlake-${cmdName}`,
|
|
185
|
+
description: tool.label,
|
|
186
|
+
acceptsArgs: true,
|
|
187
|
+
handler: (slashCommands as any)[`${tool.name}Handler`]
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
132
191
|
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash commands registered`);
|
|
133
192
|
} catch (error: any) {
|
|
134
193
|
logger.error(`[${new Date().toISOString()}] [ContextLake] Error registering Slash commands: ${error.message}${error.stack ? '\\n' + error.stack : ''}`);
|
package/src/commands/slashcmd.ts
CHANGED
|
@@ -2,13 +2,132 @@ import { ingestSource } from '../lib/actions/ingest';
|
|
|
2
2
|
import { retrieveAssets } from '../lib/actions/retrieve';
|
|
3
3
|
import { listAssets, deleteAssets } from '../lib/actions/manage';
|
|
4
4
|
import { connectDataSource, listDataSources, ConnectParams } from '../lib/actions/profiler';
|
|
5
|
+
import { getLasTools } from '../lib/actions/las-tools';
|
|
6
|
+
import { listS3Objects, readS3Object, getPresignedUrl } from '../lib/actions/s3-tools';
|
|
5
7
|
import { ContextLakeConfig } from '../utils/config';
|
|
6
8
|
import * as fs from 'fs';
|
|
7
9
|
import * as path from 'path';
|
|
8
10
|
import * as os from 'os';
|
|
9
11
|
|
|
12
|
+
function parseOptionalInt(value: any, fallback: number): number {
|
|
13
|
+
const parsed = Number.parseInt(String(value), 10);
|
|
14
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
export function getSlashCommands(pluginConfig: ContextLakeConfig, logger: any) {
|
|
18
|
+
const lasTools = getLasTools(pluginConfig, logger);
|
|
19
|
+
const lasHandlers: Record<string, any> = {};
|
|
20
|
+
|
|
21
|
+
for (const tool of lasTools) {
|
|
22
|
+
lasHandlers[`${tool.name}Handler`] = async (commandCtx: any) => {
|
|
23
|
+
const rawArgs = commandCtx.args || "";
|
|
24
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command ${tool.name} started`, { args: rawArgs });
|
|
25
|
+
try {
|
|
26
|
+
if (!rawArgs.trim()) {
|
|
27
|
+
return { text: `**Error:** Missing arguments. Please provide JSON data or URL.` };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let data = {};
|
|
31
|
+
try {
|
|
32
|
+
data = JSON.parse(rawArgs);
|
|
33
|
+
} catch (e) {
|
|
34
|
+
data = { url: rawArgs.trim() };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let params = tool.name === 'las_bare_image_text_embedding'
|
|
38
|
+
? data
|
|
39
|
+
: { data };
|
|
40
|
+
|
|
41
|
+
const result = await tool.execute('slash', params);
|
|
42
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command ${tool.name} completed`);
|
|
43
|
+
return { text: `**${tool.label} Results:**\n\`\`\`json\n${JSON.stringify(result, null, 2)}\n\`\`\`` };
|
|
44
|
+
} catch (e: any) {
|
|
45
|
+
logger.error(`[ContextLake] Slash ${tool.name} failed`, { error: e.message });
|
|
46
|
+
return { text: `**Error executing ${tool.label}:** ${e.message}` };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
11
51
|
return {
|
|
52
|
+
...lasHandlers,
|
|
53
|
+
|
|
54
|
+
listS3ObjectsHandler: async (commandCtx: any) => {
|
|
55
|
+
const rawArgs = commandCtx.args || "";
|
|
56
|
+
const args = rawArgs.split(' ').filter((arg: string) => arg.trim() !== '');
|
|
57
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command list-s3-objects started`, { args });
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
if (args.length === 0) {
|
|
61
|
+
return { text: `**Error:** Missing URL. Usage: /contextlake-list-s3-objects <url> [maxKeys]` };
|
|
62
|
+
}
|
|
63
|
+
let url = args[0];
|
|
64
|
+
const maxKeys = args.length > 1 ? parseOptionalInt(args[1], 1000) : 1000;
|
|
65
|
+
|
|
66
|
+
let prefix = '';
|
|
67
|
+
if (url && !url.startsWith('file://')) {
|
|
68
|
+
try {
|
|
69
|
+
const parsedUrl = new URL(url);
|
|
70
|
+
prefix = parsedUrl.pathname.replace(/^\//, '');
|
|
71
|
+
// Reconstruct url without path to pass to listS3Objects as base url
|
|
72
|
+
url = `${parsedUrl.protocol}//${parsedUrl.host}`;
|
|
73
|
+
} catch (e) {
|
|
74
|
+
// ignore, leave url as is
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const result = await listS3Objects({ url }, prefix, maxKeys);
|
|
79
|
+
return { text: `**List S3 Objects Results:**\n\`\`\`json\n${JSON.stringify(result, null, 2)}\n\`\`\`` };
|
|
80
|
+
} catch (e: any) {
|
|
81
|
+
logger.error(`[ContextLake] Slash list-s3-objects failed`, { error: e.message });
|
|
82
|
+
return { text: `**Error executing list-s3-objects:** ${e.message}` };
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
readS3ObjectHandler: async (commandCtx: any) => {
|
|
87
|
+
const rawArgs = commandCtx.args || "";
|
|
88
|
+
const args = rawArgs.split(' ').filter((arg: string) => arg.trim() !== '');
|
|
89
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command read-s3-object started`, { args });
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
if (args.length === 0) {
|
|
93
|
+
return { text: `**Error:** Missing URL. Usage: /contextlake-read-s3-object <url> [maxBytes]` };
|
|
94
|
+
}
|
|
95
|
+
const url = args[0];
|
|
96
|
+
const parsedUrl = new URL(url);
|
|
97
|
+
const key = parsedUrl.pathname.replace(/^\//, '');
|
|
98
|
+
const maxBytes = args.length > 1 ? parseOptionalInt(args[1], 0) : undefined;
|
|
99
|
+
|
|
100
|
+
const result = await readS3Object({ url }, key, maxBytes);
|
|
101
|
+
// Return base64 or string based on content? Returning string for simplicity in slash commands.
|
|
102
|
+
return { text: `**Read S3 Object Results:**\n\`\`\`\n${result.toString('utf-8')}\n\`\`\`` };
|
|
103
|
+
} catch (e: any) {
|
|
104
|
+
logger.error(`[ContextLake] Slash read-s3-object failed`, { error: e.message });
|
|
105
|
+
return { text: `**Error executing read-s3-object:** ${e.message}` };
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
generatePresignedUrlHandler: async (commandCtx: any) => {
|
|
110
|
+
const rawArgs = commandCtx.args || "";
|
|
111
|
+
const args = rawArgs.split(' ').filter((arg: string) => arg.trim() !== '');
|
|
112
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Slash command generate-presigned-url started`, { args });
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
if (args.length === 0) {
|
|
116
|
+
return { text: `**Error:** Missing URL. Usage: /contextlake-generate-presigned-url <url> [expiresIn]` };
|
|
117
|
+
}
|
|
118
|
+
const url = args[0];
|
|
119
|
+
const parsedUrl = new URL(url);
|
|
120
|
+
const key = parsedUrl.pathname.replace(/^\//, '');
|
|
121
|
+
const expiresIn = args.length > 1 ? parseOptionalInt(args[1], 3600) : 3600;
|
|
122
|
+
|
|
123
|
+
const result = await getPresignedUrl({ url }, key, expiresIn);
|
|
124
|
+
return { text: `**Presigned URL:**\n${result}` };
|
|
125
|
+
} catch (e: any) {
|
|
126
|
+
logger.error(`[ContextLake] Slash generate-presigned-url failed`, { error: e.message });
|
|
127
|
+
return { text: `**Error executing generate-presigned-url:** ${e.message}` };
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
|
|
12
131
|
listHandler: async (commandCtx: any) => {
|
|
13
132
|
const rawArgs = commandCtx.args || "";
|
|
14
133
|
const args = rawArgs.split(' ').filter((arg: string) => arg.trim() !== '');
|
package/src/commands/tools.ts
CHANGED
|
@@ -36,7 +36,7 @@ export function getAgentTools(pluginConfig: ContextLakeConfig, logger: any): {
|
|
|
36
36
|
additionalProperties: false
|
|
37
37
|
},
|
|
38
38
|
async execute(toolCallId: string, params: any) {
|
|
39
|
-
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing list-datasource
|
|
39
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing list-datasource tool, toolCallId: ${toolCallId}`);
|
|
40
40
|
try {
|
|
41
41
|
const result = await listDataSources();
|
|
42
42
|
return {
|
|
@@ -44,7 +44,7 @@ export function getAgentTools(pluginConfig: ContextLakeConfig, logger: any): {
|
|
|
44
44
|
details: result
|
|
45
45
|
} as any;
|
|
46
46
|
} catch (error: any) {
|
|
47
|
-
logger.error(`[${new Date().toISOString()}] [ContextLake] list-datasource
|
|
47
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] list-datasource tool failed`, { error: error.message });
|
|
48
48
|
return {
|
|
49
49
|
content: [{ type: "text", text: String(error.message) }],
|
|
50
50
|
details: { error: error.message }
|
|
@@ -77,7 +77,7 @@ Example User Queries:
|
|
|
77
77
|
},
|
|
78
78
|
|
|
79
79
|
async execute(toolCallId: string, params: any) {
|
|
80
|
-
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing retrieve
|
|
80
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing retrieve tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
81
81
|
|
|
82
82
|
try {
|
|
83
83
|
let actualParams = params;
|
|
@@ -101,13 +101,13 @@ Example User Queries:
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
const result = await retrieveAssets(actualParams, pluginConfig, logger);
|
|
104
|
-
logger.info(`[${new Date().toISOString()}] [ContextLake] Retrieve
|
|
104
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Retrieve tool completed`, { resultCount: Array.isArray(result) ? result.length : 0 });
|
|
105
105
|
return {
|
|
106
106
|
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
107
107
|
details: result
|
|
108
108
|
} as any;
|
|
109
109
|
} catch (error: any) {
|
|
110
|
-
logger.error(`[${new Date().toISOString()}] [ContextLake] Retrieve
|
|
110
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] Retrieve tool failed`, { error: error.message, stack: error.stack });
|
|
111
111
|
return {
|
|
112
112
|
content: [{ type: "text", text: String(error.message
|
|
113
113
|
) }],
|
|
@@ -137,7 +137,7 @@ Example User Queries:
|
|
|
137
137
|
},
|
|
138
138
|
|
|
139
139
|
async execute(toolCallId: string, params: any) {
|
|
140
|
-
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing list
|
|
140
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing list tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
141
141
|
|
|
142
142
|
try {
|
|
143
143
|
let actualParams = params;
|
|
@@ -145,13 +145,13 @@ Example User Queries:
|
|
|
145
145
|
actualParams = params.params;
|
|
146
146
|
}
|
|
147
147
|
const result = await listAssets(actualParams, pluginConfig, logger);
|
|
148
|
-
logger.info(`[${new Date().toISOString()}] [ContextLake] List
|
|
148
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] List tool completed`, { count: Array.isArray(result) ? result.length : 0 });
|
|
149
149
|
return {
|
|
150
150
|
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
151
151
|
details: result
|
|
152
152
|
} as any;
|
|
153
153
|
} catch (error: any) {
|
|
154
|
-
logger.error(`[${new Date().toISOString()}] [ContextLake] List
|
|
154
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] List tool failed`, { error: error.message, stack: error.stack });
|
|
155
155
|
return {
|
|
156
156
|
content: [{ type: "text", text: String(error.message
|
|
157
157
|
) }],
|
|
@@ -183,7 +183,7 @@ Example User Queries:
|
|
|
183
183
|
},
|
|
184
184
|
|
|
185
185
|
async execute(toolCallId: string, params: any) {
|
|
186
|
-
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing delete
|
|
186
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing delete tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
187
187
|
|
|
188
188
|
try {
|
|
189
189
|
let actualParams = params;
|
|
@@ -191,13 +191,13 @@ Example User Queries:
|
|
|
191
191
|
actualParams = params.params;
|
|
192
192
|
}
|
|
193
193
|
const result = await deleteAssets(actualParams, pluginConfig, logger);
|
|
194
|
-
logger.info(`[${new Date().toISOString()}] [ContextLake] Delete
|
|
194
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Delete tool completed`, { result });
|
|
195
195
|
return {
|
|
196
196
|
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
197
197
|
details: result
|
|
198
198
|
} as any;
|
|
199
199
|
} catch (error: any) {
|
|
200
|
-
logger.error(`[${new Date().toISOString()}] [ContextLake] Delete
|
|
200
|
+
logger.error(`[${new Date().toISOString()}] [ContextLake] Delete tool failed`, { error: error.message, stack: error.stack });
|
|
201
201
|
return {
|
|
202
202
|
content: [{ type: "text", text: String(error.message
|
|
203
203
|
) }],
|
|
@@ -226,6 +226,7 @@ Example User Queries:
|
|
|
226
226
|
additionalProperties: false
|
|
227
227
|
},
|
|
228
228
|
async execute(toolCallId: string, params: any) {
|
|
229
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing list-s3-objects tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
229
230
|
let actualParams = params.params || params;
|
|
230
231
|
try {
|
|
231
232
|
const result = await listS3Objects(actualParams, actualParams.prefix || '', actualParams.maxKeys, actualParams.continuationToken);
|
|
@@ -253,6 +254,7 @@ Example User Queries:
|
|
|
253
254
|
additionalProperties: false
|
|
254
255
|
},
|
|
255
256
|
async execute(toolCallId: string, params: any) {
|
|
257
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing read-s3-object tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
256
258
|
let actualParams = params.params || params;
|
|
257
259
|
try {
|
|
258
260
|
// Extract key from url if provided
|
|
@@ -299,6 +301,7 @@ Example User Queries:
|
|
|
299
301
|
additionalProperties: false
|
|
300
302
|
},
|
|
301
303
|
async execute(toolCallId: string, params: any) {
|
|
304
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing generate-presigned-url tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
302
305
|
let actualParams = params.params || params;
|
|
303
306
|
try {
|
|
304
307
|
let key = actualParams.key;
|
|
@@ -339,6 +342,7 @@ Example User Queries:
|
|
|
339
342
|
additionalProperties: false
|
|
340
343
|
},
|
|
341
344
|
async execute(toolCallId: string, params: any) {
|
|
345
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing write-lance-catalog tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
342
346
|
let actualParams = params.params || params;
|
|
343
347
|
try {
|
|
344
348
|
await writeLanceCatalog(actualParams);
|
|
@@ -364,6 +368,7 @@ Example User Queries:
|
|
|
364
368
|
additionalProperties: false
|
|
365
369
|
},
|
|
366
370
|
async execute(toolCallId: string, params: any) {
|
|
371
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing read-lance-catalog tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
367
372
|
let actualParams = params.params || params;
|
|
368
373
|
try {
|
|
369
374
|
const results = await readLanceCatalog(actualParams);
|
|
@@ -60,6 +60,7 @@ Parameters in data:
|
|
|
60
60
|
required: ['data']
|
|
61
61
|
},
|
|
62
62
|
async execute(toolCallId: string, params: any) {
|
|
63
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_image_resample tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
63
64
|
if (params.data?.image) {
|
|
64
65
|
params.data.image = await processUrl(params.data.image);
|
|
65
66
|
}
|
|
@@ -83,6 +84,7 @@ Parameters in data:
|
|
|
83
84
|
required: ['data']
|
|
84
85
|
},
|
|
85
86
|
async execute(toolCallId: string, params: any) {
|
|
87
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_audio_extract_and_split tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
86
88
|
if (params.data?.input_path) {
|
|
87
89
|
params.data.input_path = await processUrl(params.data.input_path);
|
|
88
90
|
}
|
|
@@ -104,6 +106,7 @@ Parameters in data:
|
|
|
104
106
|
required: ['data']
|
|
105
107
|
},
|
|
106
108
|
async execute(toolCallId: string, params: any) {
|
|
109
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_audio_convert tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
107
110
|
if (params.data?.input_path) {
|
|
108
111
|
params.data.input_path = await processUrl(params.data.input_path);
|
|
109
112
|
}
|
|
@@ -125,6 +128,7 @@ Parameters in data:
|
|
|
125
128
|
required: ['data']
|
|
126
129
|
},
|
|
127
130
|
async execute(toolCallId: string, params: any) {
|
|
131
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_asr_pro tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
128
132
|
if (params.data?.audio?.url) {
|
|
129
133
|
params.data.audio.url = await processUrl(params.data.audio.url);
|
|
130
134
|
}
|
|
@@ -144,6 +148,7 @@ Parameters in data:
|
|
|
144
148
|
required: ['data']
|
|
145
149
|
},
|
|
146
150
|
async execute(toolCallId: string, params: any) {
|
|
151
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_seed_2_0 tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
147
152
|
if (params.data?.audio?.url) {
|
|
148
153
|
params.data.audio.url = await processUrl(params.data.audio.url);
|
|
149
154
|
}
|
|
@@ -170,6 +175,7 @@ Parameters:
|
|
|
170
175
|
required: ['model', 'input']
|
|
171
176
|
},
|
|
172
177
|
async execute(toolCallId: string, params: any) {
|
|
178
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_bare_image_text_embedding tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
173
179
|
if (params.input && Array.isArray(params.input)) {
|
|
174
180
|
for (const item of params.input) {
|
|
175
181
|
if (item.type === 'image_url' && item.image_url?.url) {
|
|
@@ -200,6 +206,7 @@ Parameters in data:
|
|
|
200
206
|
required: ['data']
|
|
201
207
|
},
|
|
202
208
|
async execute(toolCallId: string, params: any) {
|
|
209
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_long_video_understand tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
203
210
|
if (params.data?.video_url) {
|
|
204
211
|
params.data.video_url = await processUrl(params.data.video_url);
|
|
205
212
|
}
|
|
@@ -221,6 +228,7 @@ Parameters in data:
|
|
|
221
228
|
required: ['data']
|
|
222
229
|
},
|
|
223
230
|
async execute(toolCallId: string, params: any) {
|
|
231
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_pdf_parse_doubao tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
224
232
|
if (params.data?.url) {
|
|
225
233
|
params.data.url = await processUrl(params.data.url);
|
|
226
234
|
}
|
|
@@ -242,6 +250,7 @@ Parameters in data:
|
|
|
242
250
|
required: ['data']
|
|
243
251
|
},
|
|
244
252
|
async execute(toolCallId: string, params: any) {
|
|
253
|
+
logger.info(`[${new Date().toISOString()}] [ContextLake] Executing las_video_resize tool, toolCallId: ${toolCallId}`, { params: JSON.stringify(params) });
|
|
245
254
|
if (params.data?.video_url) {
|
|
246
255
|
params.data.video_url = await processUrl(params.data.video_url);
|
|
247
256
|
}
|