joonecli 0.2.0 → 0.2.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/dist/__tests__/config.test.js +1 -0
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/installHostDeps.test.js +45 -0
- package/dist/__tests__/installHostDeps.test.js.map +1 -0
- package/dist/__tests__/whitelistedBackend.test.js +18 -0
- package/dist/__tests__/whitelistedBackend.test.js.map +1 -0
- package/dist/cli/config.d.ts +2 -0
- package/dist/cli/config.js +1 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/index.js +84 -100
- package/dist/cli/index.js.map +1 -1
- package/dist/core/agentLoop.d.ts +10 -29
- package/dist/core/agentLoop.js +66 -237
- package/dist/core/agentLoop.js.map +1 -1
- package/dist/core/promptBuilder.js.map +1 -1
- package/dist/hitl/bridge.js +1 -27
- package/dist/hitl/bridge.js.map +1 -1
- package/dist/middleware/loopDetection.d.ts +7 -23
- package/dist/middleware/loopDetection.js +38 -42
- package/dist/middleware/loopDetection.js.map +1 -1
- package/dist/sandbox/whitelistedBackend.d.ts +5 -0
- package/dist/sandbox/whitelistedBackend.js +27 -0
- package/dist/sandbox/whitelistedBackend.js.map +1 -0
- package/dist/tools/askUser.d.ts +12 -3
- package/dist/tools/askUser.js +16 -28
- package/dist/tools/askUser.js.map +1 -1
- package/dist/tools/bashTool.d.ts +11 -0
- package/dist/tools/bashTool.js +51 -0
- package/dist/tools/bashTool.js.map +1 -0
- package/dist/tools/index.d.ts +15 -28
- package/dist/tools/index.js +9 -189
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/installHostDeps.d.ts +8 -2
- package/dist/tools/installHostDeps.js +38 -31
- package/dist/tools/installHostDeps.js.map +1 -1
- package/dist/ui/App.js +112 -56
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/components/MessageBubble.js +1 -1
- package/dist/ui/components/MessageBubble.js.map +1 -1
- package/package.json +7 -2
- package/dist/__tests__/m55.test.js +0 -160
- package/dist/__tests__/m55.test.js.map +0 -1
- package/dist/__tests__/middleware.test.js +0 -169
- package/dist/__tests__/middleware.test.js.map +0 -1
- package/dist/__tests__/optimizations.test.d.ts +0 -1
- package/dist/__tests__/optimizations.test.js +0 -136
- package/dist/__tests__/optimizations.test.js.map +0 -1
- package/dist/__tests__/security.test.d.ts +0 -1
- package/dist/__tests__/security.test.js +0 -86
- package/dist/__tests__/security.test.js.map +0 -1
- package/dist/__tests__/streaming.test.d.ts +0 -1
- package/dist/__tests__/streaming.test.js +0 -71
- package/dist/__tests__/streaming.test.js.map +0 -1
- package/dist/__tests__/toolRouter.test.d.ts +0 -1
- package/dist/__tests__/toolRouter.test.js +0 -37
- package/dist/__tests__/toolRouter.test.js.map +0 -1
- package/dist/__tests__/tools.test.d.ts +0 -1
- package/dist/__tests__/tools.test.js +0 -112
- package/dist/__tests__/tools.test.js.map +0 -1
- package/dist/core/subAgent.d.ts +0 -56
- package/dist/core/subAgent.js +0 -240
- package/dist/core/subAgent.js.map +0 -1
- package/dist/debug_google.d.ts +0 -1
- package/dist/debug_google.js +0 -23
- package/dist/debug_google.js.map +0 -1
- package/dist/middleware/commandSanitizer.d.ts +0 -18
- package/dist/middleware/commandSanitizer.js +0 -50
- package/dist/middleware/commandSanitizer.js.map +0 -1
- package/dist/middleware/permission.d.ts +0 -17
- package/dist/middleware/permission.js +0 -60
- package/dist/middleware/permission.js.map +0 -1
- package/dist/middleware/pipeline.d.ts +0 -31
- package/dist/middleware/pipeline.js +0 -62
- package/dist/middleware/pipeline.js.map +0 -1
- package/dist/middleware/preCompletion.d.ts +0 -29
- package/dist/middleware/preCompletion.js +0 -82
- package/dist/middleware/preCompletion.js.map +0 -1
- package/dist/middleware/types.d.ts +0 -40
- package/dist/middleware/types.js +0 -8
- package/dist/middleware/types.js.map +0 -1
- package/dist/skills/loader.d.ts +0 -55
- package/dist/skills/loader.js +0 -132
- package/dist/skills/loader.js.map +0 -1
- package/dist/skills/tools.d.ts +0 -5
- package/dist/skills/tools.js +0 -78
- package/dist/skills/tools.js.map +0 -1
- package/dist/test_cache.d.ts +0 -1
- package/dist/test_cache.js +0 -55
- package/dist/test_cache.js.map +0 -1
- package/dist/test_google.d.ts +0 -1
- package/dist/test_google.js +0 -36
- package/dist/test_google.js.map +0 -1
- package/dist/tools/browser.d.ts +0 -19
- package/dist/tools/browser.js +0 -114
- package/dist/tools/browser.js.map +0 -1
- package/dist/tools/registry.d.ts +0 -31
- package/dist/tools/registry.js +0 -168
- package/dist/tools/registry.js.map +0 -1
- package/dist/tools/router.d.ts +0 -34
- package/dist/tools/router.js +0 -76
- package/dist/tools/router.js.map +0 -1
- package/dist/tools/security.d.ts +0 -28
- package/dist/tools/security.js +0 -183
- package/dist/tools/security.js.map +0 -1
- package/dist/tools/spawnAgent.d.ts +0 -19
- package/dist/tools/spawnAgent.js +0 -132
- package/dist/tools/spawnAgent.js.map +0 -1
- package/dist/tools/webSearch.d.ts +0 -6
- package/dist/tools/webSearch.js +0 -120
- package/dist/tools/webSearch.js.map +0 -1
- /package/dist/__tests__/{m55.test.d.ts → installHostDeps.test.d.ts} +0 -0
- /package/dist/__tests__/{middleware.test.d.ts → whitelistedBackend.test.d.ts} +0 -0
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Executes tool calls through a chain of middleware hooks.
|
|
3
|
-
*
|
|
4
|
-
* Execution flow:
|
|
5
|
-
* 1. Run all `before()` hooks in registration order.
|
|
6
|
-
* - If any returns a string → short-circuit (tool is NOT executed).
|
|
7
|
-
* 2. Execute the actual tool function.
|
|
8
|
-
* 3. Run all `after()` hooks in reverse registration order.
|
|
9
|
-
* - Each can transform the result before it enters conversation history.
|
|
10
|
-
*/
|
|
11
|
-
export class MiddlewarePipeline {
|
|
12
|
-
middlewares = [];
|
|
13
|
-
/**
|
|
14
|
-
* Register a middleware. Middlewares run in the order they are added.
|
|
15
|
-
*/
|
|
16
|
-
use(middleware) {
|
|
17
|
-
this.middlewares.push(middleware);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Returns the number of registered middlewares.
|
|
21
|
-
*/
|
|
22
|
-
get length() {
|
|
23
|
-
return this.middlewares.length;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Execute a tool call through the middleware pipeline.
|
|
27
|
-
*
|
|
28
|
-
* @param ctx - The tool call context (name, args, callId).
|
|
29
|
-
* @param executeFn - The actual tool execution function.
|
|
30
|
-
* @returns The final result string (possibly transformed by after-hooks).
|
|
31
|
-
*/
|
|
32
|
-
async run(ctx, executeFn) {
|
|
33
|
-
// ── Before phase: run hooks in order ──
|
|
34
|
-
let currentCtx = ctx;
|
|
35
|
-
for (const mw of this.middlewares) {
|
|
36
|
-
if (mw.before) {
|
|
37
|
-
const result = await mw.before(currentCtx);
|
|
38
|
-
if (typeof result === "string") {
|
|
39
|
-
// Short-circuit: middleware rejected the call
|
|
40
|
-
return result;
|
|
41
|
-
}
|
|
42
|
-
if (result !== undefined) {
|
|
43
|
-
currentCtx = result;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
// ── Execute the tool ──
|
|
48
|
-
let output = await executeFn(currentCtx);
|
|
49
|
-
// ── After phase: run hooks in reverse order ──
|
|
50
|
-
for (let i = this.middlewares.length - 1; i >= 0; i--) {
|
|
51
|
-
const mw = this.middlewares[i];
|
|
52
|
-
if (mw.after) {
|
|
53
|
-
const transformed = await mw.after(currentCtx, output);
|
|
54
|
-
if (transformed !== undefined) {
|
|
55
|
-
output = transformed;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return output.content;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=pipeline.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/middleware/pipeline.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,MAAM,OAAO,kBAAkB;IACrB,WAAW,GAAqB,EAAE,CAAC;IAE3C;;OAEG;IACH,GAAG,CAAC,UAA0B;QAC5B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;IACjC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,GAAG,CACP,GAAoB,EACpB,SAAqE;QAErE,yCAAyC;QACzC,IAAI,UAAU,GAAG,GAAG,CAAC;QAErB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;gBACd,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBAE3C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;oBAC/B,8CAA8C;oBAC9C,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAED,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBACzB,UAAU,GAAG,MAAM,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;QAED,yBAAyB;QACzB,IAAI,MAAM,GAAe,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC;QAErD,gDAAgD;QAChD,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACtD,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAC/B,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;gBACb,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;gBACvD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBAC9B,MAAM,GAAG,WAAW,CAAC;gBACvB,CAAC;YACH,CAAC;QAAI,CAAC;QAER,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { ToolCallContext, ToolMiddleware } from "./types.js";
|
|
2
|
-
import { ToolResult } from "../tools/index.js";
|
|
3
|
-
/**
|
|
4
|
-
* Prevents the agent from marking a task as "done" without running tests.
|
|
5
|
-
*
|
|
6
|
-
* Tracks whether any test command has been executed during the session.
|
|
7
|
-
* If the agent attempts to signal completion without running tests first,
|
|
8
|
-
* the middleware intercepts and forces verification.
|
|
9
|
-
*
|
|
10
|
-
* Reference: docs/02_edge_cases_and_mitigations.md — "The Fake Success Verification"
|
|
11
|
-
*/
|
|
12
|
-
export declare class PreCompletionMiddleware implements ToolMiddleware {
|
|
13
|
-
readonly name = "PreCompletion";
|
|
14
|
-
private testsPassed;
|
|
15
|
-
/** Patterns in bash commands that count as "running tests". */
|
|
16
|
-
private readonly testPatterns;
|
|
17
|
-
/** Tool names that signal the agent is trying to complete the task. */
|
|
18
|
-
private readonly completionSignals;
|
|
19
|
-
before(ctx: ToolCallContext): ToolCallContext | string;
|
|
20
|
-
after(ctx: ToolCallContext, result: ToolResult): void;
|
|
21
|
-
/**
|
|
22
|
-
* Returns whether tests have been run and passed in this session.
|
|
23
|
-
*/
|
|
24
|
-
hasPassedTests(): boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Resets state. Useful for testing or session boundaries.
|
|
27
|
-
*/
|
|
28
|
-
reset(): void;
|
|
29
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Prevents the agent from marking a task as "done" without running tests.
|
|
3
|
-
*
|
|
4
|
-
* Tracks whether any test command has been executed during the session.
|
|
5
|
-
* If the agent attempts to signal completion without running tests first,
|
|
6
|
-
* the middleware intercepts and forces verification.
|
|
7
|
-
*
|
|
8
|
-
* Reference: docs/02_edge_cases_and_mitigations.md — "The Fake Success Verification"
|
|
9
|
-
*/
|
|
10
|
-
export class PreCompletionMiddleware {
|
|
11
|
-
name = "PreCompletion";
|
|
12
|
-
testsPassed = false;
|
|
13
|
-
/** Patterns in bash commands that count as "running tests". */
|
|
14
|
-
testPatterns = [
|
|
15
|
-
/\bvitest\b/,
|
|
16
|
-
/\bjest\b/,
|
|
17
|
-
/\bpytest\b/,
|
|
18
|
-
/\bmocha\b/,
|
|
19
|
-
/\bnpm\s+test\b/,
|
|
20
|
-
/\bnpm\s+run\s+test\b/,
|
|
21
|
-
/\byarn\s+test\b/,
|
|
22
|
-
/\bpnpm\s+test\b/,
|
|
23
|
-
/\bgo\s+test\b/,
|
|
24
|
-
/\bcargo\s+test\b/,
|
|
25
|
-
];
|
|
26
|
-
/** Tool names that signal the agent is trying to complete the task. */
|
|
27
|
-
completionSignals = new Set([
|
|
28
|
-
"task_complete",
|
|
29
|
-
"attempt_completion",
|
|
30
|
-
"finish_task",
|
|
31
|
-
"submit_result",
|
|
32
|
-
]);
|
|
33
|
-
before(ctx) {
|
|
34
|
-
// When a test command is initiated, assume it hasn't passed yet
|
|
35
|
-
if (ctx.toolName === "bash" && typeof ctx.args.command === "string") {
|
|
36
|
-
for (const pattern of this.testPatterns) {
|
|
37
|
-
if (pattern.test(ctx.args.command)) {
|
|
38
|
-
this.testsPassed = false;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// Intercept completion attempts
|
|
44
|
-
if (this.completionSignals.has(ctx.toolName)) {
|
|
45
|
-
if (!this.testsPassed) {
|
|
46
|
-
return ("⚠ You must run tests before completing the task, AND they must pass.\n" +
|
|
47
|
-
"Use the bash tool to execute your test suite (e.g., `npm test`, `vitest`, `pytest`).\n" +
|
|
48
|
-
"If tests fail, fix the issues. Once tests pass cleanly, you may attempt completion again.");
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return ctx;
|
|
52
|
-
}
|
|
53
|
-
after(ctx, result) {
|
|
54
|
-
if (ctx.toolName === "bash" && typeof ctx.args.command === "string") {
|
|
55
|
-
for (const pattern of this.testPatterns) {
|
|
56
|
-
if (pattern.test(ctx.args.command)) {
|
|
57
|
-
// Robustly check the exact exit code from the tool metadata
|
|
58
|
-
if (result.metadata?.exitCode === 0) {
|
|
59
|
-
this.testsPassed = true;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
this.testsPassed = false;
|
|
63
|
-
}
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Returns whether tests have been run and passed in this session.
|
|
71
|
-
*/
|
|
72
|
-
hasPassedTests() {
|
|
73
|
-
return this.testsPassed;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Resets state. Useful for testing or session boundaries.
|
|
77
|
-
*/
|
|
78
|
-
reset() {
|
|
79
|
-
this.testsPassed = false;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
//# sourceMappingURL=preCompletion.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"preCompletion.js","sourceRoot":"","sources":["../../src/middleware/preCompletion.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,MAAM,OAAO,uBAAuB;IACzB,IAAI,GAAG,eAAe,CAAC;IAExB,WAAW,GAAG,KAAK,CAAC;IAE5B,+DAA+D;IAC9C,YAAY,GAAG;QAC9B,YAAY;QACZ,UAAU;QACV,YAAY;QACZ,WAAW;QACX,gBAAgB;QAChB,sBAAsB;QACtB,iBAAiB;QACjB,iBAAiB;QACjB,eAAe;QACf,kBAAkB;KACnB,CAAC;IAEF,uEAAuE;IACtD,iBAAiB,GAAG,IAAI,GAAG,CAAC;QAC3C,eAAe;QACf,oBAAoB;QACpB,aAAa;QACb,eAAe;KAChB,CAAC,CAAC;IAEH,MAAM,CAAC,GAAoB;QACzB,gEAAgE;QAChE,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpE,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACxC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBACnC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;oBACzB,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,gCAAgC;QAChC,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtB,OAAO,CACL,wEAAwE;oBACxE,wFAAwF;oBACxF,2FAA2F,CAC5F,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,GAAoB,EAAE,MAAkB;QAC5C,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpE,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACxC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBACnC,4DAA4D;oBAC5D,IAAI,MAAM,CAAC,QAAQ,EAAE,QAAQ,KAAK,CAAC,EAAE,CAAC;wBACpC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;oBAC1B,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;oBAC3B,CAAC;oBACD,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Middleware types for the tool execution pipeline.
|
|
3
|
-
*
|
|
4
|
-
* Each middleware can hook into both the "before" and "after" phases
|
|
5
|
-
* of a tool call. The pipeline chains them in order.
|
|
6
|
-
*/
|
|
7
|
-
import { ToolResult } from "../tools/index.js";
|
|
8
|
-
/**
|
|
9
|
-
* Context object passed through the middleware chain for each tool call.
|
|
10
|
-
*/
|
|
11
|
-
export interface ToolCallContext {
|
|
12
|
-
/** Name of the tool being called (e.g., "bash", "read_file"). */
|
|
13
|
-
toolName: string;
|
|
14
|
-
/** Arguments passed to the tool. */
|
|
15
|
-
args: Record<string, any>;
|
|
16
|
-
/** Unique ID of this tool call (from the LLM response). */
|
|
17
|
-
callId: string;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* A middleware that can intercept tool calls before and after execution.
|
|
21
|
-
*
|
|
22
|
-
* - `before()`: Runs before the tool executes. Return the (possibly modified)
|
|
23
|
-
* context to continue, or a `string` to short-circuit with an error/warning.
|
|
24
|
-
* - `after()`: Runs after the tool executes. Can transform the result before
|
|
25
|
-
* it enters the conversation history.
|
|
26
|
-
*/
|
|
27
|
-
export interface ToolMiddleware {
|
|
28
|
-
/** Human-readable name for logging and debugging. */
|
|
29
|
-
name: string;
|
|
30
|
-
/**
|
|
31
|
-
* Pre-execution hook.
|
|
32
|
-
* @returns ToolCallContext to mutate, a string to short-circuit, or void to pass through unmodified.
|
|
33
|
-
*/
|
|
34
|
-
before?(ctx: ToolCallContext): Promise<ToolCallContext | string | void> | ToolCallContext | string | void;
|
|
35
|
-
/**
|
|
36
|
-
* Post-execution hook.
|
|
37
|
-
* @returns The transformed tool result object, or void to pass through unmodified.
|
|
38
|
-
*/
|
|
39
|
-
after?(ctx: ToolCallContext, result: ToolResult): Promise<ToolResult | void> | ToolResult | void;
|
|
40
|
-
}
|
package/dist/middleware/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/middleware/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/dist/skills/loader.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { SkillMeta } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* SkillLoader — discovers and loads skills from multiple directories.
|
|
4
|
-
*
|
|
5
|
-
* Discovery paths (priority order — project overrides user):
|
|
6
|
-
* 1. Project root: ./skills/, ./.agents/skills/, ./.agent/skills/
|
|
7
|
-
* 2. User home: ~/.joone/skills/, ~/.agents/skills/
|
|
8
|
-
*
|
|
9
|
-
* On Windows, ~ resolves to %USERPROFILE%.
|
|
10
|
-
*
|
|
11
|
-
* Skills are folders containing a SKILL.md with YAML frontmatter:
|
|
12
|
-
* ---
|
|
13
|
-
* name: my-skill
|
|
14
|
-
* description: What this skill does
|
|
15
|
-
* ---
|
|
16
|
-
* ## Instructions
|
|
17
|
-
* ...
|
|
18
|
-
*/
|
|
19
|
-
export declare class SkillLoader {
|
|
20
|
-
private projectRoot;
|
|
21
|
-
private userHome;
|
|
22
|
-
private cachedSkills;
|
|
23
|
-
constructor(projectRoot?: string, userHome?: string);
|
|
24
|
-
/**
|
|
25
|
-
* Returns all skill discovery directories in priority order.
|
|
26
|
-
* Project-level directories come first (higher priority).
|
|
27
|
-
*/
|
|
28
|
-
getDiscoveryPaths(): {
|
|
29
|
-
path: string;
|
|
30
|
-
source: "project" | "user";
|
|
31
|
-
}[];
|
|
32
|
-
/**
|
|
33
|
-
* Parses YAML frontmatter from a SKILL.md content string.
|
|
34
|
-
* Simple parser — handles `name:` and `description:` fields.
|
|
35
|
-
*/
|
|
36
|
-
parseFrontmatter(content: string): {
|
|
37
|
-
name?: string;
|
|
38
|
-
description?: string;
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* Discovers all available skills from all discovery paths.
|
|
42
|
-
* Deduplicates by name — project-level skills override user-level.
|
|
43
|
-
* Results are cached per session.
|
|
44
|
-
*/
|
|
45
|
-
discoverSkills(): SkillMeta[];
|
|
46
|
-
/**
|
|
47
|
-
* Loads the full content of a specific skill's SKILL.md.
|
|
48
|
-
* Returns undefined if the skill is not found.
|
|
49
|
-
*/
|
|
50
|
-
loadSkill(name: string): string | undefined;
|
|
51
|
-
/**
|
|
52
|
-
* Clears the cached skills. Call when skills directory contents may have changed.
|
|
53
|
-
*/
|
|
54
|
-
clearCache(): void;
|
|
55
|
-
}
|
package/dist/skills/loader.js
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import * as os from "node:os";
|
|
4
|
-
/**
|
|
5
|
-
* SkillLoader — discovers and loads skills from multiple directories.
|
|
6
|
-
*
|
|
7
|
-
* Discovery paths (priority order — project overrides user):
|
|
8
|
-
* 1. Project root: ./skills/, ./.agents/skills/, ./.agent/skills/
|
|
9
|
-
* 2. User home: ~/.joone/skills/, ~/.agents/skills/
|
|
10
|
-
*
|
|
11
|
-
* On Windows, ~ resolves to %USERPROFILE%.
|
|
12
|
-
*
|
|
13
|
-
* Skills are folders containing a SKILL.md with YAML frontmatter:
|
|
14
|
-
* ---
|
|
15
|
-
* name: my-skill
|
|
16
|
-
* description: What this skill does
|
|
17
|
-
* ---
|
|
18
|
-
* ## Instructions
|
|
19
|
-
* ...
|
|
20
|
-
*/
|
|
21
|
-
export class SkillLoader {
|
|
22
|
-
projectRoot;
|
|
23
|
-
userHome;
|
|
24
|
-
cachedSkills = null;
|
|
25
|
-
constructor(projectRoot, userHome) {
|
|
26
|
-
this.projectRoot = projectRoot ?? process.cwd();
|
|
27
|
-
this.userHome = userHome ?? os.homedir();
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Returns all skill discovery directories in priority order.
|
|
31
|
-
* Project-level directories come first (higher priority).
|
|
32
|
-
*/
|
|
33
|
-
getDiscoveryPaths() {
|
|
34
|
-
const home = this.userHome;
|
|
35
|
-
return [
|
|
36
|
-
// Project-level (highest priority)
|
|
37
|
-
{ path: path.join(this.projectRoot, "skills"), source: "project" },
|
|
38
|
-
{ path: path.join(this.projectRoot, ".agents", "skills"), source: "project" },
|
|
39
|
-
{ path: path.join(this.projectRoot, ".agent", "skills"), source: "project" },
|
|
40
|
-
// User-level
|
|
41
|
-
{ path: path.join(home, ".joone", "skills"), source: "user" },
|
|
42
|
-
{ path: path.join(home, ".agents", "skills"), source: "user" },
|
|
43
|
-
];
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Parses YAML frontmatter from a SKILL.md content string.
|
|
47
|
-
* Simple parser — handles `name:` and `description:` fields.
|
|
48
|
-
*/
|
|
49
|
-
parseFrontmatter(content) {
|
|
50
|
-
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
51
|
-
if (!match)
|
|
52
|
-
return {};
|
|
53
|
-
const yaml = match[1];
|
|
54
|
-
const nameMatch = yaml.match(/^name:\s*(.+)$/m);
|
|
55
|
-
const descMatch = yaml.match(/^description:\s*(.+)$/m);
|
|
56
|
-
return {
|
|
57
|
-
name: nameMatch?.[1]?.trim(),
|
|
58
|
-
description: descMatch?.[1]?.trim(),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Discovers all available skills from all discovery paths.
|
|
63
|
-
* Deduplicates by name — project-level skills override user-level.
|
|
64
|
-
* Results are cached per session.
|
|
65
|
-
*/
|
|
66
|
-
discoverSkills() {
|
|
67
|
-
if (this.cachedSkills)
|
|
68
|
-
return this.cachedSkills;
|
|
69
|
-
const skills = new Map();
|
|
70
|
-
const paths = this.getDiscoveryPaths();
|
|
71
|
-
for (const { path: dir, source } of paths) {
|
|
72
|
-
if (!fs.existsSync(dir))
|
|
73
|
-
continue;
|
|
74
|
-
let entries;
|
|
75
|
-
try {
|
|
76
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
for (const entry of entries) {
|
|
82
|
-
if (!entry.isDirectory())
|
|
83
|
-
continue;
|
|
84
|
-
const skillMdPath = path.join(dir, entry.name, "SKILL.md");
|
|
85
|
-
if (!fs.existsSync(skillMdPath))
|
|
86
|
-
continue;
|
|
87
|
-
try {
|
|
88
|
-
const content = fs.readFileSync(skillMdPath, "utf-8");
|
|
89
|
-
const frontmatter = this.parseFrontmatter(content);
|
|
90
|
-
const name = frontmatter.name || entry.name;
|
|
91
|
-
// Only add if not already found (project overrides user)
|
|
92
|
-
if (!skills.has(name)) {
|
|
93
|
-
skills.set(name, {
|
|
94
|
-
name,
|
|
95
|
-
description: frontmatter.description || `Skill: ${name}`,
|
|
96
|
-
path: skillMdPath,
|
|
97
|
-
source,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
// Skip unreadable skills
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
this.cachedSkills = Array.from(skills.values());
|
|
107
|
-
return this.cachedSkills;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Loads the full content of a specific skill's SKILL.md.
|
|
111
|
-
* Returns undefined if the skill is not found.
|
|
112
|
-
*/
|
|
113
|
-
loadSkill(name) {
|
|
114
|
-
const skills = this.discoverSkills();
|
|
115
|
-
const skill = skills.find((s) => s.name === name);
|
|
116
|
-
if (!skill)
|
|
117
|
-
return undefined;
|
|
118
|
-
try {
|
|
119
|
-
return fs.readFileSync(skill.path, "utf-8");
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
return undefined;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Clears the cached skills. Call when skills directory contents may have changed.
|
|
127
|
-
*/
|
|
128
|
-
clearCache() {
|
|
129
|
-
this.cachedSkills = null;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
//# sourceMappingURL=loader.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/skills/loader.ts"],"names":[],"mappings":"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"}
|
package/dist/skills/tools.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { DynamicToolInterface } from "../tools/index.js";
|
|
2
|
-
import { SkillLoader } from "./loader.js";
|
|
3
|
-
export declare function bindSkillLoader(loader: SkillLoader): void;
|
|
4
|
-
export declare const SearchSkillsTool: DynamicToolInterface;
|
|
5
|
-
export declare const LoadSkillTool: DynamicToolInterface;
|
package/dist/skills/tools.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { SkillLoader } from "./loader.js";
|
|
2
|
-
// ─── Shared SkillLoader instance ──────────────────────────────────────────────
|
|
3
|
-
let _loader = null;
|
|
4
|
-
export function bindSkillLoader(loader) {
|
|
5
|
-
_loader = loader;
|
|
6
|
-
}
|
|
7
|
-
function getLoader() {
|
|
8
|
-
if (!_loader) {
|
|
9
|
-
_loader = new SkillLoader();
|
|
10
|
-
}
|
|
11
|
-
return _loader;
|
|
12
|
-
}
|
|
13
|
-
// ─── SearchSkillsTool ───────────────────────────────────────────────────────────
|
|
14
|
-
export const SearchSkillsTool = {
|
|
15
|
-
name: "search_skills",
|
|
16
|
-
description: "Search for available skills. Skills provide specialized instructions for specific tasks " +
|
|
17
|
-
"(e.g., deployment workflows, testing strategies, coding patterns).",
|
|
18
|
-
schema: {
|
|
19
|
-
type: "object",
|
|
20
|
-
properties: {
|
|
21
|
-
query: {
|
|
22
|
-
type: "string",
|
|
23
|
-
description: "Search query to match against skill names and descriptions (optional — omit to list all)",
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
execute: async (args) => {
|
|
28
|
-
const loader = getLoader();
|
|
29
|
-
let skills = loader.discoverSkills();
|
|
30
|
-
if (args?.query) {
|
|
31
|
-
const q = args.query.toLowerCase();
|
|
32
|
-
skills = skills.filter((s) => s.name.toLowerCase().includes(q) ||
|
|
33
|
-
s.description.toLowerCase().includes(q));
|
|
34
|
-
}
|
|
35
|
-
if (skills.length === 0) {
|
|
36
|
-
return {
|
|
37
|
-
content: args?.query
|
|
38
|
-
? `No skills found matching "${args.query}".`
|
|
39
|
-
: "No skills found. Create a skill by adding a folder with SKILL.md to ./skills/ or ~/.joone/skills/."
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
const list = skills
|
|
43
|
-
.map((s) => `- **${s.name}** (${s.source}): ${s.description}`)
|
|
44
|
-
.join("\n");
|
|
45
|
-
return {
|
|
46
|
-
content: `Found ${skills.length} skill(s):\n${list}\n\n` +
|
|
47
|
-
`To load a skill, call \`load_skill\` with the skill name.`
|
|
48
|
-
};
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
// ─── LoadSkillTool ──────────────────────────────────────────────────────────────
|
|
52
|
-
export const LoadSkillTool = {
|
|
53
|
-
name: "load_skill",
|
|
54
|
-
description: "Loads a specific skill's full instructions (SKILL.md content). " +
|
|
55
|
-
"Use search_skills first to discover available skills.",
|
|
56
|
-
schema: {
|
|
57
|
-
type: "object",
|
|
58
|
-
properties: {
|
|
59
|
-
name: {
|
|
60
|
-
type: "string",
|
|
61
|
-
description: "The name of the skill to load",
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
required: ["name"],
|
|
65
|
-
},
|
|
66
|
-
execute: async (args) => {
|
|
67
|
-
const loader = getLoader();
|
|
68
|
-
const content = loader.loadSkill(args.name);
|
|
69
|
-
if (!content) {
|
|
70
|
-
return {
|
|
71
|
-
content: `Error: Skill "${args.name}" not found. Use search_skills to see available skills.`,
|
|
72
|
-
isError: true
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
return { content };
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
//# sourceMappingURL=tools.js.map
|
package/dist/skills/tools.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/skills/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,iFAAiF;AAEjF,IAAI,OAAO,GAAuB,IAAI,CAAC;AAEvC,MAAM,UAAU,eAAe,CAAC,MAAmB;IACjD,OAAO,GAAG,MAAM,CAAC;AACnB,CAAC;AAED,SAAS,SAAS;IAChB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,mFAAmF;AAEnF,MAAM,CAAC,MAAM,gBAAgB,GAAyB;IACpD,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,0FAA0F;QAC1F,oEAAoE;IACtE,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,0FAA0F;aAC7F;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAAyB,EAAuB,EAAE;QAChE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,IAAI,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QAErC,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACnC,MAAM,GAAG,MAAM,CAAC,MAAM,CACpB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAChC,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC1C,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;gBACL,OAAO,EAAE,IAAI,EAAE,KAAK;oBAClB,CAAC,CAAC,6BAA6B,IAAI,CAAC,KAAK,IAAI;oBAC7C,CAAC,CAAC,oGAAoG;aACzG,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM;aAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;aAC7D,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,OAAO;YACL,OAAO,EACL,SAAS,MAAM,CAAC,MAAM,eAAe,IAAI,MAAM;gBAC/C,2DAA2D;SAC9D,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,mFAAmF;AAEnF,MAAM,CAAC,MAAM,aAAa,GAAyB;IACjD,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,iEAAiE;QACjE,uDAAuD;IACzD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+BAA+B;aAC7C;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;IACD,OAAO,EAAE,KAAK,EAAE,IAAsB,EAAuB,EAAE;QAC7D,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,iBAAiB,IAAI,CAAC,IAAI,yDAAyD;gBAC5F,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;CACF,CAAC"}
|
package/dist/test_cache.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "dotenv/config";
|
package/dist/test_cache.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import "dotenv/config";
|
|
2
|
-
import { ChatAnthropic } from "@langchain/anthropic";
|
|
3
|
-
import { ExecutionHarness } from "./core/agentLoop.js";
|
|
4
|
-
import { HumanMessage } from "@langchain/core/messages";
|
|
5
|
-
async function runCacheTest() {
|
|
6
|
-
console.log("=== Starting Prompt Caching Test ===\n");
|
|
7
|
-
// We need Anthropic API Key for this to actually hit the network and measure cache
|
|
8
|
-
if (!process.env.ANTHROPIC_API_KEY) {
|
|
9
|
-
console.warn("WARNING: ANTHROPIC_API_KEY is not set in .env file. The LLM call will fail.");
|
|
10
|
-
}
|
|
11
|
-
const model = new ChatAnthropic({
|
|
12
|
-
modelName: "claude-3-5-sonnet-20241022",
|
|
13
|
-
temperature: 0,
|
|
14
|
-
maxTokens: 4096,
|
|
15
|
-
}); // No tools needed for this basic string test
|
|
16
|
-
const harness = new ExecutionHarness(model, []);
|
|
17
|
-
// 1. Create a massive static prefix (simulating a lot of project context)
|
|
18
|
-
// We repeat a string many times to ensure we pass the 1024 token minimum for Anthropic caching.
|
|
19
|
-
const massiveProjectMemory = Array(500).fill("Project Rule: Always write clean, modular TypeScript code with strict typings. ").join("\n");
|
|
20
|
-
const state = {
|
|
21
|
-
globalSystemInstructions: "You are a helpful coding assistant. You remember rules carefully.",
|
|
22
|
-
projectMemory: massiveProjectMemory,
|
|
23
|
-
sessionContext: "User OS: Windows 11",
|
|
24
|
-
conversationHistory: []
|
|
25
|
-
};
|
|
26
|
-
console.log("Turn 1: Initial Query (Should create cache)");
|
|
27
|
-
state.conversationHistory.push(new HumanMessage("Hello! What is one of the project rules?"));
|
|
28
|
-
const response1 = await harness.step(state);
|
|
29
|
-
state.conversationHistory.push(response1);
|
|
30
|
-
// In @langchain/anthropic, the actual usage stats (including cache hits/misses)
|
|
31
|
-
// are stored in the response_metadata of the AIMessage.
|
|
32
|
-
console.log(`Response 1: ${response1.content}`);
|
|
33
|
-
console.log(`Token Usage 1: ${JSON.stringify(response1.response_metadata?.usage, null, 2)}\n`);
|
|
34
|
-
// --- TURN 2 ---
|
|
35
|
-
console.log("Turn 2: Follow-up Query (Should hit cache)");
|
|
36
|
-
// We DO NOT change the globalSystemInstructions, projectMemory, or sessionContext.
|
|
37
|
-
// We only append to the conversation history. This preserves the prefix!
|
|
38
|
-
state.conversationHistory.push(new HumanMessage("Could you summarize the rule again briefly?"));
|
|
39
|
-
const response2 = await harness.step(state);
|
|
40
|
-
state.conversationHistory.push(response2);
|
|
41
|
-
console.log(`Response 2: ${response2.content}`);
|
|
42
|
-
console.log(`Token Usage 2: ${JSON.stringify(response2.response_metadata?.usage, null, 2)}\n`);
|
|
43
|
-
// --- TURN 3: The System Reminder Pattern ---
|
|
44
|
-
console.log("Turn 3: Using <system-reminder> to simulate environment change without breaking cache");
|
|
45
|
-
// If a file changed, we DON'T update `state.projectMemory`. We inject a reminder.
|
|
46
|
-
state.conversationHistory.push(new HumanMessage("<system-reminder>\nThe file 'auth.ts' has just been deleted by the user.\n</system-reminder>\nWhat should we do if we need auth now?"));
|
|
47
|
-
const response3 = await harness.step(state);
|
|
48
|
-
state.conversationHistory.push(response3);
|
|
49
|
-
console.log(`Response 3: ${response3.content}`);
|
|
50
|
-
console.log(`Token Usage 3: ${JSON.stringify(response3.response_metadata?.usage, null, 2)}\n`);
|
|
51
|
-
}
|
|
52
|
-
if (require.main === module) {
|
|
53
|
-
runCacheTest().catch(console.error);
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=test_cache.js.map
|
package/dist/test_cache.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test_cache.js","sourceRoot":"","sources":["../src/test_cache.ts"],"names":[],"mappings":"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"}
|
package/dist/test_google.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/test_google.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
|
|
2
|
-
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
3
|
-
import * as dotenv from "dotenv";
|
|
4
|
-
dotenv.config();
|
|
5
|
-
async function main() {
|
|
6
|
-
const model = new ChatGoogleGenerativeAI({
|
|
7
|
-
model: "gemini-2.5-flash",
|
|
8
|
-
});
|
|
9
|
-
const messagesGrouped = [
|
|
10
|
-
new SystemMessage("You are a helpful assistant."),
|
|
11
|
-
new SystemMessage("Also, be concise."),
|
|
12
|
-
new HumanMessage("Hello!"),
|
|
13
|
-
];
|
|
14
|
-
try {
|
|
15
|
-
await model.invoke(messagesGrouped);
|
|
16
|
-
console.log("Success: Grouped SystemMessages at the start work perfectly.");
|
|
17
|
-
}
|
|
18
|
-
catch (e) {
|
|
19
|
-
console.error("Grouped systems failed:", e.message);
|
|
20
|
-
}
|
|
21
|
-
const messagesMidstream = [
|
|
22
|
-
new SystemMessage("You are a helpful assistant."),
|
|
23
|
-
new HumanMessage("Hello!"),
|
|
24
|
-
new SystemMessage("System recovery hint here."),
|
|
25
|
-
new HumanMessage("What did I say?"),
|
|
26
|
-
];
|
|
27
|
-
try {
|
|
28
|
-
await model.invoke(messagesMidstream);
|
|
29
|
-
console.log("Success: Mid-stream SystemMessages work.");
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
console.error("Midstream systems failed:", e.message);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
main();
|
|
36
|
-
//# sourceMappingURL=test_google.js.map
|
package/dist/test_google.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test_google.js","sourceRoot":"","sources":["../src/test_google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,KAAK,UAAU,IAAI;IACjB,MAAM,KAAK,GAAG,IAAI,sBAAsB,CAAC;QACvC,KAAK,EAAE,kBAAkB;KAC1B,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG;QACtB,IAAI,aAAa,CAAC,8BAA8B,CAAC;QACjD,IAAI,aAAa,CAAC,mBAAmB,CAAC;QACtC,IAAI,YAAY,CAAC,QAAQ,CAAC;KAC3B,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,iBAAiB,GAAG;QACxB,IAAI,aAAa,CAAC,8BAA8B,CAAC;QACjD,IAAI,YAAY,CAAC,QAAQ,CAAC;QAC1B,IAAI,aAAa,CAAC,4BAA4B,CAAC;QAC/C,IAAI,YAAY,CAAC,iBAAiB,CAAC;KACpC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/tools/browser.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { SandboxManager } from "../sandbox/manager.js";
|
|
2
|
-
import { LazyInstaller } from "../sandbox/bootstrap.js";
|
|
3
|
-
import { DynamicToolInterface } from "./index.js";
|
|
4
|
-
export declare function bindBrowserSandbox(sandbox: SandboxManager, installer: LazyInstaller): void;
|
|
5
|
-
/**
|
|
6
|
-
* Web Browser Tool — wraps Vercel Labs' `agent-browser` CLI.
|
|
7
|
-
*
|
|
8
|
-
* Provides compact accessibility-tree output optimized for LLMs
|
|
9
|
-
* (low token usage vs raw HTML). Runs inside the E2B sandbox.
|
|
10
|
-
*
|
|
11
|
-
* Supported actions:
|
|
12
|
-
* - navigate: Go to a URL
|
|
13
|
-
* - snapshot: Get the accessibility tree (compact text representation)
|
|
14
|
-
* - click: Click an element by ref
|
|
15
|
-
* - type: Type text into a form field by ref
|
|
16
|
-
* - screenshot: Capture a screenshot
|
|
17
|
-
* - scroll: Scroll the page up or down
|
|
18
|
-
*/
|
|
19
|
-
export declare const BrowserTool: DynamicToolInterface;
|