装饰器:处理类与已有实例方法
类装饰代办定义实例化,方法装饰绑定原对象;输出仍走原 define、构造和 bind。
仅从 @jangts/agent-core/support/decorators 使用标准装饰器;NestJS 旧版 experimentalDecorators 编译单元不能直接接入。无新增依赖、反射或自动 DI。
id 来自装饰器,类提供其余配置、处理方法与 this._xxx 内部协作。定义类可无参构造,静态初始化后只构造一次;Node、Tool、Fragment、Workflow、Agent、Model 提供具名类合同。
每类各一个共享读取池,不创建池、不手动登记。装饰器 ns 接受字符串或字符串数组,默认 default。同类型同命名空间内 id 唯一;不同空间可同名。多个空间共享同一对象,冲突先全部预检。get(id, ns?) 缺失返回 undefined,getAll(ns?) 返回该空间登记顺序快照,pick(ids, ns?) 按指定顺序选取并拒绝重复或缺失 id。
方法装饰自动绑定并在实例初始化钩子中登记,调用方等待宿主构造成功后才读取运行。构造失败不回滚已完成登记,应视为装配失败;共享池不保存请求级宿主,同命名空间同 id 的第二个实例拒绝。没有 registerFrom、手写 bind 或额外类装饰器。
node 映射 run,tool 映射 execute,fragment 映射 format,均回到原接口与校验。agent/model 只定义配置,不创建 Engine/Runner。ns 不传给 Core,也不改变 id;合并命名空间中的同名定义仍受原图与工具清单唯一性约束。同一 realm 内 ESM/CJS 共享读取池,独立进程与 Worker 不共享;池不是执行或授权。
由简到繁的同业务示例
类拥有配置与私有辅助方法,不手写 new
入门 · TypeScript 标准装饰器
import { AgentCoreEngine, defineWorkflow } from '@jangts/agent-core';
import type { WorkflowNode } from '@jangts/agent-core';
import { node, nodePool } from '@jangts/agent-core/support/decorators';
import type { Node } from '@jangts/agent-core/support/decorators';
type State = { text: string; answer?: string };
@node<State, string>('greet', { ns: 'greeting' })
class Greeting implements Node<State, string> {
readonly description = '生成问候';
readonly routes = [{ complete: (state: Readonly<State>) => state.answer! }];
#prefix = '你好,';
run(state: Readonly<State>) { return { answer: this._format(state.text) }; }
private _format(text: string) { return this.#prefix + text.trim(); }
}
const flow = defineWorkflow<State, string>({ id: 'greeting', nodes: nodePool.getAll('greeting') });
console.log(await new AgentCoreEngine({ workflow: flow }).run({ text: '访客' }));var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { AgentCoreEngine, defineWorkflow } from '@jangts/agent-core';
import { node, nodePool } from '@jangts/agent-core/support/decorators';
let Greeting = class Greeting {
description = '生成问候';
routes = [{ complete: (state) => state.answer }];
#prefix = '你好,';
run(state) { return { answer: this._format(state.text) }; }
_format(text) { return this.#prefix + text.trim(); }
};
Greeting = __decorate([
node('greet', { ns: 'greeting' })
], Greeting);
const flow = defineWorkflow({ id: 'greeting', nodes: nodePool.getAll('greeting') });
console.log(await new AgentCoreEngine({ workflow: flow }).run({ text: '访客' }));保留服务方法名,自动绑定原对象
配置 · TypeScript 标准装饰器
import type { WorkflowNode } from '@jangts/agent-core';
import { node, nodePool } from '@jangts/agent-core/support/decorators';
type State = { text: string; answer?: string };
class GreetingService {
constructor(private readonly prefix: string) {}
@node<State, string>('reply', { ns: 'service',
description: '调用现有服务',
routes: [{ complete: (state: Readonly<State>) => state.answer! }],
})
answer(state: Readonly<State>) { return { answer: this.prefix + state.text }; }
}
const service = new GreetingService('你好,');
const definition = nodePool.get<WorkflowNode<State, string>>('reply', 'service')!;
console.log(definition === nodePool.get('reply', 'service'));var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { node, nodePool } from '@jangts/agent-core/support/decorators';
class GreetingService {
prefix;
constructor(prefix) {
this.prefix = prefix;
}
answer(state) { return { answer: this.prefix + state.text }; }
}
__decorate([
node('reply', { ns: 'service',
description: '调用现有服务',
routes: [{ complete: (state) => state.answer }],
})
], GreetingService.prototype, "answer", null);
const service = new GreetingService('你好,');
const definition = nodePool.get('reply', 'service');
console.log(definition === nodePool.get('reply', 'service'));工具类继续使用原授权与结果检查
扩展 · TypeScript 标准装饰器
import { Support } from '@jangts/agent-core';
import type { ToolDefinition } from '@jangts/agent-core';
import { tool, toolPool } from '@jangts/agent-core/support/decorators';
import type { Tool } from '@jangts/agent-core/support/decorators';
type Input = { text: string };
@tool<Input, string, undefined>('echo', { ns: 'echo' })
class Echo implements Tool<Input, string, undefined> {
readonly kind = 'read';
readonly description = '回显文本';
readonly inputSchema = {
jsonSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
parse(value: unknown): Input {
if (!value || typeof value !== 'object' || !('text' in value) || typeof value.text !== 'string') throw new TypeError('text');
return { text: value.text };
},
};
authorize(): void {}
execute(input: Input) { return this._format(input.text); }
private _format(text: string) { return text.trim(); }
parseOutput(value: unknown): string {
if (typeof value !== 'string') throw new TypeError('string');
return value;
}
}
const runtime = Support.defineToolCatalog<undefined>(toolPool.getAll<ToolDefinition<Input, string, undefined>>('echo')).bind({ app: undefined });
console.log((await runtime.invoke({ toolId: 'echo', input: { text: 'hello' } })).value);var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { Support } from '@jangts/agent-core';
import { tool, toolPool } from '@jangts/agent-core/support/decorators';
let Echo = class Echo {
kind = 'read';
description = '回显文本';
inputSchema = {
jsonSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
parse(value) {
if (!value || typeof value !== 'object' || !('text' in value) || typeof value.text !== 'string')
throw new TypeError('text');
return { text: value.text };
},
};
authorize() { }
execute(input) { return this._format(input.text); }
_format(text) { return text.trim(); }
parseOutput(value) {
if (typeof value !== 'string')
throw new TypeError('string');
return value;
}
};
Echo = __decorate([
tool('echo', { ns: 'echo' })
], Echo);
const runtime = Support.defineToolCatalog(toolPool.getAll('echo')).bind({ app: undefined });
console.log((await runtime.invoke({ toolId: 'echo', input: { text: 'hello' } })).value);资料、工作流与运行配置仍回到原入口
扩展 · TypeScript 标准装饰器
import { AgentCoreEngine, ModelRunner, Support, defineWorkflow } from '@jangts/agent-core';
import type { AgentWorkflowDefinition, ContextFragmentConfig } from '@jangts/agent-core/types';
import { fragment, workflow, agent, model, fragmentPool, workflowPool, agentPool, modelPool } from '@jangts/agent-core/support/decorators';
import type { AgentOptions, ModelOptions } from '@jangts/agent-core/support/decorators';
@fragment<string>('subject')
class Subject {
readonly sourceId = 'app'; readonly trust = 'server' as const;
readonly lifetime = 'turn' as const; readonly role = 'user' as const; readonly maxChars = 100;
format(text: string) { return text; }
}
const builder = Support.defineContextFragments([fragmentPool.get<ContextFragmentConfig<string>>('subject')!]);
console.log(builder.fragments('hello'));
@workflow<{ answer: string }, string>('flow')
class Flow {
readonly nodes = [{ id: 'done', description: '交付', routes: [{ complete: (s: {answer: string}) => s.answer }] }];
}
const flow = defineWorkflow(workflowPool.get<AgentWorkflowDefinition<{answer:string},string>>('flow')!);
@agent<{answer:string}, string>('configured')
class Configured { readonly workflow = flow; }
console.log(await new AgentCoreEngine<string,{answer:string}>(agentPool.get<AgentOptions<{answer:string},string>>('configured')!).run({answer:'hello'}));
@model('text-model')
class TextModel { readonly provider = { async *stream() { yield 'hello'; } }; readonly maxCalls = 1; }
const runner = new ModelRunner(modelPool.get<ModelOptions>('text-model')!);
console.log((await runner.invoke({input:'hello'})).value);var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { AgentCoreEngine, ModelRunner, Support, defineWorkflow } from '@jangts/agent-core';
import { fragment, workflow, agent, model, fragmentPool, workflowPool, agentPool, modelPool } from '@jangts/agent-core/support/decorators';
let Subject = class Subject {
sourceId = 'app';
trust = 'server';
lifetime = 'turn';
role = 'user';
maxChars = 100;
format(text) { return text; }
};
Subject = __decorate([
fragment('subject')
], Subject);
const builder = Support.defineContextFragments([fragmentPool.get('subject')]);
console.log(builder.fragments('hello'));
let Flow = class Flow {
nodes = [{ id: 'done', description: '交付', routes: [{ complete: (s) => s.answer }] }];
};
Flow = __decorate([
workflow('flow')
], Flow);
const flow = defineWorkflow(workflowPool.get('flow'));
let Configured = class Configured {
workflow = flow;
};
Configured = __decorate([
agent('configured')
], Configured);
console.log(await new AgentCoreEngine(agentPool.get('configured')).run({ answer: 'hello' }));
let TextModel = class TextModel {
provider = { async *stream() { yield 'hello'; } };
maxCalls = 1;
};
TextModel = __decorate([
model('text-model')
], TextModel);
const runner = new ModelRunner(modelPool.get('text-model'));
console.log((await runner.invoke({ input: 'hello' })).value);