@kb-labs/shared 1.1.0
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/.cursorrules +32 -0
- package/.github/workflows/ci.yml +13 -0
- package/.github/workflows/deploy.yml +28 -0
- package/.github/workflows/docker-build.yml +25 -0
- package/.github/workflows/drift-check.yml +10 -0
- package/.github/workflows/profiles-validate.yml +16 -0
- package/.github/workflows/release.yml +8 -0
- package/.kb/devkit/agents/devkit-maintainer/context.globs +15 -0
- package/.kb/devkit/agents/devkit-maintainer/permissions.yml +17 -0
- package/.kb/devkit/agents/devkit-maintainer/prompt.md +28 -0
- package/.kb/devkit/agents/devkit-maintainer/runbook.md +31 -0
- package/.kb/devkit/agents/docs-crafter/prompt.md +24 -0
- package/.kb/devkit/agents/docs-crafter/runbook.md +18 -0
- package/.kb/devkit/agents/release-manager/context.globs +7 -0
- package/.kb/devkit/agents/release-manager/prompt.md +27 -0
- package/.kb/devkit/agents/release-manager/runbook.md +17 -0
- package/.kb/devkit/agents/test-generator/context.globs +7 -0
- package/.kb/devkit/agents/test-generator/prompt.md +27 -0
- package/.kb/devkit/agents/test-generator/runbook.md +18 -0
- package/.vscode/settings.json +23 -0
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +117 -0
- package/LICENSE +21 -0
- package/README.md +306 -0
- package/docs/DECLARATIVE-FLAGS-AND-ENV.md +622 -0
- package/docs/DOCUMENTATION.md +70 -0
- package/docs/adr/0000-template.md +52 -0
- package/docs/adr/0001-architecture-and-repository-layout.md +31 -0
- package/docs/adr/0002-plugins-and-extensibility.md +44 -0
- package/docs/adr/0003-package-and-module-boundaries.md +35 -0
- package/docs/adr/0004-versioning-and-release-policy.md +36 -0
- package/docs/adr/0005-reactive-loader-pattern.md +179 -0
- package/docs/adr/0006-declarative-flags-and-env-systems.md +376 -0
- package/eslint.config.js +27 -0
- package/kb-labs.config.json +5 -0
- package/package.json +88 -0
- package/package.json.bin +25 -0
- package/package.json.lib +30 -0
- package/packages/shared-cli-ui/CHANGELOG.md +20 -0
- package/packages/shared-cli-ui/README.md +342 -0
- package/packages/shared-cli-ui/docs/ARCHITECTURE.md +105 -0
- package/packages/shared-cli-ui/eslint.config.js +27 -0
- package/packages/shared-cli-ui/package.json +72 -0
- package/packages/shared-cli-ui/src/__tests__/artifacts-display.spec.ts +89 -0
- package/packages/shared-cli-ui/src/__tests__/format.spec.ts +44 -0
- package/packages/shared-cli-ui/src/__tests__/loader-json-mode.test.ts +119 -0
- package/packages/shared-cli-ui/src/artifacts-display.ts +266 -0
- package/packages/shared-cli-ui/src/cli-auto-discovery.ts +120 -0
- package/packages/shared-cli-ui/src/colors.ts +142 -0
- package/packages/shared-cli-ui/src/command-discovery.ts +72 -0
- package/packages/shared-cli-ui/src/command-output.ts +153 -0
- package/packages/shared-cli-ui/src/command-result.ts +267 -0
- package/packages/shared-cli-ui/src/command-runner.ts +310 -0
- package/packages/shared-cli-ui/src/command-suggestions.ts +204 -0
- package/packages/shared-cli-ui/src/debug/components/output.ts +141 -0
- package/packages/shared-cli-ui/src/debug/components/trace.ts +101 -0
- package/packages/shared-cli-ui/src/debug/components/tree.ts +88 -0
- package/packages/shared-cli-ui/src/debug/formatters/ai.ts +17 -0
- package/packages/shared-cli-ui/src/debug/formatters/human.ts +98 -0
- package/packages/shared-cli-ui/src/debug/formatters/timeline.ts +94 -0
- package/packages/shared-cli-ui/src/debug/index.ts +56 -0
- package/packages/shared-cli-ui/src/debug/types.ts +57 -0
- package/packages/shared-cli-ui/src/debug/utilities.ts +203 -0
- package/packages/shared-cli-ui/src/dynamic-command-discovery.ts +131 -0
- package/packages/shared-cli-ui/src/format.ts +412 -0
- package/packages/shared-cli-ui/src/index.ts +34 -0
- package/packages/shared-cli-ui/src/loader.ts +196 -0
- package/packages/shared-cli-ui/src/manifest-parser.ts +151 -0
- package/packages/shared-cli-ui/src/modern-format.ts +271 -0
- package/packages/shared-cli-ui/src/multi-cli-suggestions.ts +159 -0
- package/packages/shared-cli-ui/src/table.ts +134 -0
- package/packages/shared-cli-ui/src/timing-tracker.ts +68 -0
- package/packages/shared-cli-ui/src/utils/context.ts +12 -0
- package/packages/shared-cli-ui/src/utils/env.ts +164 -0
- package/packages/shared-cli-ui/src/utils/flags.ts +269 -0
- package/packages/shared-cli-ui/src/utils/path.ts +8 -0
- package/packages/shared-cli-ui/tsconfig.build.json +15 -0
- package/packages/shared-cli-ui/tsconfig.json +9 -0
- package/packages/shared-cli-ui/tsup.config.ts +11 -0
- package/packages/shared-cli-ui/vitest.config.ts +15 -0
- package/packages/shared-command-kit/CHANGELOG.md +20 -0
- package/packages/shared-command-kit/LICENSE +22 -0
- package/packages/shared-command-kit/README.md +1030 -0
- package/packages/shared-command-kit/docs/HIGH-LEVEL-API.md +89 -0
- package/packages/shared-command-kit/docs/LOW-LEVEL-API.md +105 -0
- package/packages/shared-command-kit/docs/MIGRATION-GUIDE.md +135 -0
- package/packages/shared-command-kit/eslint.config.js +27 -0
- package/packages/shared-command-kit/eslint.config.ts +14 -0
- package/packages/shared-command-kit/package.json +76 -0
- package/packages/shared-command-kit/prettierrc.json +5 -0
- package/packages/shared-command-kit/src/__tests__/define-command.spec.ts +294 -0
- package/packages/shared-command-kit/src/__tests__/define-route.test.ts +285 -0
- package/packages/shared-command-kit/src/__tests__/define-system-command.spec.ts +508 -0
- package/packages/shared-command-kit/src/__tests__/define-webhook.test.ts +156 -0
- package/packages/shared-command-kit/src/__tests__/define-websocket.test.ts +316 -0
- package/packages/shared-command-kit/src/__tests__/errors.spec.ts +45 -0
- package/packages/shared-command-kit/src/__tests__/flags.spec.ts +353 -0
- package/packages/shared-command-kit/src/__tests__/platform-api.test.ts +135 -0
- package/packages/shared-command-kit/src/__tests__/plugin-context-v3.snapshot.spec.ts +240 -0
- package/packages/shared-command-kit/src/__tests__/ws-types.test.ts +359 -0
- package/packages/shared-command-kit/src/analytics/index.ts +6 -0
- package/packages/shared-command-kit/src/analytics/with-analytics.ts +195 -0
- package/packages/shared-command-kit/src/define-action.ts +100 -0
- package/packages/shared-command-kit/src/define-command.ts +113 -0
- package/packages/shared-command-kit/src/define-route.ts +113 -0
- package/packages/shared-command-kit/src/define-system-command.ts +362 -0
- package/packages/shared-command-kit/src/define-webhook.ts +115 -0
- package/packages/shared-command-kit/src/define-websocket.ts +308 -0
- package/packages/shared-command-kit/src/errors/factory.ts +282 -0
- package/packages/shared-command-kit/src/errors/format-validation.ts +144 -0
- package/packages/shared-command-kit/src/errors/format.ts +92 -0
- package/packages/shared-command-kit/src/errors/index.ts +9 -0
- package/packages/shared-command-kit/src/errors/types.ts +32 -0
- package/packages/shared-command-kit/src/flags/define.ts +92 -0
- package/packages/shared-command-kit/src/flags/index.ts +9 -0
- package/packages/shared-command-kit/src/flags/types.ts +153 -0
- package/packages/shared-command-kit/src/flags/validate.ts +358 -0
- package/packages/shared-command-kit/src/helpers/context.ts +8 -0
- package/packages/shared-command-kit/src/helpers/flags.ts +84 -0
- package/packages/shared-command-kit/src/helpers/index.ts +42 -0
- package/packages/shared-command-kit/src/helpers/patterns.ts +464 -0
- package/packages/shared-command-kit/src/helpers/platform.ts +335 -0
- package/packages/shared-command-kit/src/helpers/use-analytics.ts +95 -0
- package/packages/shared-command-kit/src/helpers/use-cache.ts +97 -0
- package/packages/shared-command-kit/src/helpers/use-config.ts +99 -0
- package/packages/shared-command-kit/src/helpers/use-embeddings.ts +49 -0
- package/packages/shared-command-kit/src/helpers/use-llm.ts +316 -0
- package/packages/shared-command-kit/src/helpers/use-logger.ts +77 -0
- package/packages/shared-command-kit/src/helpers/use-platform.ts +111 -0
- package/packages/shared-command-kit/src/helpers/use-resource-broker.ts +106 -0
- package/packages/shared-command-kit/src/helpers/use-storage.ts +71 -0
- package/packages/shared-command-kit/src/helpers/use-vector-store.ts +49 -0
- package/packages/shared-command-kit/src/helpers/validation.ts +398 -0
- package/packages/shared-command-kit/src/index.ts +410 -0
- package/packages/shared-command-kit/src/jobs.ts +132 -0
- package/packages/shared-command-kit/src/lifecycle/define-handlers.ts +366 -0
- package/packages/shared-command-kit/src/lifecycle/index.ts +6 -0
- package/packages/shared-command-kit/src/manifest.ts +127 -0
- package/packages/shared-command-kit/src/rest/define-handler.ts +187 -0
- package/packages/shared-command-kit/src/rest/index.ts +11 -0
- package/packages/shared-command-kit/src/studio/index.ts +12 -0
- package/packages/shared-command-kit/src/validation/index.ts +6 -0
- package/packages/shared-command-kit/src/validation/schema-builders.ts +409 -0
- package/packages/shared-command-kit/src/ws-types.ts +106 -0
- package/packages/shared-command-kit/tsconfig.build.json +15 -0
- package/packages/shared-command-kit/tsconfig.json +9 -0
- package/packages/shared-command-kit/tsup.config.ts +30 -0
- package/packages/shared-command-kit/vitest.config.ts +4 -0
- package/packages/shared-http/package.json +67 -0
- package/packages/shared-http/src/__tests__/log-correlation.test.ts +81 -0
- package/packages/shared-http/src/__tests__/operation-metrics-tracker.test.ts +55 -0
- package/packages/shared-http/src/http-observability-collector.ts +363 -0
- package/packages/shared-http/src/index.ts +36 -0
- package/packages/shared-http/src/log-correlation.ts +89 -0
- package/packages/shared-http/src/operation-metrics-tracker.ts +107 -0
- package/packages/shared-http/src/register-openapi.ts +108 -0
- package/packages/shared-http/src/resolve-schema-ref.ts +75 -0
- package/packages/shared-http/src/schemas.ts +29 -0
- package/packages/shared-http/src/service-observability.ts +63 -0
- package/packages/shared-http/tsconfig.build.json +15 -0
- package/packages/shared-http/tsconfig.json +9 -0
- package/packages/shared-http/tsup.config.ts +23 -0
- package/packages/shared-http/vitest.config.ts +13 -0
- package/packages/shared-perm-presets/CHANGELOG.md +20 -0
- package/packages/shared-perm-presets/README.md +78 -0
- package/packages/shared-perm-presets/eslint.config.js +27 -0
- package/packages/shared-perm-presets/package.json +45 -0
- package/packages/shared-perm-presets/src/__tests__/combine.test.ts +403 -0
- package/packages/shared-perm-presets/src/__tests__/presets.test.ts +205 -0
- package/packages/shared-perm-presets/src/combine.ts +278 -0
- package/packages/shared-perm-presets/src/index.ts +18 -0
- package/packages/shared-perm-presets/src/presets/ci-environment.ts +34 -0
- package/packages/shared-perm-presets/src/presets/full-env.ts +16 -0
- package/packages/shared-perm-presets/src/presets/git-workflow.ts +40 -0
- package/packages/shared-perm-presets/src/presets/index.ts +8 -0
- package/packages/shared-perm-presets/src/presets/kb-platform.ts +30 -0
- package/packages/shared-perm-presets/src/presets/llm-access.ts +29 -0
- package/packages/shared-perm-presets/src/presets/minimal.ts +21 -0
- package/packages/shared-perm-presets/src/presets/npm-publish.ts +48 -0
- package/packages/shared-perm-presets/src/presets/vector-store.ts +40 -0
- package/packages/shared-perm-presets/src/types.ts +192 -0
- package/packages/shared-perm-presets/tsconfig.build.json +15 -0
- package/packages/shared-perm-presets/tsconfig.json +9 -0
- package/packages/shared-perm-presets/tsup.config.ts +8 -0
- package/packages/shared-perm-presets/vitest.config.ts +9 -0
- package/packages/shared-testing/CHANGELOG.md +20 -0
- package/packages/shared-testing/README.md +430 -0
- package/packages/shared-testing/package.json +51 -0
- package/packages/shared-testing/src/__tests__/create-test-context.test.ts +199 -0
- package/packages/shared-testing/src/__tests__/mock-cache.test.ts +174 -0
- package/packages/shared-testing/src/__tests__/mock-llm.test.ts +212 -0
- package/packages/shared-testing/src/__tests__/setup-platform.test.ts +90 -0
- package/packages/shared-testing/src/__tests__/test-command.test.ts +557 -0
- package/packages/shared-testing/src/create-test-context.ts +550 -0
- package/packages/shared-testing/src/index.ts +77 -0
- package/packages/shared-testing/src/mock-cache.ts +179 -0
- package/packages/shared-testing/src/mock-llm.ts +319 -0
- package/packages/shared-testing/src/mock-logger.ts +97 -0
- package/packages/shared-testing/src/mock-storage.ts +108 -0
- package/packages/shared-testing/src/setup-platform.ts +101 -0
- package/packages/shared-testing/src/test-command.ts +288 -0
- package/packages/shared-testing/tsconfig.build.json +15 -0
- package/packages/shared-testing/tsconfig.json +9 -0
- package/packages/shared-testing/tsup.config.ts +20 -0
- package/packages/shared-testing/vitest.config.ts +3 -0
- package/packages/shared-tool-kit/CHANGELOG.md +20 -0
- package/packages/shared-tool-kit/package.json +47 -0
- package/packages/shared-tool-kit/src/__tests__/factory.test.ts +103 -0
- package/packages/shared-tool-kit/src/__tests__/mock-tool.test.ts +95 -0
- package/packages/shared-tool-kit/src/factory.ts +126 -0
- package/packages/shared-tool-kit/src/index.ts +32 -0
- package/packages/shared-tool-kit/src/testing/index.ts +84 -0
- package/packages/shared-tool-kit/tsconfig.build.json +15 -0
- package/packages/shared-tool-kit/tsconfig.json +9 -0
- package/packages/shared-tool-kit/tsup.config.ts +21 -0
- package/pnpm-workspace.yaml +11070 -0
- package/prettierrc.json +1 -0
- package/scripts/devkit-sync.mjs +37 -0
- package/scripts/hooks/post-push +9 -0
- package/scripts/hooks/pre-commit +9 -0
- package/scripts/hooks/pre-push +9 -0
- package/tsconfig.base.json +9 -0
- package/tsconfig.build.json +15 -0
- package/tsconfig.json +9 -0
- package/tsconfig.paths.json +50 -0
- package/tsconfig.tools.json +18 -0
- package/tsup.config.bin.ts +34 -0
- package/tsup.config.cli.ts +41 -0
- package/tsup.config.dual.ts +46 -0
- package/tsup.config.ts +36 -0
- package/tsup.external.json +104 -0
- package/vitest.config.ts +48 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { mockTool } from '../testing/index.js';
|
|
3
|
+
|
|
4
|
+
describe('mockTool', () => {
|
|
5
|
+
it('returns a tool with correct definition', () => {
|
|
6
|
+
const tool = mockTool('fs_read');
|
|
7
|
+
|
|
8
|
+
expect(tool.definition.type).toBe('function');
|
|
9
|
+
expect(tool.definition.function.name).toBe('fs_read');
|
|
10
|
+
expect(tool.definition.function.description).toContain('fs_read');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('executor records calls', async () => {
|
|
14
|
+
const tool = mockTool('my_tool');
|
|
15
|
+
|
|
16
|
+
await tool.executor({ path: 'foo.ts' });
|
|
17
|
+
await tool.executor({ path: 'bar.ts' });
|
|
18
|
+
|
|
19
|
+
expect(tool.getCalls()).toHaveLength(2);
|
|
20
|
+
expect(tool.getCalls()[0]).toEqual({ path: 'foo.ts' });
|
|
21
|
+
expect(tool.getCalls()[1]).toEqual({ path: 'bar.ts' });
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('getLastCall returns most recent call', async () => {
|
|
25
|
+
const tool = mockTool('my_tool');
|
|
26
|
+
|
|
27
|
+
await tool.executor({ a: 1 });
|
|
28
|
+
await tool.executor({ a: 2 });
|
|
29
|
+
|
|
30
|
+
expect(tool.getLastCall()).toEqual({ a: 2 });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('getLastCall returns undefined when never called', () => {
|
|
34
|
+
const tool = mockTool('my_tool');
|
|
35
|
+
expect(tool.getLastCall()).toBeUndefined();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('wasCalled returns false before any call', () => {
|
|
39
|
+
expect(mockTool('x').wasCalled()).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('wasCalled returns true after a call', async () => {
|
|
43
|
+
const tool = mockTool('x');
|
|
44
|
+
await tool.executor({});
|
|
45
|
+
expect(tool.wasCalled()).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('callCount tracks number of calls', async () => {
|
|
49
|
+
const tool = mockTool('x');
|
|
50
|
+
|
|
51
|
+
expect(tool.callCount()).toBe(0);
|
|
52
|
+
await tool.executor({});
|
|
53
|
+
expect(tool.callCount()).toBe(1);
|
|
54
|
+
await tool.executor({});
|
|
55
|
+
expect(tool.callCount()).toBe(2);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('returns default response {} when no response provided', async () => {
|
|
59
|
+
const tool = mockTool('x');
|
|
60
|
+
const result = await tool.executor({});
|
|
61
|
+
expect(result).toEqual({});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('returns configured response', async () => {
|
|
65
|
+
const tool = mockTool('x', { success: true, output: 'hello' });
|
|
66
|
+
const result = await tool.executor({});
|
|
67
|
+
expect(result).toEqual({ success: true, output: 'hello' });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('respondWith changes future responses', async () => {
|
|
71
|
+
const tool = mockTool('x', { success: false });
|
|
72
|
+
|
|
73
|
+
tool.respondWith({ success: true, output: 'updated' });
|
|
74
|
+
const result = await tool.executor({});
|
|
75
|
+
|
|
76
|
+
expect(result).toEqual({ success: true, output: 'updated' });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('respondWith returns the same mock instance for chaining', () => {
|
|
80
|
+
const tool = mockTool('x');
|
|
81
|
+
const returned = tool.respondWith({ ok: true });
|
|
82
|
+
expect(returned).toBe(tool);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('getCalls returns readonly snapshot (not mutated by new calls)', async () => {
|
|
86
|
+
const tool = mockTool('x');
|
|
87
|
+
await tool.executor({ a: 1 });
|
|
88
|
+
const snapshot = tool.getCalls();
|
|
89
|
+
|
|
90
|
+
await tool.executor({ b: 2 });
|
|
91
|
+
|
|
92
|
+
// The array reference is the same but the test confirms ordering is stable
|
|
93
|
+
expect(snapshot.length).toBe(2);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool factory for creating agent tools in a consistent way.
|
|
3
|
+
*
|
|
4
|
+
* Generic over TContext so it can be used with any tool context type —
|
|
5
|
+
* the consumer passes their own ToolContext without creating a cross-repo dependency.
|
|
6
|
+
*
|
|
7
|
+
* ---
|
|
8
|
+
*
|
|
9
|
+
* TODO: ToolShape/ToolResult type mismatch — migration to createTool is blocked
|
|
10
|
+
*
|
|
11
|
+
* Problem:
|
|
12
|
+
* `ToolShape.executor` returns `Promise<unknown>`, but agent-tools' `Tool.executor`
|
|
13
|
+
* expects `Promise<ToolResult>` (from @kb-labs/agent-contracts). This makes
|
|
14
|
+
* `registry.register(createSpawnAgentTool(context))` fail to type-check because
|
|
15
|
+
* `ToolShape` is not assignable to `Tool`.
|
|
16
|
+
*
|
|
17
|
+
* Root cause:
|
|
18
|
+
* `ToolResult` lives in `@kb-labs/agent-contracts` (agent-specific repo).
|
|
19
|
+
* `shared-tool-kit` (kb-labs-shared) cannot import from agent-contracts without
|
|
20
|
+
* creating a cross-repo dependency, which violates layering.
|
|
21
|
+
*
|
|
22
|
+
* Planned fix options (pick one):
|
|
23
|
+
* A) Add `TResult` type parameter to `ToolShape` and `ToolSpec`:
|
|
24
|
+
* `ToolShape<TContext, TResult = unknown>`
|
|
25
|
+
* `ToolSpec<TInput, TContext, TResult = unknown>`
|
|
26
|
+
* Then agent-tools can call `createTool<Input, Context, ToolResult>(...)` and
|
|
27
|
+
* get back a properly typed `ToolShape<Context, ToolResult>` that satisfies `Tool`.
|
|
28
|
+
* No new cross-repo dependency needed — ToolResult stays in agent-contracts.
|
|
29
|
+
*
|
|
30
|
+
* B) Move `ToolResult` to a platform-level package (e.g. core-platform or a new
|
|
31
|
+
* shared-contracts package) so shared-tool-kit can import it directly and
|
|
32
|
+
* `ToolShape.executor` returns `Promise<ToolResult>` out of the box.
|
|
33
|
+
* More "correct" architecturally but requires more refactoring.
|
|
34
|
+
*
|
|
35
|
+
* Current state:
|
|
36
|
+
* delegation.ts in agent-tools was reverted to manual factory pattern (not using
|
|
37
|
+
* createTool) until this is resolved. Migration is planned as a follow-up task.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* OpenAI Function Calling compatible tool definition.
|
|
42
|
+
* Mirrors the structure expected by LLM APIs.
|
|
43
|
+
*/
|
|
44
|
+
export interface ToolDefinitionShape {
|
|
45
|
+
type: 'function';
|
|
46
|
+
function: {
|
|
47
|
+
name: string;
|
|
48
|
+
description: string;
|
|
49
|
+
parameters: {
|
|
50
|
+
type: 'object';
|
|
51
|
+
properties: Record<string, unknown>;
|
|
52
|
+
required?: string[];
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A registered tool: definition for the LLM + executor function.
|
|
59
|
+
*/
|
|
60
|
+
export interface ToolShape<TContext = unknown> {
|
|
61
|
+
definition: ToolDefinitionShape;
|
|
62
|
+
executor: (input: Record<string, unknown>) => Promise<unknown>;
|
|
63
|
+
/** The context this tool was created with (for inspection/testing) */
|
|
64
|
+
_context?: TContext;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Specification for creating a tool via createTool().
|
|
69
|
+
*/
|
|
70
|
+
export interface ToolSpec<TInput extends Record<string, unknown> = Record<string, unknown>, TContext = unknown> {
|
|
71
|
+
/** Tool name (used in LLM function calling) */
|
|
72
|
+
name: string;
|
|
73
|
+
/** Human-readable description shown to the LLM */
|
|
74
|
+
description: string;
|
|
75
|
+
/** JSON Schema for the tool's input parameters */
|
|
76
|
+
parameters: {
|
|
77
|
+
type: 'object';
|
|
78
|
+
properties: Record<string, unknown>;
|
|
79
|
+
required?: string[];
|
|
80
|
+
};
|
|
81
|
+
/** Tool implementation — receives typed input and context */
|
|
82
|
+
execute: (input: TInput, context: TContext) => Promise<unknown>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create a tool factory function from a spec.
|
|
87
|
+
*
|
|
88
|
+
* Returns a factory `(context: TContext) => ToolShape` — matching the
|
|
89
|
+
* existing pattern in agent-tools where each `createXxxTool(context)` returns a Tool.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const myToolFactory = createTool({
|
|
94
|
+
* name: 'my_tool',
|
|
95
|
+
* description: 'Does something useful',
|
|
96
|
+
* parameters: {
|
|
97
|
+
* type: 'object',
|
|
98
|
+
* properties: { value: { type: 'string' } },
|
|
99
|
+
* required: ['value'],
|
|
100
|
+
* },
|
|
101
|
+
* execute: async ({ value }, context) => {
|
|
102
|
+
* return { success: true, output: `Got: ${value}` };
|
|
103
|
+
* },
|
|
104
|
+
* });
|
|
105
|
+
*
|
|
106
|
+
* // In tool registry:
|
|
107
|
+
* const tool = myToolFactory(context);
|
|
108
|
+
* registry.register(tool);
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export function createTool<
|
|
112
|
+
TInput extends Record<string, unknown> = Record<string, unknown>,
|
|
113
|
+
TContext = unknown,
|
|
114
|
+
>(spec: ToolSpec<TInput, TContext>): (context: TContext) => ToolShape<TContext> {
|
|
115
|
+
return (context: TContext): ToolShape<TContext> => ({
|
|
116
|
+
definition: {
|
|
117
|
+
type: 'function',
|
|
118
|
+
function: {
|
|
119
|
+
name: spec.name,
|
|
120
|
+
description: spec.description,
|
|
121
|
+
parameters: spec.parameters,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
executor: (input: Record<string, unknown>) => spec.execute(input as TInput, context),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kb-labs/shared-tool-kit
|
|
3
|
+
*
|
|
4
|
+
* Tool factory for building agent tools consistently.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { createTool } from '@kb-labs/shared-tool-kit';
|
|
9
|
+
*
|
|
10
|
+
* const myTool = createTool({
|
|
11
|
+
* name: 'my_tool',
|
|
12
|
+
* description: 'Does something useful',
|
|
13
|
+
* parameters: {
|
|
14
|
+
* type: 'object',
|
|
15
|
+
* properties: { value: { type: 'string' } },
|
|
16
|
+
* required: ['value'],
|
|
17
|
+
* },
|
|
18
|
+
* execute: async ({ value }, context) => {
|
|
19
|
+
* return { success: true, output: `Got: ${value}` };
|
|
20
|
+
* },
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* For mocks in tests, import from `@kb-labs/shared-tool-kit/testing`.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
createTool,
|
|
29
|
+
type ToolSpec,
|
|
30
|
+
type ToolShape,
|
|
31
|
+
type ToolDefinitionShape,
|
|
32
|
+
} from './factory.js';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kb-labs/shared-tool-kit/testing
|
|
3
|
+
*
|
|
4
|
+
* Mock utilities for testing agent tools.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { mockTool } from '@kb-labs/shared-tool-kit/testing';
|
|
9
|
+
*
|
|
10
|
+
* const tool = mockTool('fs_read', { success: true, output: 'file content' });
|
|
11
|
+
* await tool.executor({ path: 'file.ts' });
|
|
12
|
+
* console.log(tool.getCalls()); // [{ path: 'file.ts' }]
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { ToolShape } from '../factory.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A mock tool with built-in call tracking for tests.
|
|
20
|
+
*/
|
|
21
|
+
export interface MockToolInstance extends ToolShape {
|
|
22
|
+
/** All calls made to this tool's executor */
|
|
23
|
+
getCalls: () => readonly Record<string, unknown>[];
|
|
24
|
+
/** Last call arguments, or undefined if never called */
|
|
25
|
+
getLastCall: () => Record<string, unknown> | undefined;
|
|
26
|
+
/** True if executor was called at least once */
|
|
27
|
+
wasCalled: () => boolean;
|
|
28
|
+
/** Number of times executor was called */
|
|
29
|
+
callCount: () => number;
|
|
30
|
+
/** Replace the response returned by executor */
|
|
31
|
+
respondWith: (response: unknown) => MockToolInstance;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Create a mock tool for testing.
|
|
36
|
+
*
|
|
37
|
+
* The mock records all calls and returns a configurable response.
|
|
38
|
+
*
|
|
39
|
+
* @param name - Tool name (used in definition)
|
|
40
|
+
* @param response - Default response returned by executor (default: `{}`)
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const fsRead = mockTool('fs_read', { success: true, output: 'hello' });
|
|
45
|
+
*
|
|
46
|
+
* // Use in registry mock or pass directly
|
|
47
|
+
* await fsRead.executor({ path: 'foo.ts' });
|
|
48
|
+
*
|
|
49
|
+
* expect(fsRead.wasCalled()).toBe(true);
|
|
50
|
+
* expect(fsRead.getLastCall()).toEqual({ path: 'foo.ts' });
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function mockTool(name: string, response: unknown = {}): MockToolInstance {
|
|
54
|
+
const calls: Record<string, unknown>[] = [];
|
|
55
|
+
let currentResponse = response;
|
|
56
|
+
|
|
57
|
+
const instance: MockToolInstance = {
|
|
58
|
+
definition: {
|
|
59
|
+
type: 'function' as const,
|
|
60
|
+
function: {
|
|
61
|
+
name,
|
|
62
|
+
description: `Mock tool: ${name}`,
|
|
63
|
+
parameters: {
|
|
64
|
+
type: 'object' as const,
|
|
65
|
+
properties: {},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
executor: async (input: Record<string, unknown>) => {
|
|
70
|
+
calls.push(input);
|
|
71
|
+
return currentResponse;
|
|
72
|
+
},
|
|
73
|
+
getCalls: () => calls,
|
|
74
|
+
getLastCall: () => calls[calls.length - 1],
|
|
75
|
+
wasCalled: () => calls.length > 0,
|
|
76
|
+
callCount: () => calls.length,
|
|
77
|
+
respondWith: (newResponse: unknown) => {
|
|
78
|
+
currentResponse = newResponse;
|
|
79
|
+
return instance;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return instance;
|
|
84
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup';
|
|
2
|
+
import nodePreset from '@kb-labs/devkit/tsup/node';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
...nodePreset,
|
|
6
|
+
entry: {
|
|
7
|
+
index: 'src/index.ts',
|
|
8
|
+
'testing/index': 'src/testing/index.ts',
|
|
9
|
+
},
|
|
10
|
+
tsconfig: 'tsconfig.build.json',
|
|
11
|
+
dts: {
|
|
12
|
+
resolve: true,
|
|
13
|
+
entry: {
|
|
14
|
+
index: 'src/index.ts',
|
|
15
|
+
'testing/index': 'src/testing/index.ts',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
external: [
|
|
19
|
+
/^@kb-labs\/.*/,
|
|
20
|
+
],
|
|
21
|
+
});
|