@kb-labs/scaffold 2.29.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/dist/commands/doctor.d.ts +15 -0
- package/dist/commands/doctor.js +63 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/scaffold.d.ts +18 -0
- package/dist/commands/scaffold.js +196 -0
- package/dist/commands/scaffold.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +114 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +75 -0
- package/dist/manifest.js +114 -0
- package/dist/manifest.js.map +1 -0
- package/package.json +55 -0
- package/templates/adapter/blocks/base/block.yaml +4 -0
- package/templates/adapter/blocks/base/files/README.md.eta +28 -0
- package/templates/adapter/blocks/base/files/package.json.eta +37 -0
- package/templates/adapter/blocks/base/files/src/manifest.ts.eta +24 -0
- package/templates/adapter/blocks/base/files/tsconfig.json +8 -0
- package/templates/adapter/blocks/base/files/tsup.config.ts +10 -0
- package/templates/adapter/blocks/base/files/vitest.config.ts +12 -0
- package/templates/adapter/blocks/provider-example/block.yaml +6 -0
- package/templates/adapter/blocks/provider-example/files/src/index.ts.eta +6 -0
- package/templates/adapter/blocks/provider-example/files/src/llm.ts.eta +46 -0
- package/templates/adapter/entity.yaml +37 -0
- package/templates/plugin/blocks/base/block.yaml +5 -0
- package/templates/plugin/blocks/base/files/README.md.eta +54 -0
- package/templates/plugin/blocks/base/files/package.json.eta +14 -0
- package/templates/plugin/blocks/base/files/packages/__name__-contracts/package.json.eta +29 -0
- package/templates/plugin/blocks/base/files/packages/__name__-contracts/src/index.ts.eta +14 -0
- package/templates/plugin/blocks/base/files/packages/__name__-contracts/tsconfig.json +8 -0
- package/templates/plugin/blocks/base/files/packages/__name__-contracts/tsup.config.ts +10 -0
- package/templates/plugin/blocks/base/files/packages/__name__-contracts/vitest.config.ts +12 -0
- package/templates/plugin/blocks/base/files/packages/__name__-core/package.json.eta +33 -0
- package/templates/plugin/blocks/base/files/packages/__name__-core/src/hello.ts.eta +59 -0
- package/templates/plugin/blocks/base/files/packages/__name__-core/src/index.ts.eta +1 -0
- package/templates/plugin/blocks/base/files/packages/__name__-core/tests/hello.test.ts.eta +16 -0
- package/templates/plugin/blocks/base/files/packages/__name__-core/tsconfig.json +8 -0
- package/templates/plugin/blocks/base/files/packages/__name__-core/tsup.config.ts +10 -0
- package/templates/plugin/blocks/base/files/packages/__name__-core/vitest.config.ts +12 -0
- package/templates/plugin/blocks/base/files/packages/__name__-entry/eslint.config.js +3 -0
- package/templates/plugin/blocks/base/files/packages/__name__-entry/package.json.eta +41 -0
- package/templates/plugin/blocks/base/files/packages/__name__-entry/src/commands/hello.ts.eta +39 -0
- package/templates/plugin/blocks/base/files/packages/__name__-entry/src/index.ts.eta +4 -0
- package/templates/plugin/blocks/base/files/packages/__name__-entry/tsconfig.json +8 -0
- package/templates/plugin/blocks/base/files/packages/__name__-entry/tsup.config.ts +10 -0
- package/templates/plugin/blocks/base/files/packages/__name__-entry/vitest.config.ts +12 -0
- package/templates/plugin/blocks/base/files/pnpm-workspace.yaml.eta +3 -0
- package/templates/plugin/blocks/base/files/tsconfig.base.json +3 -0
- package/templates/plugin/blocks/base/manifest.patch.yaml +28 -0
- package/templates/plugin/blocks/base/manifest.snippets.yaml +4 -0
- package/templates/plugin/blocks/cli/block.yaml +5 -0
- package/templates/plugin/blocks/cli/files/packages/__name__-entry/src/commands/ping.ts.eta +25 -0
- package/templates/plugin/blocks/cli/manifest.patch.yaml +14 -0
- package/templates/plugin/blocks/contracts/block.yaml +5 -0
- package/templates/plugin/blocks/contracts/files/packages/__name__-contracts/src/events.ts.eta +13 -0
- package/templates/plugin/blocks/rest/block.yaml +6 -0
- package/templates/plugin/blocks/rest/files/packages/__name__-entry/src/rest/hello.ts.eta +22 -0
- package/templates/plugin/blocks/rest/manifest.patch.yaml +9 -0
- package/templates/plugin/entity.yaml +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/manifest.ts"],"names":[],"mappings":"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","file":"manifest.js","sourcesContent":["import { combinePermissions, kbPlatformPreset } from '@kb-labs/sdk';\n\nconst permissions = combinePermissions()\n .with(kbPlatformPreset)\n .withFs({\n mode: 'readWrite',\n allow: [\n '.kb/plugins/**',\n '.kb/marketplace.lock',\n 'plugins/**',\n 'adapters/**',\n ],\n })\n .withShell({\n // Needed to call `kb marketplace plugins link` after scaffolding,\n // so the generated plugin lands in .kb/marketplace.lock automatically.\n allow: ['kb'],\n })\n .withQuotas({ timeoutMs: 120000, memoryMb: 256 })\n .build();\n\nconst manifest = {\n schema: 'kb.plugin/3',\n id: '@kb-labs/scaffold',\n version: '0.1.0',\n display: {\n name: 'Scaffold',\n description:\n 'Generic entity scaffolder for KB Labs plugins, adapters, and friends.',\n tags: ['scaffold', 'generator', 'dx'],\n },\n cli: {\n groupMeta: [\n { name: 'scaffold', describe: 'Scaffold KB Labs entities' },\n ],\n commands: [\n {\n id: 'run',\n group: 'scaffold',\n describe: 'Scaffold <entity> <name> from blocks',\n handler: './commands/scaffold.js#default',\n handlerPath: './commands/scaffold.js',\n flags: [\n {\n name: 'blocks',\n type: 'string',\n description: 'Comma-separated block ids',\n },\n {\n name: 'yes',\n alias: 'y',\n type: 'boolean',\n description: 'Accept defaults and skip prompts',\n },\n {\n name: 'force',\n type: 'boolean',\n description: 'Overwrite non-empty target directory',\n },\n {\n name: 'dry-run',\n type: 'boolean',\n description: 'Print the tree that would be written and exit',\n },\n {\n name: 'out',\n type: 'string',\n description: 'Override the output directory',\n },\n {\n name: 'scope',\n type: 'string',\n description: 'npm scope for the generated package',\n },\n {\n name: 'mode',\n type: 'string',\n description:\n 'Layout mode: \"in-workspace\" (workspace:* deps) or \"standalone\" (semver deps + pnpm-workspace.yaml)',\n },\n ],\n examples: [\n 'kb scaffold run plugin my-plugin',\n 'kb scaffold run adapter my-llm --blocks base',\n 'kb scaffold run plugin ui --scope @acme --yes',\n 'kb scaffold run plugin demo --dry-run',\n ],\n },\n {\n id: 'doctor',\n group: 'scaffold',\n describe: 'Scan user plugins for common issues',\n handler: './commands/doctor.js#default',\n handlerPath: './commands/doctor.js',\n flags: [\n {\n name: 'path',\n type: 'string',\n description: 'Path to scan (default: .kb/plugins)',\n },\n {\n name: 'json',\n type: 'boolean',\n description: 'Emit JSON instead of text',\n },\n ],\n examples: [\n 'kb scaffold doctor',\n 'kb scaffold doctor --path ./plugins',\n 'kb scaffold doctor --json',\n ],\n },\n ],\n },\n permissions,\n} as const;\n\nexport default manifest;\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kb-labs/scaffold",
|
|
3
|
+
"version": "2.29.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Generic entity scaffolder for KB Labs plugins, adapters, and friends.",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./plugin-manifest": {
|
|
14
|
+
"import": "./dist/manifest.js",
|
|
15
|
+
"types": "./dist/manifest.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"kb": {
|
|
19
|
+
"manifest": "./dist/manifest.js"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"templates"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@clack/prompts": "^0.11.0",
|
|
28
|
+
"@kb-labs/scaffold-contracts": "2.29.0",
|
|
29
|
+
"@kb-labs/scaffold-core": "2.29.0",
|
|
30
|
+
"@kb-labs/sdk": "2.18.1"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^24.3.3",
|
|
34
|
+
"eslint": "^9",
|
|
35
|
+
"rimraf": "^6.0.1",
|
|
36
|
+
"tsup": "^8.5.0",
|
|
37
|
+
"typescript": "^5.6.3",
|
|
38
|
+
"vitest": "^3.2.4",
|
|
39
|
+
"@kb-labs/devkit": "2.29.0",
|
|
40
|
+
"@kb-labs/plugin-contracts": "2.29.0"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20.0.0",
|
|
44
|
+
"pnpm": ">=9.0.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"clean": "rimraf dist",
|
|
48
|
+
"build": "tsup",
|
|
49
|
+
"dev": "tsup --watch",
|
|
50
|
+
"type-check": "tsc --noEmit",
|
|
51
|
+
"test": "vitest run --passWithNoTests",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"lint": "eslint src --ext .ts"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# <%= it.scope ? it.scope + '/' : '' %><%= it.name %>
|
|
2
|
+
|
|
3
|
+
<%= it.vars.description %>
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
src/
|
|
9
|
+
index.ts # createAdapter factory — instantiated by the host
|
|
10
|
+
manifest.ts # AdapterManifest (id, type, what this adapter implements)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
All imports come from `@kb-labs/sdk/adapters`. **Never** reach into
|
|
14
|
+
`@kb-labs/core-platform` directly — that's internal and will break on
|
|
15
|
+
core majors. If you need something not re-exported by SDK, open an issue
|
|
16
|
+
on `@kb-labs/sdk` rather than working around it.
|
|
17
|
+
|
|
18
|
+
## Using it
|
|
19
|
+
|
|
20
|
+
Register the adapter in your project's `.kb/kb.config.jsonc` (the host
|
|
21
|
+
plugin will resolve this package via npm or `workspace:*`). Then the
|
|
22
|
+
runtime wires it up to whichever capability it `implements`.
|
|
23
|
+
|
|
24
|
+
## Health check
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm kb scaffold doctor --path .
|
|
28
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= it.scope ? it.scope + '/' : '' %><%= it.name %>",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "<%= it.vars.description %>",
|
|
6
|
+
"license": "<%= it.vars.license %>",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./manifest": {
|
|
15
|
+
"import": "./dist/manifest.js",
|
|
16
|
+
"types": "./dist/manifest.d.ts"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": ["dist"],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"scripts": {
|
|
22
|
+
"clean": "rimraf dist",
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"type-check": "tsc --noEmit",
|
|
25
|
+
"test": "vitest run --passWithNoTests"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@kb-labs/sdk": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^' + it.versions.sdk %>"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@kb-labs/devkit": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^' + it.versions.devkit %>",
|
|
32
|
+
"rimraf": "^6.0.1",
|
|
33
|
+
"tsup": "^8.5.0",
|
|
34
|
+
"typescript": "^5.6.3",
|
|
35
|
+
"vitest": "^3.2.4"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineAdapterManifest } from '@kb-labs/sdk/adapters';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AdapterManifest for <%= it.name %>.
|
|
5
|
+
*
|
|
6
|
+
* `implements` names the capability interface this adapter provides
|
|
7
|
+
* (e.g. "ILLM", "ILogger", "ICache"). The host resolves adapters by this
|
|
8
|
+
* string at bind time.
|
|
9
|
+
*
|
|
10
|
+
* Types:
|
|
11
|
+
* - "core" — shipped with the platform, always available
|
|
12
|
+
* - "extension" — third-party or in-project, opt-in via config
|
|
13
|
+
* - "proxy" — forwards calls to a remote runtime
|
|
14
|
+
*/
|
|
15
|
+
export const manifest = defineAdapterManifest({
|
|
16
|
+
manifestVersion: '1.0.0',
|
|
17
|
+
id: '<%= it.name %>',
|
|
18
|
+
name: '<%= it.name %>',
|
|
19
|
+
version: '0.1.0',
|
|
20
|
+
type: 'extension',
|
|
21
|
+
implements: 'ILLM',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export default manifest;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup';
|
|
2
|
+
import nodePreset from '@kb-labs/devkit/tsup/node';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
...nodePreset,
|
|
6
|
+
entry: ['src/index.ts', 'src/manifest.ts'],
|
|
7
|
+
dts: { resolve: true, skipLibCheck: true },
|
|
8
|
+
clean: true,
|
|
9
|
+
sourcemap: true,
|
|
10
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
import baseConfig from '@kb-labs/devkit/vitest/node';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
...baseConfig,
|
|
6
|
+
test: {
|
|
7
|
+
...baseConfig.test,
|
|
8
|
+
globals: true,
|
|
9
|
+
include: ['tests/**/*.test.ts', 'src/**/*.test.ts'],
|
|
10
|
+
environment: 'node',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ILLM,
|
|
3
|
+
LLMOptions,
|
|
4
|
+
LLMResponse,
|
|
5
|
+
IDisposable,
|
|
6
|
+
} from '@kb-labs/sdk/adapters';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Minimal ILLM implementation.
|
|
10
|
+
*
|
|
11
|
+
* Replace the `complete` body with a real API call (OpenAI, Anthropic,
|
|
12
|
+
* local llama.cpp, whatever). `dispose` is called by the host on shutdown
|
|
13
|
+
* — use it to close connection pools, flush buffers, etc.
|
|
14
|
+
*
|
|
15
|
+
* Cookbook:
|
|
16
|
+
* - Use `useLogger(ctx)` / `useCache(ctx)` from '@kb-labs/sdk' inside
|
|
17
|
+
* the host, not here. Adapters should stay capability-focused.
|
|
18
|
+
* - Declare streaming / batch support via AdapterCapabilities in the
|
|
19
|
+
* manifest so the router can pick the right adapter for a request.
|
|
20
|
+
*/
|
|
21
|
+
export class <%= it.name.replace(/(^|-)(\w)/g, (_, _s, c) => c.toUpperCase()) %>LLM implements ILLM, IDisposable {
|
|
22
|
+
constructor(private readonly config: { apiKey?: string } = {}) {}
|
|
23
|
+
|
|
24
|
+
async complete(options: LLMOptions): Promise<LLMResponse> {
|
|
25
|
+
// TODO: call your provider here.
|
|
26
|
+
return {
|
|
27
|
+
text: `(stub) <%= it.name %> would answer: ${options.prompt}`,
|
|
28
|
+
model: 'stub',
|
|
29
|
+
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async dispose(): Promise<void> {
|
|
34
|
+
// TODO: tear down connections / flush buffers.
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface <%= it.name.replace(/(^|-)(\w)/g, (_, _s, c) => c.toUpperCase()) %>Config {
|
|
39
|
+
apiKey?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function createAdapter(
|
|
43
|
+
config: <%= it.name.replace(/(^|-)(\w)/g, (_, _s, c) => c.toUpperCase()) %>Config = {},
|
|
44
|
+
): ILLM {
|
|
45
|
+
return new <%= it.name.replace(/(^|-)(\w)/g, (_, _s, c) => c.toUpperCase()) %>LLM(config);
|
|
46
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
id: adapter
|
|
2
|
+
displayName: KB Labs Adapter
|
|
3
|
+
description: |
|
|
4
|
+
A KB Labs adapter: implements a replaceable platform capability (LLM,
|
|
5
|
+
logger, cache, storage, etc). Single package, everything imported
|
|
6
|
+
through @kb-labs/sdk/adapters — never from @kb-labs/core-platform.
|
|
7
|
+
|
|
8
|
+
output: adapters/<%= it.name %>
|
|
9
|
+
|
|
10
|
+
variables:
|
|
11
|
+
- name: scope
|
|
12
|
+
type: string
|
|
13
|
+
describe: npm scope (e.g. @kb-labs, @acme). Leave blank for unscoped.
|
|
14
|
+
default: "@kb-labs"
|
|
15
|
+
validate: npmScope
|
|
16
|
+
- name: description
|
|
17
|
+
type: string
|
|
18
|
+
describe: Short description of the adapter
|
|
19
|
+
default: A KB Labs adapter
|
|
20
|
+
- name: license
|
|
21
|
+
type: string
|
|
22
|
+
describe: License identifier
|
|
23
|
+
default: MIT
|
|
24
|
+
- name: mode
|
|
25
|
+
type: select
|
|
26
|
+
describe: Where will this adapter live?
|
|
27
|
+
default: in-workspace
|
|
28
|
+
choices:
|
|
29
|
+
- value: in-workspace
|
|
30
|
+
label: Inside a KB Labs workspace (workspace:* deps)
|
|
31
|
+
- value: standalone
|
|
32
|
+
label: Standalone repo (semver-pinned deps)
|
|
33
|
+
|
|
34
|
+
defaults:
|
|
35
|
+
blocks:
|
|
36
|
+
- base
|
|
37
|
+
- provider-example
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# <%= it.scope ? it.scope + '/' : '' %><%= it.name %>
|
|
2
|
+
|
|
3
|
+
<%= it.vars.description %>
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
packages/
|
|
9
|
+
<%= it.name %>-contracts/ # public types (request/response shapes)
|
|
10
|
+
<%= it.name %>-core/ # pure business logic (testable in isolation)
|
|
11
|
+
<%= it.name %>-entry/ # V3 manifest + CLI command handlers
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
All three packages are published together. `entry` depends on `core`, `core`
|
|
15
|
+
depends on `contracts`. The runtime discovers the plugin through the `"kb"`
|
|
16
|
+
field in `<%= it.name %>-entry/package.json`.
|
|
17
|
+
|
|
18
|
+
## Getting started
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm install
|
|
22
|
+
pnpm -w build
|
|
23
|
+
pnpm kb <%= it.name %> hello # say hi
|
|
24
|
+
pnpm kb <%= it.name %> hello --who=World # same, explicit
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## What to edit
|
|
28
|
+
|
|
29
|
+
- **Business logic:** [packages/<%= it.name %>-core/src/hello.ts](./packages/<%= it.name %>-core/src/hello.ts)
|
|
30
|
+
Inline comments show how to call the LLM, use the cache, and log through
|
|
31
|
+
the platform — everything goes through `@kb-labs/sdk`, never through
|
|
32
|
+
`@kb-labs/core-*` or `@kb-labs/platform-*`.
|
|
33
|
+
- **CLI surface:** [packages/<%= it.name %>-entry/src/manifest.ts](./packages/<%= it.name %>-entry/src/manifest.ts)
|
|
34
|
+
Add more commands by appending to `cli.commands[]` and creating a handler
|
|
35
|
+
in `src/commands/`.
|
|
36
|
+
- **Shared types:** [packages/<%= it.name %>-contracts/src/index.ts](./packages/<%= it.name %>-contracts/src/index.ts)
|
|
37
|
+
Input/output shapes go here so `core` and `entry` agree on them.
|
|
38
|
+
|
|
39
|
+
## Linking into a workspace (development)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pnpm kb marketplace plugins link .
|
|
43
|
+
pnpm kb plugins clear-cache
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Health check
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pnpm kb scaffold doctor --path .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
<%= it.vars.license %>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= it.scope ? it.scope + '/' : '' %><%= it.name %>",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "<%= it.vars.description %>",
|
|
6
|
+
"license": "<%= it.vars.license %>",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "pnpm -r build",
|
|
10
|
+
"clean": "pnpm -r clean",
|
|
11
|
+
"type-check": "pnpm -r type-check",
|
|
12
|
+
"test": "pnpm -r test"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= it.scope ? it.scope + '/' : '' %><%= it.name %>-contracts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Public types for <%= it.name %>",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": ["dist"],
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"scripts": {
|
|
17
|
+
"clean": "rimraf dist",
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"type-check": "tsc --noEmit",
|
|
20
|
+
"test": "vitest run --passWithNoTests"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@kb-labs/devkit": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^' + it.versions.devkit %>",
|
|
24
|
+
"rimraf": "^6.0.1",
|
|
25
|
+
"tsup": "^8.5.0",
|
|
26
|
+
"typescript": "^5.6.3",
|
|
27
|
+
"vitest": "^3.2.4"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public contracts for <%= it.name %>.
|
|
3
|
+
*
|
|
4
|
+
* Keep this package tiny — it is the stable boundary between `-core` and
|
|
5
|
+
* `-entry`. If a type is only used inside one package, it does not belong here.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface HelloInput {
|
|
9
|
+
who: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface HelloResult {
|
|
13
|
+
greeting: string;
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
import baseConfig from '@kb-labs/devkit/vitest/node';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
...baseConfig,
|
|
6
|
+
test: {
|
|
7
|
+
...baseConfig.test,
|
|
8
|
+
globals: true,
|
|
9
|
+
include: ['tests/**/*.test.ts', 'src/**/*.test.ts'],
|
|
10
|
+
environment: 'node',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= it.scope ? it.scope + '/' : '' %><%= it.name %>-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Business logic for <%= it.name %> (pure, testable in isolation).",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": ["dist"],
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"scripts": {
|
|
17
|
+
"clean": "rimraf dist",
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"type-check": "tsc --noEmit",
|
|
20
|
+
"test": "vitest run --passWithNoTests"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"<%= it.scope ? it.scope + '/' : '' %><%= it.name %>-contracts": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^0.1.0' %>",
|
|
24
|
+
"@kb-labs/sdk": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^' + it.versions.sdk %>"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@kb-labs/devkit": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^' + it.versions.devkit %>",
|
|
28
|
+
"rimraf": "^6.0.1",
|
|
29
|
+
"tsup": "^8.5.0",
|
|
30
|
+
"typescript": "^5.6.3",
|
|
31
|
+
"vitest": "^3.2.4"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { HelloInput, HelloResult } from '<%= it.scope ? it.scope + '/' : '' %><%= it.name %>-contracts';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Business logic for the `hello` command.
|
|
5
|
+
*
|
|
6
|
+
* This is a pure function so it can be unit-tested without any platform
|
|
7
|
+
* scaffolding. The handler in `-entry` is responsible for wiring platform
|
|
8
|
+
* services (logger, cache, LLM) and passing the results in — keep this
|
|
9
|
+
* function free of side effects.
|
|
10
|
+
*/
|
|
11
|
+
export function hello(input: HelloInput): HelloResult {
|
|
12
|
+
const who = input.who?.trim() || 'World';
|
|
13
|
+
return { greeting: `Hello, ${who} from <%= it.name %>!` };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* ───────────────────────────────────────────────────────────────────────────
|
|
18
|
+
* Cookbook: reach for these patterns when you grow past "hello".
|
|
19
|
+
* Everything flows through `@kb-labs/sdk` — DO NOT import from
|
|
20
|
+
* `@kb-labs/core-*` or `@kb-labs/platform-*` directly.
|
|
21
|
+
* ───────────────────────────────────────────────────────────────────────────
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// ── 1. Call an LLM ─────────────────────────────────────────────────────────
|
|
25
|
+
//
|
|
26
|
+
// import { useLLM, type PluginContextV3 } from '@kb-labs/sdk';
|
|
27
|
+
//
|
|
28
|
+
// export async function greetWithLLM(ctx: PluginContextV3, who: string) {
|
|
29
|
+
// const llm = await useLLM(ctx); // throws if no LLM adapter bound
|
|
30
|
+
// const res = await llm.complete({
|
|
31
|
+
// prompt: `Write a one-line greeting for ${who}.`,
|
|
32
|
+
// maxTokens: 40,
|
|
33
|
+
// });
|
|
34
|
+
// return res.text;
|
|
35
|
+
// }
|
|
36
|
+
|
|
37
|
+
// ── 2. Cache the result ────────────────────────────────────────────────────
|
|
38
|
+
//
|
|
39
|
+
// import { useCache, type PluginContextV3 } from '@kb-labs/sdk';
|
|
40
|
+
//
|
|
41
|
+
// export async function cachedGreeting(ctx: PluginContextV3, who: string) {
|
|
42
|
+
// const cache = await useCache(ctx); // namespaced per plugin
|
|
43
|
+
// const key = `greeting:${who}`;
|
|
44
|
+
// const hit = await cache.get<string>(key);
|
|
45
|
+
// if (hit) return hit;
|
|
46
|
+
//
|
|
47
|
+
// const greeting = `Hello, ${who}!`;
|
|
48
|
+
// await cache.set(key, greeting, { ttlMs: 60_000 });
|
|
49
|
+
// return greeting;
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
// ── 3. Structured logging ──────────────────────────────────────────────────
|
|
53
|
+
//
|
|
54
|
+
// import { useLogger, type PluginContextV3 } from '@kb-labs/sdk';
|
|
55
|
+
//
|
|
56
|
+
// export function logGreeting(ctx: PluginContextV3, who: string) {
|
|
57
|
+
// const log = useLogger(ctx);
|
|
58
|
+
// log.info({ who }, 'computed greeting');
|
|
59
|
+
// }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { hello } from './hello.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { hello } from '../src/hello.js';
|
|
3
|
+
|
|
4
|
+
describe('hello', () => {
|
|
5
|
+
it('greets a named person', () => {
|
|
6
|
+
expect(hello({ who: 'Kirill' })).toEqual({
|
|
7
|
+
greeting: 'Hello, Kirill from <%= it.name %>!',
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('falls back to World when empty', () => {
|
|
12
|
+
expect(hello({ who: '' })).toEqual({
|
|
13
|
+
greeting: 'Hello, World from <%= it.name %>!',
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
import baseConfig from '@kb-labs/devkit/vitest/node';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
...baseConfig,
|
|
6
|
+
test: {
|
|
7
|
+
...baseConfig.test,
|
|
8
|
+
globals: true,
|
|
9
|
+
include: ['tests/**/*.test.ts', 'src/**/*.test.ts'],
|
|
10
|
+
environment: 'node',
|
|
11
|
+
},
|
|
12
|
+
});
|