@tyvm/knowhow 0.0.108-dev.bd8f104-dev.bd8f104-dev.bd8f104 → 0.0.108-dev.c47492f
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/package.json +2 -2
- package/scripts/publish.sh +20 -4
- package/src/agents/base/base.ts +9 -0
- package/src/chat/CliChatService.ts +7 -1
- package/src/chat/renderer/CompactRenderer.ts +20 -0
- package/src/chat/renderer/ConsoleRenderer.ts +19 -0
- package/src/chat/renderer/FancyRenderer.ts +19 -0
- package/src/chat/renderer/types.ts +11 -0
- package/src/cli.ts +45 -21
- package/src/clients/types.ts +12 -4
- package/src/processors/JsonCompressor.ts +3 -3
- package/src/services/modules/index.ts +21 -17
- package/src/tunnel.ts +216 -0
- package/src/worker.ts +65 -336
- package/src/workers/auth/WsMiddleware.ts +99 -0
- package/src/workers/auth/authMiddleware.ts +104 -0
- package/src/workers/auth/types.ts +14 -2
- package/ts_build/package.json +2 -2
- package/ts_build/src/agents/base/base.js +10 -0
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/chat/CliChatService.js +10 -1
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/renderer/CompactRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/CompactRenderer.js +16 -0
- package/ts_build/src/chat/renderer/CompactRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/ConsoleRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.js +16 -0
- package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/FancyRenderer.d.ts +4 -0
- package/ts_build/src/chat/renderer/FancyRenderer.js +16 -0
- package/ts_build/src/chat/renderer/FancyRenderer.js.map +1 -1
- package/ts_build/src/chat/renderer/types.d.ts +2 -0
- package/ts_build/src/cli.js +17 -9
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +2 -2
- package/ts_build/src/processors/JsonCompressor.js +3 -3
- package/ts_build/src/processors/JsonCompressor.js.map +1 -1
- package/ts_build/src/services/modules/index.d.ts +30 -0
- package/ts_build/src/services/modules/index.js +9 -14
- package/ts_build/src/services/modules/index.js.map +1 -1
- package/ts_build/src/tunnel.d.ts +27 -0
- package/ts_build/src/tunnel.js +112 -0
- package/ts_build/src/tunnel.js.map +1 -0
- package/ts_build/src/worker.d.ts +1 -4
- package/ts_build/src/worker.js +38 -244
- package/ts_build/src/worker.js.map +1 -1
- package/ts_build/src/workers/auth/WsMiddleware.d.ts +8 -0
- package/ts_build/src/workers/auth/WsMiddleware.js +65 -0
- package/ts_build/src/workers/auth/WsMiddleware.js.map +1 -0
- package/ts_build/src/workers/auth/authMiddleware.d.ts +3 -0
- package/ts_build/src/workers/auth/authMiddleware.js +60 -0
- package/ts_build/src/workers/auth/authMiddleware.js.map +1 -0
- package/ts_build/src/workers/auth/types.d.ts +8 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tyvm/knowhow",
|
|
3
|
-
"version": "0.0.108-dev.
|
|
3
|
+
"version": "0.0.108-dev.c47492f",
|
|
4
4
|
"description": "ai cli with plugins and agents",
|
|
5
5
|
"main": "ts_build/src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@inquirer/editor": "^4.2.18",
|
|
56
56
|
"@modelcontextprotocol/sdk": "^1.13.3",
|
|
57
57
|
"@simplewebauthn/server": "^13.3.0",
|
|
58
|
-
"@tyvm/knowhow-tunnel": "0.0.
|
|
58
|
+
"@tyvm/knowhow-tunnel": "0.0.5",
|
|
59
59
|
"commander": "^14.0.0",
|
|
60
60
|
"diff": "^5.2.0",
|
|
61
61
|
"express": "^4.19.2",
|
package/scripts/publish.sh
CHANGED
|
@@ -10,21 +10,37 @@ get_current_version() {
|
|
|
10
10
|
version_nightly() {
|
|
11
11
|
local version
|
|
12
12
|
version=$(get_current_version)
|
|
13
|
+
# Strip any existing pre-release suffix (e.g. -dev.xxx or -nightly.xxx)
|
|
14
|
+
version=$(echo "$version" | sed 's/-.*$//')
|
|
13
15
|
local stamp
|
|
14
16
|
stamp=$(date -u +%Y%m%d)
|
|
15
17
|
local pre="${version}-nightly.${stamp}"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
local current
|
|
19
|
+
current=$(get_current_version)
|
|
20
|
+
if [ "$current" = "$pre" ]; then
|
|
21
|
+
echo "Version already set to: $pre (no change needed)"
|
|
22
|
+
else
|
|
23
|
+
echo "Bumping version to: $pre"
|
|
24
|
+
npm version "$pre" --no-git-tag-version
|
|
25
|
+
fi
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
version_dev() {
|
|
21
29
|
local version
|
|
22
30
|
version=$(get_current_version)
|
|
31
|
+
# Strip any existing pre-release suffix (e.g. -dev.xxx or -nightly.xxx)
|
|
32
|
+
version=$(echo "$version" | sed 's/-.*$//')
|
|
23
33
|
local hash
|
|
24
34
|
hash=$(git rev-parse --short HEAD)
|
|
25
35
|
local pre="${version}-dev.${hash}"
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
local current
|
|
37
|
+
current=$(get_current_version)
|
|
38
|
+
if [ "$current" = "$pre" ]; then
|
|
39
|
+
echo "Version already set to: $pre (no change needed)"
|
|
40
|
+
else
|
|
41
|
+
echo "Bumping version to: $pre"
|
|
42
|
+
npm version "$pre" --no-git-tag-version
|
|
43
|
+
fi
|
|
28
44
|
}
|
|
29
45
|
|
|
30
46
|
case "$COMMAND" in
|
package/src/agents/base/base.ts
CHANGED
|
@@ -317,6 +317,15 @@ export abstract class BaseAgent implements IAgent {
|
|
|
317
317
|
if (trimmed.startsWith("✅") || /^[\d\.\-\*]/.test(trimmed)) return true;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
+
// Detect JSON-wrapped finalAnswer output, e.g. {"answer":"..."} or {"finalAnswer":"..."}
|
|
321
|
+
try {
|
|
322
|
+
const parsed = JSON.parse(trimmed);
|
|
323
|
+
if (parsed && typeof parsed === "object") {
|
|
324
|
+
if (typeof parsed.answer === "string") return true;
|
|
325
|
+
if (typeof parsed.finalAnswer === "string") return true;
|
|
326
|
+
}
|
|
327
|
+
} catch (_) {}
|
|
328
|
+
|
|
320
329
|
return false;
|
|
321
330
|
}
|
|
322
331
|
|
|
@@ -265,7 +265,13 @@ export class CliChatService implements ChatService {
|
|
|
265
265
|
if (this.context.voiceMode) {
|
|
266
266
|
value = await voiceToText();
|
|
267
267
|
} else if (this.context.multilineMode) {
|
|
268
|
-
|
|
268
|
+
const renderer = this.context.renderer;
|
|
269
|
+
if (renderer) renderer.pause();
|
|
270
|
+
try {
|
|
271
|
+
value = await editor({ message: prompt });
|
|
272
|
+
} finally {
|
|
273
|
+
if (renderer) renderer.resume();
|
|
274
|
+
}
|
|
269
275
|
this.context.multilineMode = false; // Disable after use like original
|
|
270
276
|
} else {
|
|
271
277
|
// Use saved input history for scrollback (InputQueueManager handles reverse access)
|
|
@@ -72,6 +72,8 @@ function colorFor(n: string) {
|
|
|
72
72
|
export class CompactRenderer implements AgentRenderer {
|
|
73
73
|
private activeTaskId: string | undefined;
|
|
74
74
|
private emitter = new EventEmitter();
|
|
75
|
+
private paused = false;
|
|
76
|
+
private bufferedEvents: RenderEvent[] = [];
|
|
75
77
|
|
|
76
78
|
setActiveTaskId(id: string | undefined): void {
|
|
77
79
|
this.activeTaskId = id;
|
|
@@ -110,8 +112,26 @@ export class CompactRenderer implements AgentRenderer {
|
|
|
110
112
|
this.emitter.on("agentDone", handler);
|
|
111
113
|
}
|
|
112
114
|
|
|
115
|
+
pause(): void {
|
|
116
|
+
this.paused = true;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
resume(): void {
|
|
120
|
+
this.paused = false;
|
|
121
|
+
const buffered = this.bufferedEvents.splice(0);
|
|
122
|
+
for (const event of buffered) {
|
|
123
|
+
this.render(event);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
113
127
|
render(event: RenderEvent): void {
|
|
114
128
|
if (!this.isActiveTask(event.taskId)) return;
|
|
129
|
+
|
|
130
|
+
if (this.paused) {
|
|
131
|
+
this.bufferedEvents.push(event);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
115
135
|
this.emitter.emit(event.type, event);
|
|
116
136
|
switch (event.type) {
|
|
117
137
|
case "log":
|
|
@@ -17,6 +17,8 @@ import { EventEmitter } from "events";
|
|
|
17
17
|
export class ConsoleRenderer implements AgentRenderer {
|
|
18
18
|
private activeTaskId: string | undefined;
|
|
19
19
|
private emitter = new EventEmitter();
|
|
20
|
+
private paused = false;
|
|
21
|
+
private bufferedEvents: RenderEvent[] = [];
|
|
20
22
|
|
|
21
23
|
setActiveTaskId(taskId: string | undefined): void {
|
|
22
24
|
this.activeTaskId = taskId;
|
|
@@ -56,9 +58,26 @@ export class ConsoleRenderer implements AgentRenderer {
|
|
|
56
58
|
this.emitter.on("agentDone", handler);
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
pause(): void {
|
|
62
|
+
this.paused = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
resume(): void {
|
|
66
|
+
this.paused = false;
|
|
67
|
+
const buffered = this.bufferedEvents.splice(0);
|
|
68
|
+
for (const event of buffered) {
|
|
69
|
+
this.render(event);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
render(event: RenderEvent): void {
|
|
60
74
|
if (!this.isActiveTask(event.taskId)) return;
|
|
61
75
|
|
|
76
|
+
if (this.paused) {
|
|
77
|
+
this.bufferedEvents.push(event);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
62
81
|
switch (event.type) {
|
|
63
82
|
case "log":
|
|
64
83
|
this.emitter.emit("log", event);
|
|
@@ -194,6 +194,8 @@ const toolTimers = new Map<string, number>();
|
|
|
194
194
|
export class FancyRenderer implements AgentRenderer {
|
|
195
195
|
private activeTaskId: string | undefined;
|
|
196
196
|
private emitter = new EventEmitter();
|
|
197
|
+
private paused = false;
|
|
198
|
+
private bufferedEvents: RenderEvent[] = [];
|
|
197
199
|
|
|
198
200
|
setActiveTaskId(taskId: string | undefined): void {
|
|
199
201
|
this.activeTaskId = taskId;
|
|
@@ -227,9 +229,26 @@ export class FancyRenderer implements AgentRenderer {
|
|
|
227
229
|
this.emitter.on("agentDone", handler);
|
|
228
230
|
}
|
|
229
231
|
|
|
232
|
+
pause(): void {
|
|
233
|
+
this.paused = true;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
resume(): void {
|
|
237
|
+
this.paused = false;
|
|
238
|
+
const buffered = this.bufferedEvents.splice(0);
|
|
239
|
+
for (const event of buffered) {
|
|
240
|
+
this.render(event);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
230
244
|
render(event: RenderEvent): void {
|
|
231
245
|
if (!this.isActiveTask(event.taskId)) return;
|
|
232
246
|
|
|
247
|
+
if (this.paused) {
|
|
248
|
+
this.bufferedEvents.push(event);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
233
252
|
switch (event.type) {
|
|
234
253
|
case "log":
|
|
235
254
|
this.emitter.emit("log", event);
|
|
@@ -80,6 +80,17 @@ export interface AgentRenderer {
|
|
|
80
80
|
setActiveTaskId(taskId: string | undefined): void;
|
|
81
81
|
getActiveTaskId(): string | undefined;
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Pause rendering - buffer any incoming events instead of printing them.
|
|
85
|
+
* Useful when an interactive UI (e.g. editor for /multi) takes over the terminal.
|
|
86
|
+
*/
|
|
87
|
+
pause(): void;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resume rendering - flush any buffered events and resume normal output.
|
|
91
|
+
*/
|
|
92
|
+
resume(): void;
|
|
93
|
+
|
|
83
94
|
/**
|
|
84
95
|
* Replay the last N render events (used by /logs command).
|
|
85
96
|
* If count is not provided, shows last 10.
|
package/src/cli.ts
CHANGED
|
@@ -14,7 +14,8 @@ import { includedTools } from "./agents/tools/list";
|
|
|
14
14
|
import * as allTools from "./agents/tools";
|
|
15
15
|
import { LazyToolsService, services } from "./services";
|
|
16
16
|
import { login } from "./login";
|
|
17
|
-
import { worker
|
|
17
|
+
import { worker } from "./worker";
|
|
18
|
+
import { TUNNEL_MINIMAL_TOOLS } from "./tunnel";
|
|
18
19
|
import { fileSync } from "./fileSync";
|
|
19
20
|
import { KnowhowSimpleClient } from "./services/KnowhowClient";
|
|
20
21
|
import { ModulesService } from "./services/modules";
|
|
@@ -44,23 +45,28 @@ import { CliChatService } from "./chat/CliChatService";
|
|
|
44
45
|
// Without this, a single failing MCP server (e.g. expired Notion token) will
|
|
45
46
|
// crash the entire CLI with an unhandled rejection.
|
|
46
47
|
process.on("unhandledRejection", (reason: unknown) => {
|
|
47
|
-
const message =
|
|
48
|
-
reason instanceof Error ? reason.message : String(reason);
|
|
48
|
+
const message = reason instanceof Error ? reason.message : String(reason);
|
|
49
49
|
// Only warn — don't exit. The MCP connect errors are recoverable;
|
|
50
50
|
// the server will simply be unavailable but others continue working.
|
|
51
|
-
console.warn(
|
|
52
|
-
`⚠ Unhandled MCP/async error (non-fatal): ${message}`
|
|
53
|
-
);
|
|
51
|
+
console.warn(`⚠ Unhandled MCP/async error (non-fatal): ${message}`);
|
|
54
52
|
});
|
|
55
53
|
|
|
56
54
|
async function setupServices() {
|
|
57
|
-
const {
|
|
55
|
+
const {
|
|
56
|
+
Agents,
|
|
57
|
+
Mcp,
|
|
58
|
+
Clients,
|
|
59
|
+
Tools: AllTools,
|
|
60
|
+
Embeddings,
|
|
61
|
+
Plugins,
|
|
62
|
+
MediaProcessor,
|
|
63
|
+
} = services();
|
|
58
64
|
const Tools = new LazyToolsService(); // eslint-disable-line no-shadow
|
|
59
65
|
|
|
60
66
|
// Load modules from config first so module-provided tools/agents/plugins are available
|
|
61
67
|
// We need to wireup the LazyTools to be connected to the same singletons that are in services()
|
|
62
68
|
Tools.setContext({
|
|
63
|
-
...
|
|
69
|
+
...AllTools.getContext(),
|
|
64
70
|
});
|
|
65
71
|
|
|
66
72
|
// Build the AgentContext with the fully-populated LazyToolsService so every
|
|
@@ -107,16 +113,17 @@ async function setupServices() {
|
|
|
107
113
|
const modulesService = new ModulesService();
|
|
108
114
|
await modulesService.loadModulesFromConfig({
|
|
109
115
|
Agents,
|
|
110
|
-
Embeddings
|
|
111
|
-
Plugins
|
|
116
|
+
Embeddings,
|
|
117
|
+
Plugins,
|
|
112
118
|
Clients,
|
|
119
|
+
|
|
113
120
|
// Use LazyToolsService so module-provided tools are visible to agents and scripts
|
|
114
|
-
Tools
|
|
115
|
-
MediaProcessor
|
|
121
|
+
Tools,
|
|
122
|
+
MediaProcessor,
|
|
116
123
|
});
|
|
117
124
|
|
|
118
|
-
// Return both LazyToolsService (for agents) and
|
|
119
|
-
return { Tools, Clients
|
|
125
|
+
// Return both LazyToolsService (for agents) and AllTools (plain ToolsService with all tools for scripts)
|
|
126
|
+
return { Tools, Clients };
|
|
120
127
|
}
|
|
121
128
|
|
|
122
129
|
// Utility function to read from stdin
|
|
@@ -528,14 +535,25 @@ async function main() {
|
|
|
528
535
|
program
|
|
529
536
|
.command("cloudworker")
|
|
530
537
|
.description("Create or sync a cloud worker with your local knowhow config")
|
|
531
|
-
.option(
|
|
532
|
-
|
|
533
|
-
|
|
538
|
+
.option(
|
|
539
|
+
"--create",
|
|
540
|
+
"Create a new cloud worker with synced config and files"
|
|
541
|
+
)
|
|
542
|
+
.option(
|
|
543
|
+
"--push <uid>",
|
|
544
|
+
"Push/sync local config and files to an existing cloud worker"
|
|
545
|
+
)
|
|
546
|
+
.option(
|
|
547
|
+
"--pull <id>",
|
|
548
|
+
"Pull the latest workerConfigJson from a cloud worker and update local config"
|
|
549
|
+
)
|
|
534
550
|
.option("--name <name>", "Name for the cloud worker (used with --create)")
|
|
535
551
|
.option("--dry-run", "Print what would be synced without doing it")
|
|
536
552
|
.action(async (options) => {
|
|
537
553
|
try {
|
|
538
|
-
const { cloudWorker, pullCloudWorkerConfig } = await import(
|
|
554
|
+
const { cloudWorker, pullCloudWorkerConfig } = await import(
|
|
555
|
+
"./cloudWorker"
|
|
556
|
+
);
|
|
539
557
|
if (options.pull) {
|
|
540
558
|
await pullCloudWorkerConfig({ id: options.pull });
|
|
541
559
|
} else {
|
|
@@ -550,7 +568,9 @@ async function main() {
|
|
|
550
568
|
program
|
|
551
569
|
.command("tunnel")
|
|
552
570
|
.description(
|
|
553
|
-
"Start tunnel
|
|
571
|
+
"Start a minimal worker with tunnel enabled: exposes local ports to the cloud. " +
|
|
572
|
+
"Registers essential tools (unlock, lock, listAllowedPorts) so the backend is aware of the worker and ports. " +
|
|
573
|
+
"If passkey auth is configured, the tunnel is locked until unlocked via tool call or WebSocket auth protocol."
|
|
554
574
|
)
|
|
555
575
|
.option(
|
|
556
576
|
"--share",
|
|
@@ -558,10 +578,14 @@ async function main() {
|
|
|
558
578
|
)
|
|
559
579
|
.option("--unshare", "Make this tunnel private (only you can use it)")
|
|
560
580
|
.action(async (options) => {
|
|
561
|
-
|
|
581
|
+
console.log("🌐 Starting tunnel (minimal worker) mode...");
|
|
582
|
+
console.log(` Tools: ${TUNNEL_MINIMAL_TOOLS.join(", ")}`);
|
|
583
|
+
await worker({
|
|
584
|
+
...options,
|
|
585
|
+
allowedTools: TUNNEL_MINIMAL_TOOLS,
|
|
586
|
+
});
|
|
562
587
|
});
|
|
563
588
|
|
|
564
|
-
|
|
565
589
|
program
|
|
566
590
|
.command("script")
|
|
567
591
|
.description("Run a local tool script file using the executeScript sandbox")
|
package/src/clients/types.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
export type ModelModality =
|
|
1
|
+
export type ModelModality =
|
|
2
|
+
| "completion"
|
|
3
|
+
| "embedding"
|
|
4
|
+
| "image"
|
|
5
|
+
| "audio"
|
|
6
|
+
| "video"
|
|
7
|
+
| "transcription";
|
|
2
8
|
|
|
3
9
|
export type MessageContent =
|
|
4
10
|
| { type: "text"; text: string }
|
|
@@ -8,7 +14,7 @@ export type MessageContent =
|
|
|
8
14
|
|
|
9
15
|
export interface Message {
|
|
10
16
|
role: "system" | "user" | "assistant" | "tool";
|
|
11
|
-
content?: string | MessageContent[];
|
|
17
|
+
content?: string | MessageContent[] | null;
|
|
12
18
|
|
|
13
19
|
name?: string;
|
|
14
20
|
tool_call_id?: string;
|
|
@@ -16,7 +22,7 @@ export interface Message {
|
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
export interface OutputMessage extends Message {
|
|
19
|
-
content
|
|
25
|
+
content?: string | null;
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
export interface ToolProp {
|
|
@@ -301,7 +307,9 @@ export interface GenericClient {
|
|
|
301
307
|
* When modality is provided, return only models for that modality (static list).
|
|
302
308
|
* When omitted, return ALL models (backward compat — may do a live API call).
|
|
303
309
|
*/
|
|
304
|
-
getModels(
|
|
310
|
+
getModels(
|
|
311
|
+
modality?: ModelModality
|
|
312
|
+
): Promise<{ id: string; modality?: ModelModality[] }[]>;
|
|
305
313
|
/**
|
|
306
314
|
* Returns the context window limit and compression threshold for a given model,
|
|
307
315
|
* or undefined if the model is not known to this client.
|
|
@@ -382,7 +382,7 @@ export class JsonCompressor {
|
|
|
382
382
|
i + currentChunk.length - 1
|
|
383
383
|
}]\nPreview: ${chunkString.substring(0, 100)}...\n[Use ${
|
|
384
384
|
this.toolName
|
|
385
|
-
} tool with key "${key}" to retrieve this chunk]`;
|
|
385
|
+
} tool with key "${key}" to retrieve this chunk]\n[TIP: try jqToolResponse,grepToolResponse,tailToolResponse to filter/search/map without repeated ${this.toolName} calls - especially useful for JSON data]`;
|
|
386
386
|
finalArray.unshift(stub); // Add stub to the start of our final result.
|
|
387
387
|
|
|
388
388
|
currentChunk = [];
|
|
@@ -453,7 +453,7 @@ export class JsonCompressor {
|
|
|
453
453
|
result
|
|
454
454
|
).join(", ")}\nPreview: ${objectAsString.substring(0, 200)}...\n[Use ${
|
|
455
455
|
this.toolName
|
|
456
|
-
} tool with key "${key}" to retrieve full content]`;
|
|
456
|
+
} tool with key "${key}" to retrieve full content]\n[TIP: try jqToolResponse,grepToolResponse,tailToolResponse to filter/search/map without repeated ${this.toolName} calls - especially useful for JSON data]`;
|
|
457
457
|
}
|
|
458
458
|
return result;
|
|
459
459
|
}
|
|
@@ -486,7 +486,7 @@ export class JsonCompressor {
|
|
|
486
486
|
200
|
|
487
487
|
)}...\n[Use ${
|
|
488
488
|
this.toolName
|
|
489
|
-
} tool with key "${key}" to retrieve full content]`;
|
|
489
|
+
} tool with key "${key}" to retrieve full content]\n[TIP: try jqToolResponse,grepToolResponse,tailToolResponse to filter/search/map without repeated ${this.toolName} calls - especially useful for JSON data]`;
|
|
490
490
|
}
|
|
491
491
|
return obj;
|
|
492
492
|
}
|
|
@@ -5,20 +5,21 @@ import { services } from "../";
|
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
|
|
7
7
|
export class ModulesService {
|
|
8
|
+
async getDefaultContext() {
|
|
9
|
+
return { ...services() };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async overrideDefaultContext(overrides: Partial<ModuleContext>) {
|
|
13
|
+
const defaultContext = await this.getDefaultContext();
|
|
14
|
+
return { ...defaultContext, ...overrides };
|
|
15
|
+
}
|
|
16
|
+
|
|
8
17
|
async loadModulesFromConfig(context?: ModuleContext) {
|
|
9
18
|
const config = await getConfig();
|
|
10
19
|
|
|
11
20
|
// If no context provided, fall back to global singletons
|
|
12
21
|
if (!context) {
|
|
13
|
-
|
|
14
|
-
context = {
|
|
15
|
-
Agents,
|
|
16
|
-
Embeddings,
|
|
17
|
-
Plugins,
|
|
18
|
-
Clients,
|
|
19
|
-
Tools,
|
|
20
|
-
MediaProcessor,
|
|
21
|
-
};
|
|
22
|
+
context = { ...(await this.getDefaultContext()) };
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
// Use the toolsService from context
|
|
@@ -43,9 +44,13 @@ export class ModulesService {
|
|
|
43
44
|
: modulePath;
|
|
44
45
|
const rawModule = require(resolvedPath);
|
|
45
46
|
const importedModule = (rawModule.default || rawModule) as KnowhowModule;
|
|
46
|
-
console.log(
|
|
47
|
+
console.log(
|
|
48
|
+
`🔌 Loading module: ${modulePath} (resolved: ${resolvedPath})`
|
|
49
|
+
);
|
|
47
50
|
await importedModule.init({ config, cwd: process.cwd(), context });
|
|
48
|
-
console.log(
|
|
51
|
+
console.log(
|
|
52
|
+
`✅ Module initialized: ${modulePath} (tools: ${importedModule.tools.length}, agents: ${importedModule.agents.length}, plugins: ${importedModule.plugins.length}, clients: ${importedModule.clients.length})`
|
|
53
|
+
);
|
|
49
54
|
|
|
50
55
|
for (const agent of importedModule.agents) {
|
|
51
56
|
agentService.registerAgent(agent);
|
|
@@ -58,13 +63,12 @@ export class ModulesService {
|
|
|
58
63
|
|
|
59
64
|
for (const plugin of importedModule.plugins) {
|
|
60
65
|
const pluginContext = {
|
|
61
|
-
|
|
62
|
-
Clients: clients,
|
|
63
|
-
Tools: toolsService,
|
|
64
|
-
Plugins: pluginService,
|
|
65
|
-
...(context.MediaProcessor ? { MediaProcessor: context.MediaProcessor } : {}),
|
|
66
|
+
...context,
|
|
66
67
|
};
|
|
67
|
-
pluginService.registerPlugin(
|
|
68
|
+
pluginService.registerPlugin(
|
|
69
|
+
plugin.name,
|
|
70
|
+
new plugin.plugin(pluginContext as any)
|
|
71
|
+
);
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
for (const client of importedModule.clients) {
|