@onco-foundry/agent-template 0.1.1 → 0.2.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.
@@ -1,7 +1,8 @@
1
- import { type AgentSpec, type ModelClient } from 'agent-lattice';
1
+ import { type AgentSpec, type ModelClient, type ToolDefinition } from 'agent-lattice';
2
2
  import { z } from 'zod';
3
3
  import { type Capability } from '@onco-foundry/capability-registry';
4
4
  import type { CapabilityDelegation } from '@onco-foundry/agent-runtime';
5
+ import { type VersionedResource } from '@onco-foundry/resource-versioning';
5
6
  import { type Tracer } from '@onco-foundry/trace-port';
6
7
  /**
7
8
  * 版本化 prompt 资源的 manifest 形状:结构版本号与内容版本号分开,
@@ -30,7 +31,21 @@ export type AgentTemplateCard<I = unknown, O = unknown> = {
30
31
  readonly input: z.ZodType<I>;
31
32
  readonly output: z.ZodType<O>;
32
33
  };
33
- export type AgentTemplateDeclaration<I, O> = {
34
+ /**
35
+ * prompt 资源形状适配:资源目录不是平台 prompt manifest 形状(promptManifestSchema)
36
+ * 时注入。manifestSchema 传给 loadActiveVersionedResource 做校验(文件引用照常做
37
+ * 路径防穿越与 sha256 比对);resolve 从加载结果里取出 systemPrompt 文本与
38
+ * promptVersion。resolve 返回空 systemPrompt 与缺文件同等抛错——空 prompt 不进模型。
39
+ * manifest 的业务字段形状由注入方自定,库内只能按 any 过手。
40
+ */
41
+ export type PromptManifestAdapter = {
42
+ readonly manifestSchema: z.ZodType<any>;
43
+ readonly resolve: (loaded: VersionedResource<any>) => {
44
+ systemPrompt: string;
45
+ promptVersion: string;
46
+ };
47
+ };
48
+ export type AgentTemplateDeclaration<I, O, C = undefined> = {
34
49
  /** kebab-case:能力名片名;spec 名由它派生(kebab→snake,id.replaceAll('-', '_'))。 */
35
50
  id: string;
36
51
  /** 一句话职责:名片 summary,也是 typed 工具菜单文案的缺省。 */
@@ -40,10 +55,22 @@ export type AgentTemplateDeclaration<I, O> = {
40
55
  /** submit 交付契约(zod):名片 output = spec 的 outputSchema(SDK 据此注入 submit_output)。 */
41
56
  output: z.ZodType<O>;
42
57
  /**
43
- * mapInput 话术:把校验后的 typed 入参投影成子级 prompt。sync——需要
44
- * per-call 异步预处理(取图、缩放)的模板不适用本声明件,维持自建工厂。
58
+ * mapInput 话术:把校验后的 typed 入参投影成子级 prompt。第二个参数是会话级
59
+ * 上下文(见 createXxx 的 context 参数);C=undefined 时只传 input 的现有写法
60
+ * 保持可赋值,向后兼容。sync——需要 per-call 异步预处理(取图、缩放)的模板
61
+ * 不适用本声明件,维持自建工厂。
45
62
  */
46
- task: (input: I) => string;
63
+ task: (input: I, context: C) => string;
64
+ /**
65
+ * 业务工具槽位(可选):按 context 构建工具,依赖(上下文身份、存储端口、
66
+ * logger 等)经 context 在创建时绑定。工具与 SDK 注入的 submit_output 并存。
67
+ */
68
+ tools?: (context: C) => ToolDefinition[];
69
+ /**
70
+ * prompt 资源形状适配(可选):资源目录不是平台 prompt manifest 形状时注入。
71
+ * 缺省 = 平台形状(versionedManifestBaseShape + promptVersion/provenance/systemPrompt 引用),现状不变。
72
+ */
73
+ promptManifest?: PromptManifestAdapter;
47
74
  /**
48
75
  * 版本化 prompt 资源根(含 current.json 指针):
49
76
  * new URL('./resources/prompts/', import.meta.url)。生效版本解析归模板,编排方零感知。
@@ -72,12 +99,12 @@ export type CreateTemplateAgentOptions = {
72
99
  /** prompt 版本覆盖缝:指定版本目录名则跳过 current.json 指针,试跑/对照工具用。 */
73
100
  promptVersion?: string;
74
101
  };
75
- export type AgentTemplate<I, O> = {
102
+ export type AgentTemplate<I, O, C = undefined> = {
76
103
  /** 能力名片:{ name: id, kind: 'agent', summary, input, output },无 version(版本归场景,ADR-10)。 */
77
104
  readonly card: AgentTemplateCard<I, O>;
78
105
  /**
79
106
  * 加载生效版本 prompt(或 promptVersion 指定版本):返回 { systemPrompt, promptVersion }。
80
- * 资源缺文件当场抛错。
107
+ * 资源缺文件当场抛错;promptManifest 注入时 resolve 出空 systemPrompt 同等抛错。
81
108
  */
82
109
  loadPrompt(options?: {
83
110
  promptVersion?: string;
@@ -85,21 +112,25 @@ export type AgentTemplate<I, O> = {
85
112
  systemPrompt: string;
86
113
  promptVersion: string;
87
114
  }>;
88
- /** 构建 AgentSpec:加载 prompt + defineAgent(裸会话 workspace:false,outputSchema 交给 SDK 注入 submit_output)。 */
89
- createSpec(options: CreateTemplateAgentOptions): Promise<AgentSpec>;
90
- /** typed 委派两块料:{ spec, mapInput: task }。async——prompt 加载是 IO。 */
91
- createDelegation(options: CreateTemplateAgentOptions): Promise<CapabilityDelegation>;
115
+ /**
116
+ * 构建 AgentSpec:加载 prompt + defineAgent(裸会话 workspace:false,outputSchema 交给
117
+ * SDK 注入 submit_output)。context 是会话级数据与端口(本次任务对象 id、存储、logger),
118
+ * 会随任务变的走它;声明了 tools 槽位时按 context 构建工具挂进 spec。
119
+ */
120
+ createSpec(options: CreateTemplateAgentOptions, context?: C): Promise<AgentSpec>;
121
+ /** typed 委派两块料:{ spec, mapInput }。mapInput 闭包 context。async——prompt 加载是 IO。 */
122
+ createDelegation(options: CreateTemplateAgentOptions, context?: C): Promise<CapabilityDelegation>;
92
123
  /**
93
124
  * 完整能力:defineCapability({ ...card, version: version ?? promptVersion, run })。
94
- * run 由库提供:parse 入参 → spec.spawn().prompt(task(input)) → is_error 抛错
125
+ * run 由库提供:parse 入参 → spec.spawn().prompt(task(input, context)) → is_error 抛错
95
126
  * → structuredResult 缺失抛错 → output.parse 后返回。
96
127
  */
97
128
  createCapability(options: CreateTemplateAgentOptions & {
98
129
  version?: string;
99
- }): Promise<Capability<I, O>>;
130
+ }, context?: C): Promise<Capability<I, O>>;
100
131
  };
101
132
  /**
102
- * 智能体模板声明件:同构简单模板(submit 交付过 schema 即可、无工具、无 loop 外组装)
133
+ * 智能体模板声明件:同构简单模板(submit 交付过 schema 即可、交付物不在 loop 外组装)
103
134
  * 的生产侧形状。一次声明吐出四个出口:名片 / loadPrompt / spec / delegation / capability。
104
135
  *
105
136
  * 版本绑定口径:声明件模板的交付 payload = 纯业务契约,版本绑定不进 payload——
@@ -108,5 +139,12 @@ export type AgentTemplate<I, O> = {
108
139
  * ToolDefinition.metadata(createTypedAgentTool 投射时写入)、createCapability
109
140
  * 返回能力的 describe()。这与 knowledge-gatekeeper(自定义 submit 工具把版本注入
110
141
  * payload)是两派实现,不要混用。
142
+ *
143
+ * options vs context 的分工:options(CreateTemplateAgentOptions)是静态装配——
144
+ * model、tracer、promptVersion 覆盖缝;context(泛型 C)是会话级数据与端口——
145
+ * 本次任务对象 id、存储端口、logger 等会随任务变的东西。SDK 的 TContext 通道
146
+ * (QueryOptions.context → ToolExecutionContext)穿不过 agentTool 的 typed 委派
147
+ * 边界(agentTool spawn 子会话时不转发父级 context),所以 context 在工厂调用时
148
+ * 绑定:task 的第二个参数、tools 槽位的构建参数都从它取值。
111
149
  */
112
- export declare const defineAgentTemplate: <I, O>(declaration: AgentTemplateDeclaration<I, O>) => AgentTemplate<I, O>;
150
+ export declare const defineAgentTemplate: <I, O, C = undefined>(declaration: AgentTemplateDeclaration<I, O, C>) => AgentTemplate<I, O, C>;
@@ -26,7 +26,7 @@ const DEFAULT_MAX_TURNS = 10;
26
26
  export const clampThinkingBudgetTokens = (requestedBudgetTokens, maxTokens) => Math.min(requestedBudgetTokens, Math.max(maxTokens, 2) - 1);
27
27
  const kebabCasePattern = /^[a-z0-9]+(-[a-z0-9]+)*$/;
28
28
  /**
29
- * 智能体模板声明件:同构简单模板(submit 交付过 schema 即可、无工具、无 loop 外组装)
29
+ * 智能体模板声明件:同构简单模板(submit 交付过 schema 即可、交付物不在 loop 外组装)
30
30
  * 的生产侧形状。一次声明吐出四个出口:名片 / loadPrompt / spec / delegation / capability。
31
31
  *
32
32
  * 版本绑定口径:声明件模板的交付 payload = 纯业务契约,版本绑定不进 payload——
@@ -35,6 +35,13 @@ const kebabCasePattern = /^[a-z0-9]+(-[a-z0-9]+)*$/;
35
35
  * ToolDefinition.metadata(createTypedAgentTool 投射时写入)、createCapability
36
36
  * 返回能力的 describe()。这与 knowledge-gatekeeper(自定义 submit 工具把版本注入
37
37
  * payload)是两派实现,不要混用。
38
+ *
39
+ * options vs context 的分工:options(CreateTemplateAgentOptions)是静态装配——
40
+ * model、tracer、promptVersion 覆盖缝;context(泛型 C)是会话级数据与端口——
41
+ * 本次任务对象 id、存储端口、logger 等会随任务变的东西。SDK 的 TContext 通道
42
+ * (QueryOptions.context → ToolExecutionContext)穿不过 agentTool 的 typed 委派
43
+ * 边界(agentTool spawn 子会话时不转发父级 context),所以 context 在工厂调用时
44
+ * 绑定:task 的第二个参数、tools 槽位的构建参数都从它取值。
38
45
  */
39
46
  export const defineAgentTemplate = (declaration) => {
40
47
  if (!kebabCasePattern.test(declaration.id)) {
@@ -48,22 +55,35 @@ export const defineAgentTemplate = (declaration) => {
48
55
  input: declaration.input,
49
56
  output: declaration.output,
50
57
  };
58
+ /** 缺省适配:平台 prompt manifest 形状,取 systemPrompt 文件,缺文件当场抛错。 */
59
+ const defaultPromptManifest = {
60
+ manifestSchema: promptManifestSchema,
61
+ resolve: (loaded) => {
62
+ const manifest = loaded.manifest;
63
+ const systemPrompt = loaded.files.get(manifest.systemPrompt.file);
64
+ if (systemPrompt === undefined) {
65
+ throw new Error(`模板 ${id} 的 prompt 资源缺少文件:${manifest.systemPrompt.file}`);
66
+ }
67
+ return { systemPrompt, promptVersion: manifest.promptVersion };
68
+ },
69
+ };
51
70
  const loadPrompt = async (loadOptions) => {
71
+ const adapter = declaration.promptManifest ?? defaultPromptManifest;
52
72
  const promptResource = await loadActiveVersionedResource({
53
73
  baseDir: declaration.promptDir,
54
- manifestSchema: promptManifestSchema,
74
+ manifestSchema: adapter.manifestSchema,
55
75
  ...(loadOptions?.promptVersion !== undefined
56
76
  ? { versionOverride: loadOptions.promptVersion }
57
77
  : {}),
58
78
  });
59
- const systemPrompt = promptResource.files.get(promptResource.manifest.systemPrompt.file);
60
- if (systemPrompt === undefined) {
61
- throw new Error(`模板 ${id} 的 prompt 资源缺少文件:${promptResource.manifest.systemPrompt.file}`);
79
+ const resolved = adapter.resolve(promptResource);
80
+ if (resolved.systemPrompt === '') {
81
+ throw new Error(`模板 ${id} 的 prompt 资源解析出空 systemPrompt,与缺文件同等处理`);
62
82
  }
63
- return { systemPrompt, promptVersion: promptResource.manifest.promptVersion };
83
+ return resolved;
64
84
  };
65
85
  /** 四个出口共用同一份 spec 构建:prompt 加载、限额、tracer 回填完全一致。 */
66
- const buildSpec = async (options) => {
86
+ const buildSpec = async (options, context) => {
67
87
  const { systemPrompt, promptVersion } = await loadPrompt(options.promptVersion === undefined ? undefined : { promptVersion: options.promptVersion });
68
88
  // 调用方不传 tracer 时用 noop:追踪摘掉后模板照常运行。
69
89
  const tracer = options.tracer ?? createTracer({ kind: 'noop' });
@@ -89,6 +109,8 @@ export const defineAgentTemplate = (declaration) => {
89
109
  // 无领域校验要过,交付契约直接交给 SDK:声明 outputSchema 后 SDK 注入
90
110
  // submit_output 工具,没提交就收尾会以 error_missing_output 失败。
91
111
  outputSchema: declaration.output,
112
+ // 业务工具槽位:声明了才构建,依赖经 context 在创建时绑定;与 submit_output 并存。
113
+ ...(declaration.tools === undefined ? {} : { tools: declaration.tools(context) }),
92
114
  tracer,
93
115
  workspace: false,
94
116
  });
@@ -97,17 +119,17 @@ export const defineAgentTemplate = (declaration) => {
97
119
  return {
98
120
  card,
99
121
  loadPrompt,
100
- createSpec: async (options) => (await buildSpec(options)).spec,
101
- createDelegation: async (options) => {
102
- const { spec } = await buildSpec(options);
103
- return { spec, mapInput: (input) => declaration.task(input) };
122
+ createSpec: async (options, context) => (await buildSpec(options, context)).spec,
123
+ createDelegation: async (options, context) => {
124
+ const { spec } = await buildSpec(options, context);
125
+ return { spec, mapInput: (input) => declaration.task(input, context) };
104
126
  },
105
- createCapability: async (options) => {
106
- const { spec, promptVersion } = await buildSpec(options);
127
+ createCapability: async (options, context) => {
128
+ const { spec, promptVersion } = await buildSpec(options, context);
107
129
  const run = async (rawInput) => {
108
130
  // 运行期边界:typed 参数挡不住 any 与强转,这次 parse 是真实校验,不可删。
109
131
  const input = declaration.input.parse(rawInput);
110
- const response = await spec.spawn().prompt(declaration.task(input));
132
+ const response = await spec.spawn().prompt(declaration.task(input, context));
111
133
  if (response.is_error) {
112
134
  throw response.error ?? new Error(`模板 ${id} 运行失败:${response.subtype}`);
113
135
  }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { clampThinkingBudgetTokens, defineAgentTemplate, promptManifestSchema, type AgentTemplate, type AgentTemplateCard, type AgentTemplateDeclaration, type CreateTemplateAgentOptions, } from './agent_template.ts';
1
+ export { clampThinkingBudgetTokens, defineAgentTemplate, promptManifestSchema, type AgentTemplate, type AgentTemplateCard, type AgentTemplateDeclaration, type CreateTemplateAgentOptions, type PromptManifestAdapter, } from './agent_template.ts';
2
2
  export type { CapabilityDelegation } from '@onco-foundry/agent-runtime';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onco-foundry/agent-template",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -16,8 +16,8 @@
16
16
  "zod": "^4.4.3",
17
17
  "@onco-foundry/agent-runtime": "0.2.1",
18
18
  "@onco-foundry/capability-registry": "0.1.1",
19
- "@onco-foundry/resource-versioning": "0.1.1",
20
19
  "@onco-foundry/errors": "0.1.1",
20
+ "@onco-foundry/resource-versioning": "0.1.1",
21
21
  "@onco-foundry/trace-port": "0.3.1"
22
22
  },
23
23
  "publishConfig": {