@jangts/agent-core 0.2.5 → 0.3.5

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.
@@ -0,0 +1,108 @@
1
+ # 装饰器与定义池
2
+
3
+ 装饰器与读取池从 `@jangts/agent-core/support/decorators` 导入,仅支持 TypeScript 标准装饰器语义。启用了 experimentalDecorators 的 NestJS 编译单元不能直接使用。普通对象、define、构造与 bind 入口保持可用。无新增运行时依赖,不使用 reflect-metadata 或自动 DI。
4
+
5
+ 类装饰器代办定义实例化与 id 注入;实例方法装饰器将原方法绑定为 handler,保留原对象及 this。产物仍是原合同的定义或配置,不创建 Engine/ModelRunner,不改变预算、取消、授权、状态提交与工具回执。
6
+
7
+ ## 类:处理单元与内部协作
8
+
9
+ 从同一子路径导入 Node、Tool、Fragment、Workflow、Agent、Model 类型,描述类应提供的原字段与方法;id 由装饰器补齐,无需重复写 Omit。Agent 保留原配置的联合类型分支,由装饰器检查,不要求 class implements 联合类型。
10
+
11
+ ```ts
12
+ import { AgentCoreEngine, defineWorkflow } from '@jangts/agent-core';
13
+ import { node, nodePool } from '@jangts/agent-core/support/decorators';
14
+ import type { Node } from '@jangts/agent-core/support/decorators';
15
+
16
+ type State = { text: string; answer?: string };
17
+
18
+ @node<State, string>('greet', { ns: 'chat' })
19
+ class Greeting implements Node<State, string> {
20
+ readonly description = '问候';
21
+ readonly routes = [{ complete: (state: Readonly<State>) => state.answer! }];
22
+ #prefix = '你好,';
23
+ run(state: Readonly<State>) {
24
+ return { answer: this._format(state.text) };
25
+ }
26
+ private _format(text: string) { return this.#prefix + text.trim(); }
27
+ }
28
+
29
+ const workflow = defineWorkflow<State, string>({
30
+ id: 'greeting', nodes: nodePool.getAll('chat'),
31
+ });
32
+ console.log(await new AgentCoreEngine({ workflow }).run({ text: '访客' }));
33
+ ```
34
+
35
+ id 只来自装饰器;类中重复声明 id 会拒绝。定义类必须可无参构造,在静态初始化完成后构造一次;池读取不再构造。配置字段、handler 及内部方法由类提供,不在装饰器中重复 metadata。私有字段、getter 和原型方法保留真实接收者。构造函数只初始化定义,不执行业务操作。
36
+
37
+ ## 命名空间与读取
38
+
39
+ 每种定义各有一个共享读取池:nodePool、toolPool、fragmentPool、workflowPool、agentPool、modelPool。调用方无需创建池或手动登记。所有装饰器接受可选的 `{ ns: string | readonly string[] }`,缺省为 `'default'`。
40
+
41
+ ```ts
42
+ nodePool.get('greet', 'chat'); // 单个定义,缺失为 undefined
43
+ nodePool.getAll('chat'); // 此命名空间全部定义
44
+ nodePool.pick(['greet', 'answer'], 'chat'); // 按指定顺序选取,缺失或重复 id 抛错
45
+ nodePool.get('greet'); // 等价于 get('greet', 'default')
46
+ nodePool.getAll(); // 只读 default,不跨命名空间合并
47
+ nodePool.pick(['greet']); // 在 default 中选取
48
+ ```
49
+
50
+ 同一类型、同一命名空间内 id 唯一;不同命名空间或不同类型可同名。ns 精确匹配,不支持层级、通配或隐式回退,空白名称与空数组拒绝。数组中的重复命名空间去重。`ns: ['chat', 'assistant']` 将同一已构造定义登记到两个空间,不重复构造、不复制实例;任一目标重名则整次登记拒绝,不留下部分写入。
51
+
52
+ getAll 返回登记顺序的只读数组快照;未知命名空间返回空数组。pick 返回入参顺序的只读数组快照,空 id 数组返回空数组。读取方法可使用原定义类型泛型,如 `nodePool.get<WorkflowNode<State, string>>('greet', 'chat')`;泛型描述调用方预期合同,不是运行时类型证明。
53
+
54
+ ns 仅用于辅助登记,不进入 Core options;取出的 id 仍为原 id。把不同命名空间的同名定义装入同一 Workflow/ToolRegistry 时,原入口仍拒绝重名。Workflow 节点顺序与路由由 App 明确组织,不把模块导入顺序当成业务执行顺序。池不公开创建、写入、清空或封存接口,不支持 tags 或 owner 查询。
55
+
56
+ ## 已有实例:保留业务方法名
57
+
58
+ ```ts
59
+ class GreetingService {
60
+ constructor(private readonly prefix: string) {}
61
+ @node<State, string>('reply', {
62
+ ns: 'chat-service',
63
+ description: '调用已有服务',
64
+ routes: [{ complete: (state: Readonly<State>) => state.answer! }],
65
+ })
66
+ answer(state: Readonly<State>) {
67
+ return { answer: this._format(state.text) };
68
+ }
69
+ private _format(text: string) { return this.prefix + text; }
70
+ }
71
+ const service = new GreetingService('你好,'); // 创建原宿主,自动绑定与登记
72
+ const definition = nodePool.get('reply', 'chat-service');
73
+ ```
74
+
75
+ 方法装饰器用标准实例初始化钩子绑定并登记,不需要 registerFrom、手写 bind 或额外类装饰器。该钩子先于实例字段与构造函数体运行,因此只绑定、不执行 handler,不访问未初始化的业务字段。调用方必须等待宿主构造成功后再读取并运行定义;构造失败不回滚已完成的初始化登记,应视为装配失败。池持有真实宿主的绑定引用,适用于长期存活的定义/服务实例,不是请求级实例工厂。同命名空间同 id 的第二个实例拒绝登记,不覆盖第一个绑定。
76
+
77
+ metadata 中的直接回调同样绑定到宿主;嵌套 schema 与 routes 保留原合同接收者,箭头函数保留词法 this。仅支持公开实例方法,不支持静态/私有方法、普通顶层函数的 @ 语法或隐式继承合并。
78
+
79
+ ## getter 与按状态选路
80
+
81
+ ```ts
82
+ get routes(): Node<State, string>['routes'] {
83
+ return [
84
+ { when: state => this._hasAnswer(state), complete: state => state.answer! },
85
+ { complete: () => '没有可交付的回答' },
86
+ ];
87
+ }
88
+ private _hasAnswer(state: Readonly<State>) {
89
+ return Boolean(state.answer?.trim());
90
+ }
91
+ ```
92
+
93
+ Workflow 装配时读取并固定路由表;getter 应无副作用,不依赖调用次数,也不读取本次请求状态。每次 run 提交补丁后,when/complete 获得最新 state,并可调用原类辅助方法。getter 不会每轮重建路由;不要把请求 state 存在共享节点 this 上。
94
+
95
+ ## 定义类型与原入口
96
+
97
+ | 装饰器 | 类的结构 | 方法适配 | 读取池 | 后续入口 |
98
+ | --- | --- | --- | --- | --- |
99
+ | node | Node<State, Result, App> | run | nodePool | defineWorkflow |
100
+ | tool | Tool<Input, Output, App> | execute | toolPool | defineTool/defineToolCatalog |
101
+ | fragment | Fragment<Input> | format | fragmentPool | defineContextFragments |
102
+ | workflow | Workflow<State, Result, App> | 不提供 | workflowPool | defineWorkflow |
103
+ | agent | Agent<State, Result, App> | 不提供 | agentPool | App 创建 Engine |
104
+ | model | Model | 不提供 | modelPool | App 创建 ModelRunner |
105
+
106
+ agent/model 的 id 是辅助登记键,不覆盖 Core 分支、模型或 transport 身份。工具复用原 defineTool 校验;Workflow 复用原图校验,节点在完整图中验证;fragment 复用原 builder 的 formatter 检查,数据、信任与预算保持原合同;model 复用原配置快照验证,不消耗模型调用。辅助层不公开 metadata+普通函数转换入口,顶层函数直接填入原 options。
107
+
108
+ 同一 JavaScript realm 内 ESM/CJS 副本共享池;不同进程、Worker 或独立 realm 不共享。两次独立加载并装饰同命名空间同 id 的类仍会重名拒绝,不自动合并。定义模块必须被打包图明确保留;被 tree-shaking 删除的纯副作用导入不能保证登记。共享定义不能保存请求身份、signal 或请求预算;池读取不是执行或授权。
@@ -2266,3 +2266,35 @@
2266
2266
  | `sources` | value | [声明](../../../dist/esm/mock/web.d.ts#L8) |
2267
2267
  | `WebOptions` | type | [声明](../../../dist/esm/mock/web.d.ts#L8) |
2268
2268
  | `WebProfile` | type | [声明](../../../dist/esm/mock/web.d.ts#L8) |
2269
+
2270
+ ## @jangts/agent-core/support/decorators
2271
+
2272
+ [合同与行为](support.md) · 25 个导出符号
2273
+
2274
+ | 符号 | 类型/值 | 声明与说明 |
2275
+ | --- | --- | --- |
2276
+ | `agent` | value | [声明](../../../dist/esm/support/decorators/index.d.ts#L35) |
2277
+ | `Agent` | type | [声明](../../../dist/esm/support/decorators/types.d.ts#L20) |
2278
+ | `AgentOptions` | type | [声明](../../../dist/esm/support/decorators/index.d.ts#L33) |
2279
+ | `agentPool` | value | [声明](../../../dist/esm/support/decorators/pool.d.ts#L28) |
2280
+ | `ClassDecoration` | type | [声明](../../../dist/esm/support/decorators/definition.d.ts#L13) |
2281
+ | `DecorationOptions` | type | [声明](../../../dist/esm/support/decorators/definition.d.ts#L10) |
2282
+ | `DefinitionReader` | type | [声明](../../../dist/esm/support/decorators/pool.d.ts#L9) |
2283
+ | `fragment` | value | [声明](../../../dist/esm/support/decorators/index.d.ts#L27) |
2284
+ | `Fragment` | type | [声明](../../../dist/esm/support/decorators/types.d.ts#L16) |
2285
+ | `fragmentPool` | value | [声明](../../../dist/esm/support/decorators/pool.d.ts#L24) |
2286
+ | `IdentifiedDefinition` | type | [声明](../../../dist/esm/support/decorators/pool.d.ts#L5) |
2287
+ | `MethodDecoration` | type | [声明](../../../dist/esm/support/decorators/definition.d.ts#L14) |
2288
+ | `model` | value | [声明](../../../dist/esm/support/decorators/index.d.ts#L39) |
2289
+ | `Model` | type | [声明](../../../dist/esm/support/decorators/types.d.ts#L22) |
2290
+ | `ModelOptions` | type | [声明](../../../dist/esm/support/decorators/index.d.ts#L37) |
2291
+ | `modelPool` | value | [声明](../../../dist/esm/support/decorators/pool.d.ts#L86) |
2292
+ | `node` | value | [声明](../../../dist/esm/support/decorators/index.d.ts#L19) |
2293
+ | `Node` | type | [声明](../../../dist/esm/support/decorators/types.d.ts#L12) |
2294
+ | `nodePool` | value | [声明](../../../dist/esm/support/decorators/pool.d.ts#L20) |
2295
+ | `tool` | value | [声明](../../../dist/esm/support/decorators/index.d.ts#L23) |
2296
+ | `Tool` | type | [声明](../../../dist/esm/support/decorators/types.d.ts#L14) |
2297
+ | `toolPool` | value | [声明](../../../dist/esm/support/decorators/pool.d.ts#L22) |
2298
+ | `workflow` | value | [声明](../../../dist/esm/support/decorators/index.d.ts#L31) |
2299
+ | `Workflow` | type | [声明](../../../dist/esm/support/decorators/types.d.ts#L18) |
2300
+ | `workflowPool` | value | [声明](../../../dist/esm/support/decorators/pool.d.ts#L26) |
@@ -74,3 +74,7 @@ A custom response collector is synchronous and request-local. Its outputChars mu
74
74
  ## Node cache ownership
75
75
 
76
76
  Use context.cache for bounded Engine memory; its default capacity is 1024, partitions are node-local and only get may name another node. The low-level step partition is `$step`. An App may explicitly inject an asynchronous AgentCachePort for context.agentCache. Persistence must be supported explicitly, is separate from volatile storage and never falls back. The App owns user isolation, serialization, capacity and expiry; do not cache authorization decisions. Forks start with empty Engine memory and only regain an App port when resume explicitly supplies agentCache. Keep durable facts in state/App storage, not caches.
77
+
78
+ ## Optional definition decorators
79
+
80
+ Use the standard-only /support/decorators entry for class-based definitions or existing host methods. Classes supply original options except id; the decorator constructs once and supplies id. Host methods bind and register automatically during standard instance initialization; read and execute only after successful construction. Constructor failures do not roll back initializer registration. Use long-lived service hosts, never request-scoped ones. Keep helper methods/private fields in their real class, never a duplicate options metadata block or empty carrier. Existing Nest legacy compilation keeps object definitions. No public metadata-plus-function adapters, Engine factories, automatic DI or request lifecycle wrappers are provided. Use nodePool/toolPool/fragmentPool/workflowPool/agentPool/modelPool, without creating pools or manually registering. Decorator ns is a string or string array, default 'default'; same-kind ids are unique within a namespace. Read get(id, ns?), getAll(ns?) or pick(ids, ns?); get may return undefined. Multi-namespace registration shares one definition and preflights all conflicts. ESM/CJS copies share readers within one realm. Read api/decorators.md for registration, receivers and type limits.
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.classDecoration = classDecoration;
4
+ exports.methodDecoration = methodDecoration;
5
+ /**
6
+ * Internal decoration: construct definition classes or bind methods to their real host,
7
+ * compile through existing entry points and automatically register in the kind's root.
8
+ */
9
+ const pool_js_1 = require("./pool.js");
10
+ /** Restore only the decorator-owned id, preserving instance identity, getters and private state. */
11
+ function withId(id, instance) {
12
+ if ('id' in instance)
13
+ throw new TypeError('Decoration supplies id; do not also define it on the class');
14
+ Object.defineProperty(instance, 'id', { value: id, enumerable: true });
15
+ return instance;
16
+ }
17
+ /** Class definitions register once after static initialization and successful construction. */
18
+ function classDecoration(kind, id, options, compile) {
19
+ return (_target, context) => {
20
+ if (context?.kind !== 'class')
21
+ throw new TypeError('Use standard class decorator semantics');
22
+ context.addInitializer(function () {
23
+ (0, pool_js_1.registerDefinition)(kind, compile(withId(id, new this())), options.ns);
24
+ });
25
+ };
26
+ }
27
+ /** Method initializers bind and register automatically; no scanning or caller-side bind is needed. */
28
+ function methodDecoration(kind, id, metadata, handlerKey, options, compile) {
29
+ return (method, context) => {
30
+ if (context?.kind !== 'method' || context.static || context.private)
31
+ throw new TypeError('Use a standard public instance method decorator');
32
+ context.addInitializer(function () {
33
+ const value = { ...metadata, [handlerKey]: method.bind(this) };
34
+ for (const key of Reflect.ownKeys(value)) {
35
+ const member = value[key];
36
+ if (typeof member === 'function')
37
+ value[key] = member.bind(this);
38
+ }
39
+ (0, pool_js_1.registerDefinition)(kind, compile(withId(id, value)), options.ns);
40
+ });
41
+ };
42
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.modelPool = exports.agentPool = exports.workflowPool = exports.fragmentPool = exports.toolPool = exports.nodePool = void 0;
4
+ exports.node = node;
5
+ exports.tool = tool;
6
+ exports.fragment = fragment;
7
+ exports.workflow = workflow;
8
+ exports.agent = agent;
9
+ exports.model = model;
10
+ const tools_js_1 = require("../tools.js");
11
+ const workflow_js_1 = require("../../execution/workflow.js");
12
+ const assembly_js_1 = require("../context/assembly.js");
13
+ const binding_js_1 = require("../../model/binding.js");
14
+ const definition_js_1 = require("./definition.js");
15
+ var pool_js_1 = require("./pool.js");
16
+ Object.defineProperty(exports, "nodePool", { enumerable: true, get: function () { return pool_js_1.nodePool; } });
17
+ Object.defineProperty(exports, "toolPool", { enumerable: true, get: function () { return pool_js_1.toolPool; } });
18
+ Object.defineProperty(exports, "fragmentPool", { enumerable: true, get: function () { return pool_js_1.fragmentPool; } });
19
+ Object.defineProperty(exports, "workflowPool", { enumerable: true, get: function () { return pool_js_1.workflowPool; } });
20
+ Object.defineProperty(exports, "agentPool", { enumerable: true, get: function () { return pool_js_1.agentPool; } });
21
+ Object.defineProperty(exports, "modelPool", { enumerable: true, get: function () { return pool_js_1.modelPool; } });
22
+ /** Internal conversion shared by node/tool/fragment; never a public free-function adapter. */
23
+ function decorate(kind, id, options, key, compile) {
24
+ return (value, context) => {
25
+ if (context?.kind === 'class') {
26
+ (0, definition_js_1.classDecoration)(kind, id, options, compile)(value, context);
27
+ }
28
+ else {
29
+ const { ns, ...metadata } = options;
30
+ (0, definition_js_1.methodDecoration)(kind, id, metadata, key, { ns }, compile)(value, context);
31
+ }
32
+ };
33
+ }
34
+ function node(id, options = {}) {
35
+ return decorate('node', id, options, 'run', (value) => value);
36
+ }
37
+ function tool(id, options = {}) {
38
+ return decorate('tool', id, options, 'execute', (value) => (0, tools_js_1.defineTool)(value));
39
+ }
40
+ function fragment(id, options = {}) {
41
+ return decorate('fragment', id, options, 'format', (value) => {
42
+ (0, assembly_js_1.defineContextFragments)([value]);
43
+ return value;
44
+ });
45
+ }
46
+ /** Instantiate and validate workflow options, leaving actual execution with the original Engine. */
47
+ function workflow(id, options = {}) {
48
+ return (0, definition_js_1.classDecoration)('workflow', id, options, (value) => {
49
+ (0, workflow_js_1.defineWorkflow)(value);
50
+ return value;
51
+ });
52
+ }
53
+ /** Instantiate an Engine configuration class without creating an Engine, budget or request. */
54
+ function agent(id, options = {}) {
55
+ return (0, definition_js_1.classDecoration)('agent', id, options, (value) => value);
56
+ }
57
+ /** Instantiate and validate model options without creating a Runner or consuming calls. */
58
+ function model(id, options = {}) {
59
+ return (0, definition_js_1.classDecoration)('model', id, options, (value) => {
60
+ (0, binding_js_1.snapshotModelBinding)(value);
61
+ return value;
62
+ });
63
+ }
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.modelPool = exports.agentPool = exports.workflowPool = exports.fragmentPool = exports.toolPool = exports.nodePool = exports.definitionKinds = void 0;
4
+ exports.registerDefinition = registerDefinition;
5
+ /**
6
+ * One process-realm definition registry per kind. The shared symbol makes ESM/CJS copies
7
+ * consume the same stores; consumers receive frozen read-only views, never pool factories.
8
+ */
9
+ const protocol_registry_js_1 = require("../../utils/protocol-registry.js");
10
+ /** Enumerable categories drive allocation and lookup; no additional runtime dispatch layer. */
11
+ exports.definitionKinds = ['node', 'tool', 'fragment', 'workflow', 'agent', 'model'];
12
+ const sharedKey = Symbol.for('@jangts/agent-core/decorator-roots/v2');
13
+ const realm = globalThis;
14
+ /** Allocate once per realm, including when another module format initialized the roots first. */
15
+ function sharedPools() {
16
+ const existing = realm[sharedKey];
17
+ if (existing) {
18
+ if (existing.version !== 2 || exports.definitionKinds.some((kind) => !existing.stores[kind]))
19
+ throw new TypeError('Incompatible decorator root registry');
20
+ return existing;
21
+ }
22
+ const stores = Object.fromEntries(exports.definitionKinds.map((kind) => [kind, new Map()]));
23
+ const pools = Object.freeze({ version: 2, stores: Object.freeze(stores) });
24
+ Object.defineProperty(globalThis, sharedKey, { value: pools });
25
+ return pools;
26
+ }
27
+ /** Namespace is an exact, nonblank key; no trimming, fallback or hierarchy is applied. */
28
+ function namespace(value) {
29
+ if (typeof value !== 'string' || !value.trim())
30
+ throw new TypeError('Decorator namespace must be a nonempty string');
31
+ return value;
32
+ }
33
+ /** Preflight every destination so a conflict never leaves partial multi-namespace registration. */
34
+ function registerDefinition(kind, definition, ns = 'default') {
35
+ if (typeof definition.id !== 'string' || !definition.id.trim())
36
+ throw new TypeError('Invalid decorator definition id');
37
+ const requested = typeof ns === 'string' ? [ns] : ns;
38
+ if (!Array.isArray(requested) || requested.length === 0)
39
+ throw new TypeError('Decorator ns must be a namespace or a nonempty namespace array');
40
+ const names = [...new Set(requested.map(namespace))];
41
+ const store = sharedPools().stores[kind];
42
+ for (const name of names) {
43
+ if (store.get(name)?.has(definition.id))
44
+ throw new Error(`Duplicate ${kind} definition: ${definition.id} (ns: ${name})`);
45
+ }
46
+ for (const name of names) {
47
+ let entries = store.get(name);
48
+ if (!entries)
49
+ store.set(name, (entries = new protocol_registry_js_1.ProtocolRegistry()));
50
+ entries.set(definition.id, definition);
51
+ }
52
+ }
53
+ /** Root reads never instantiate or execute definitions; array results are immutable snapshots. */
54
+ function reader(kind) {
55
+ const store = sharedPools().stores[kind];
56
+ return Object.freeze({
57
+ get(id, ns = 'default') {
58
+ return store.get(namespace(ns))?.get(id);
59
+ },
60
+ getAll(ns = 'default') {
61
+ return Object.freeze([...(store.get(namespace(ns))?.values() ?? [])]);
62
+ },
63
+ pick(ids, ns = 'default') {
64
+ const entries = store.get(namespace(ns));
65
+ const selected = new protocol_registry_js_1.ProtocolRegistry();
66
+ for (const id of ids) {
67
+ const definition = entries?.get(id);
68
+ if (!definition)
69
+ throw new TypeError(`Unknown ${kind} definition: ${id} (ns: ${ns})`);
70
+ selected.set(id, definition);
71
+ }
72
+ return Object.freeze([...selected.values()]);
73
+ },
74
+ });
75
+ }
76
+ /** Decorated nodes; ids are unique within each namespace. */
77
+ exports.nodePool = reader('node');
78
+ /** Decorated tools; namespaces isolate otherwise identical ids. */
79
+ exports.toolPool = reader('tool');
80
+ /** Decorated fragment configurations; use the original builder to assemble them. */
81
+ exports.fragmentPool = reader('fragment');
82
+ /** Decorated workflow definitions; execution still belongs to the original Engine. */
83
+ exports.workflowPool = reader('workflow');
84
+ /** Decorated Engine options; request-specific App contracts are supplied on typed reads. */
85
+ exports.agentPool = reader('agent');
86
+ /** Decorated Runner options; reading does not create a Runner or spend model calls. */
87
+ exports.modelPool = reader('model');
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Internal decoration: construct definition classes or bind methods to their real host,
3
+ * compile through existing entry points and automatically register in the kind's root.
4
+ */
5
+ import { type DefinitionKind, type IdentifiedDefinition } from './pool.js';
6
+ type Handler = (this: any, ...args: any[]) => any;
7
+ /** Preserve union branches when removing the decorator-owned id. */
8
+ export type DefinitionBody<Definition> = Definition extends unknown ? Omit<Definition, 'id'> : never;
9
+ /** Namespaces group external registration without changing Core options. */
10
+ export interface DecorationOptions {
11
+ readonly ns?: string | readonly string[];
12
+ }
13
+ export type ClassDecoration<Definition extends IdentifiedDefinition> = <Constructor extends new () => DefinitionBody<Definition>>(target: Constructor, context: ClassDecoratorContext<Constructor>) => void;
14
+ export type MethodDecoration<Method extends Handler> = <This>(method: (this: This, ...args: Parameters<Method>) => ReturnType<Method>, context: ClassMethodDecoratorContext<This, (this: This, ...args: Parameters<Method>) => ReturnType<Method>>) => void;
15
+ /** Class definitions register once after static initialization and successful construction. */
16
+ export declare function classDecoration<Definition extends IdentifiedDefinition>(kind: DefinitionKind, id: string, options: DecorationOptions, compile: (value: Definition) => Definition): ClassDecoration<Definition>;
17
+ /** Method initializers bind and register automatically; no scanning or caller-side bind is needed. */
18
+ export declare function methodDecoration<Definition extends IdentifiedDefinition, Method extends Handler>(kind: DefinitionKind, id: string, metadata: DefinitionBody<Definition>, handlerKey: keyof Definition, options: DecorationOptions, compile: (value: Definition) => Definition): MethodDecoration<Method>;
19
+ export {};
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Internal decoration: construct definition classes or bind methods to their real host,
3
+ * compile through existing entry points and automatically register in the kind's root.
4
+ */
5
+ import { registerDefinition } from './pool.js';
6
+ /** Restore only the decorator-owned id, preserving instance identity, getters and private state. */
7
+ function withId(id, instance) {
8
+ if ('id' in instance)
9
+ throw new TypeError('Decoration supplies id; do not also define it on the class');
10
+ Object.defineProperty(instance, 'id', { value: id, enumerable: true });
11
+ return instance;
12
+ }
13
+ /** Class definitions register once after static initialization and successful construction. */
14
+ export function classDecoration(kind, id, options, compile) {
15
+ return (_target, context) => {
16
+ if (context?.kind !== 'class')
17
+ throw new TypeError('Use standard class decorator semantics');
18
+ context.addInitializer(function () {
19
+ registerDefinition(kind, compile(withId(id, new this())), options.ns);
20
+ });
21
+ };
22
+ }
23
+ /** Method initializers bind and register automatically; no scanning or caller-side bind is needed. */
24
+ export function methodDecoration(kind, id, metadata, handlerKey, options, compile) {
25
+ return (method, context) => {
26
+ if (context?.kind !== 'method' || context.static || context.private)
27
+ throw new TypeError('Use a standard public instance method decorator');
28
+ context.addInitializer(function () {
29
+ const value = { ...metadata, [handlerKey]: method.bind(this) };
30
+ for (const key of Reflect.ownKeys(value)) {
31
+ const member = value[key];
32
+ if (typeof member === 'function')
33
+ value[key] = member.bind(this);
34
+ }
35
+ registerDefinition(kind, compile(withId(id, value)), options.ns);
36
+ });
37
+ };
38
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Optional standard decorators. Classes are definition implementations; public instance methods
3
+ * keep their original host. Only definitions are created here, never Engines or ModelRunners.
4
+ */
5
+ import type { WorkflowNode, AgentWorkflowDefinition } from '../../structs/execution/workflow.js';
6
+ import type { AgentCoreEngineSetup } from '../../execution/engine.js';
7
+ import type { ToolDefinition } from '../../structs/capabilities/tools.js';
8
+ import type { ContextFragmentConfig } from '../../structs/support/context.js';
9
+ import type { ModelRunnerOptions } from '../../structs/model/runtime.js';
10
+ import { type ClassDecoration, type MethodDecoration, type DecorationOptions } from './definition.js';
11
+ import type { IdentifiedDefinition } from './pool.js';
12
+ export { nodePool, toolPool, fragmentPool, workflowPool, agentPool, modelPool } from './pool.js';
13
+ export type { IdentifiedDefinition, DefinitionReader } from './pool.js';
14
+ export type { ClassDecoration, MethodDecoration, DecorationOptions } from './definition.js';
15
+ export type { Node, Tool, Fragment, Workflow, Agent, Model } from './types.js';
16
+ /** Method metadata describes the adapted handler, with optional external namespaces. */
17
+ type MethodOptions<Definition extends IdentifiedDefinition, Key extends keyof Definition> = Omit<Definition, 'id' | Key> & DecorationOptions;
18
+ /** Instantiate a node definition class once, injecting its id; graph validation stays in Workflow. */
19
+ export declare function node<State = any, Result = unknown, App = any>(id: string, options?: DecorationOptions): ClassDecoration<WorkflowNode<State, Result, App>>;
20
+ /** Bind a named host method as run without renaming or manually binding the original object. */
21
+ export declare function node<State = any, Result = unknown, App = any>(id: string, options: MethodOptions<WorkflowNode<State, Result, App>, 'run'>): MethodDecoration<NonNullable<WorkflowNode<State, Result, App>['run']>>;
22
+ /** Instantiate a tool definition class; schema and authorization stay with existing defineTool. */
23
+ export declare function tool<Input = unknown, Output = unknown, App = any>(id: string, options?: DecorationOptions): ClassDecoration<ToolDefinition<Input, Output, App>>;
24
+ /** Bind an existing host method as the tool's execute callback. */
25
+ export declare function tool<Input = unknown, Output = unknown, App = any>(id: string, options: MethodOptions<ToolDefinition<Input, Output, App>, 'execute'>): MethodDecoration<ToolDefinition<Input, Output, App>['execute']>;
26
+ /** Instantiate a self-describing fragment class; the original builder owns formatting checks. */
27
+ export declare function fragment<Input = unknown>(id: string, options?: DecorationOptions): ClassDecoration<ContextFragmentConfig<Input>>;
28
+ /** Bind a host's formatter method into an original fragment configuration. */
29
+ export declare function fragment<Input = unknown>(id: string, options: MethodOptions<ContextFragmentConfig<Input>, 'format'>): MethodDecoration<ContextFragmentConfig<Input>['format']>;
30
+ /** Instantiate and validate workflow options, leaving actual execution with the original Engine. */
31
+ export declare function workflow<State = any, Result = unknown, App = any>(id: string, options?: DecorationOptions): ClassDecoration<AgentWorkflowDefinition<State, Result, App>>;
32
+ /** Agent id is an external pool identity, not an override of Core branch or request identity. */
33
+ export type AgentOptions<State = unknown, Result = unknown, App = undefined> = AgentCoreEngineSetup<State, Result, App> & IdentifiedDefinition;
34
+ /** Instantiate an Engine configuration class without creating an Engine, budget or request. */
35
+ export declare function agent<State = unknown, Result = unknown, App = undefined>(id: string, options?: DecorationOptions): ClassDecoration<AgentOptions<State, Result, App>>;
36
+ /** Model id is only a pool key; Core still owns the configured model/transport identities. */
37
+ export type ModelOptions = ModelRunnerOptions & IdentifiedDefinition;
38
+ /** Instantiate and validate model options without creating a Runner or consuming calls. */
39
+ export declare function model(id: string, options?: DecorationOptions): ClassDecoration<ModelOptions>;
@@ -0,0 +1,48 @@
1
+ import { defineTool } from '../tools.js';
2
+ import { defineWorkflow } from '../../execution/workflow.js';
3
+ import { defineContextFragments } from '../context/assembly.js';
4
+ import { snapshotModelBinding } from '../../model/binding.js';
5
+ import { classDecoration, methodDecoration, } from './definition.js';
6
+ export { nodePool, toolPool, fragmentPool, workflowPool, agentPool, modelPool } from './pool.js';
7
+ /** Internal conversion shared by node/tool/fragment; never a public free-function adapter. */
8
+ function decorate(kind, id, options, key, compile) {
9
+ return (value, context) => {
10
+ if (context?.kind === 'class') {
11
+ classDecoration(kind, id, options, compile)(value, context);
12
+ }
13
+ else {
14
+ const { ns, ...metadata } = options;
15
+ methodDecoration(kind, id, metadata, key, { ns }, compile)(value, context);
16
+ }
17
+ };
18
+ }
19
+ export function node(id, options = {}) {
20
+ return decorate('node', id, options, 'run', (value) => value);
21
+ }
22
+ export function tool(id, options = {}) {
23
+ return decorate('tool', id, options, 'execute', (value) => defineTool(value));
24
+ }
25
+ export function fragment(id, options = {}) {
26
+ return decorate('fragment', id, options, 'format', (value) => {
27
+ defineContextFragments([value]);
28
+ return value;
29
+ });
30
+ }
31
+ /** Instantiate and validate workflow options, leaving actual execution with the original Engine. */
32
+ export function workflow(id, options = {}) {
33
+ return classDecoration('workflow', id, options, (value) => {
34
+ defineWorkflow(value);
35
+ return value;
36
+ });
37
+ }
38
+ /** Instantiate an Engine configuration class without creating an Engine, budget or request. */
39
+ export function agent(id, options = {}) {
40
+ return classDecoration('agent', id, options, (value) => value);
41
+ }
42
+ /** Instantiate and validate model options without creating a Runner or consuming calls. */
43
+ export function model(id, options = {}) {
44
+ return classDecoration('model', id, options, (value) => {
45
+ snapshotModelBinding(value);
46
+ return value;
47
+ });
48
+ }
@@ -0,0 +1,97 @@
1
+ import type { WorkflowNode, AgentWorkflowDefinition } from '../../structs/execution/workflow.js';
2
+ import type { ToolDefinition } from '../../structs/capabilities/tools.js';
3
+ import type { ContextFragmentConfig } from '../../structs/support/context.js';
4
+ /** Registration identity; ids are unique within one kind and namespace. */
5
+ export interface IdentifiedDefinition {
6
+ readonly id: string;
7
+ }
8
+ /** Read-only roots. A typed read describes the expected contract, not a static id/type lookup. */
9
+ export interface DefinitionReader<Definition extends IdentifiedDefinition> {
10
+ get<Value extends Definition = Definition>(id: string, ns?: string): Value | undefined;
11
+ getAll<Value extends Definition = Definition>(ns?: string): readonly Value[];
12
+ pick<Value extends Definition = Definition>(ids: readonly string[], ns?: string): readonly Value[];
13
+ }
14
+ /** Enumerable categories drive allocation and lookup; no additional runtime dispatch layer. */
15
+ export declare const definitionKinds: readonly ["node", "tool", "fragment", "workflow", "agent", "model"];
16
+ export type DefinitionKind = (typeof definitionKinds)[number];
17
+ /** Preflight every destination so a conflict never leaves partial multi-namespace registration. */
18
+ export declare function registerDefinition(kind: DefinitionKind, definition: IdentifiedDefinition, ns?: string | readonly string[]): void;
19
+ /** Decorated nodes; ids are unique within each namespace. */
20
+ export declare const nodePool: DefinitionReader<WorkflowNode<any, any, any>>;
21
+ /** Decorated tools; namespaces isolate otherwise identical ids. */
22
+ export declare const toolPool: DefinitionReader<ToolDefinition<any, any, any, string>>;
23
+ /** Decorated fragment configurations; use the original builder to assemble them. */
24
+ export declare const fragmentPool: DefinitionReader<ContextFragmentConfig<any>>;
25
+ /** Decorated workflow definitions; execution still belongs to the original Engine. */
26
+ export declare const workflowPool: DefinitionReader<AgentWorkflowDefinition<any, any, any>>;
27
+ /** Decorated Engine options; request-specific App contracts are supplied on typed reads. */
28
+ export declare const agentPool: DefinitionReader<(Omit<import("../../index.js").AgentCoreEngineOptions & {
29
+ readonly branch?: import("../../index.js").AgentBranch;
30
+ readonly tools?: {
31
+ invoke: (request: import("../../index.js").ToolInvocationRequest) => Promise<import("../../index.js").ToolResult<unknown>>;
32
+ } | Pick<import("../../index.js").ToolRegistry<import("../../index.js").ExecutableTool>, "invokeAsync">;
33
+ } & {
34
+ model?: import("../../index.js").AgentModelBinding;
35
+ models?: never;
36
+ } & {
37
+ workflow?: undefined;
38
+ app?: never;
39
+ }, "app"> & {
40
+ readonly app?: unknown;
41
+ } & IdentifiedDefinition) | (Omit<import("../../index.js").AgentCoreEngineOptions & {
42
+ readonly branch?: import("../../index.js").AgentBranch;
43
+ readonly tools?: {
44
+ invoke: (request: import("../../index.js").ToolInvocationRequest) => Promise<import("../../index.js").ToolResult<unknown>>;
45
+ } | Pick<import("../../index.js").ToolRegistry<import("../../index.js").ExecutableTool>, "invokeAsync">;
46
+ } & {
47
+ model?: string;
48
+ models: Readonly<Record<string, import("../../index.js").AgentModelBinding>>;
49
+ maxModelCalls?: number;
50
+ } & {
51
+ workflow?: undefined;
52
+ app?: never;
53
+ }, "app"> & {
54
+ readonly app?: unknown;
55
+ } & IdentifiedDefinition) | (Omit<import("../../index.js").AgentCoreEngineOptions & {
56
+ readonly branch?: import("../../index.js").AgentBranch;
57
+ readonly tools?: {
58
+ invoke: (request: import("../../index.js").ToolInvocationRequest) => Promise<import("../../index.js").ToolResult<unknown>>;
59
+ } | Pick<import("../../index.js").ToolRegistry<import("../../index.js").ExecutableTool>, "invokeAsync">;
60
+ } & {
61
+ model?: import("../../index.js").AgentModelBinding;
62
+ models?: never;
63
+ } & {
64
+ readonly workflow: import("../../index.js").AgentWorkflow<any, any, any>;
65
+ } & {
66
+ readonly app?: undefined;
67
+ }, "app"> & {
68
+ readonly app?: unknown;
69
+ } & IdentifiedDefinition) | (Omit<import("../../index.js").AgentCoreEngineOptions & {
70
+ readonly branch?: import("../../index.js").AgentBranch;
71
+ readonly tools?: {
72
+ invoke: (request: import("../../index.js").ToolInvocationRequest) => Promise<import("../../index.js").ToolResult<unknown>>;
73
+ } | Pick<import("../../index.js").ToolRegistry<import("../../index.js").ExecutableTool>, "invokeAsync">;
74
+ } & {
75
+ model?: string;
76
+ models: Readonly<Record<string, import("../../index.js").AgentModelBinding>>;
77
+ maxModelCalls?: number;
78
+ } & {
79
+ readonly workflow: import("../../index.js").AgentWorkflow<any, any, any>;
80
+ } & {
81
+ readonly app?: undefined;
82
+ }, "app"> & {
83
+ readonly app?: unknown;
84
+ } & IdentifiedDefinition)>;
85
+ /** Decorated Runner options; reading does not create a Runner or spend model calls. */
86
+ export declare const modelPool: DefinitionReader<{
87
+ provider: import("../../index.js").ChatProvider;
88
+ execution?: import("../../index.js").ExecutionOptions;
89
+ transports?: readonly import("../../index.js").ModelTransportDefinition<unknown>[] | undefined;
90
+ sink?: {
91
+ output?: import("../../index.js").ModelRunnerPorts["onOutput"];
92
+ };
93
+ errors?: {
94
+ inputBudget?: import("../../index.js").ModelRunnerPorts["inputBudgetError"];
95
+ outputBudget?: import("../../index.js").ModelRunnerPorts["outputBudgetError"];
96
+ };
97
+ } & import("../../index.js").ModelRunnerSettings & IdentifiedDefinition>;