@onco-foundry/agent-template 0.4.1 → 0.6.1

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,10 @@
1
+ import { type AgentTemplateCard } from './agent_template.ts';
2
+ import type { AgentVersionExecutor } from './agent_version.ts';
3
+ export type AgentSpecExecutorDeclaration<I, O, C = undefined> = {
4
+ id: string;
5
+ summary: string;
6
+ input: AgentTemplateCard<I, O>['input'];
7
+ output: AgentTemplateCard<I, O>['output'];
8
+ task: (input: I, context: C) => string;
9
+ };
10
+ export declare const createAgentSpecExecutor: <I, O, C = undefined>(declaration: AgentSpecExecutorDeclaration<I, O, C>) => AgentVersionExecutor<C>;
@@ -0,0 +1,47 @@
1
+ import { defineAgent } from 'agent-lattice';
2
+ import { createTypedAgentTool } from '@onco-foundry/agent-runtime';
3
+ import { createTracer } from '@onco-foundry/trace-port';
4
+ import { clampThinkingBudgetTokens } from './agent_template.js';
5
+ export const createAgentSpecExecutor = (declaration) => ({
6
+ card: {
7
+ name: declaration.id,
8
+ kind: 'agent',
9
+ summary: declaration.summary,
10
+ input: declaration.input,
11
+ output: declaration.output,
12
+ },
13
+ task: declaration.task,
14
+ async createSpec(input) {
15
+ const memberTools = await Promise.all(input.members.map(async (member) => createTypedAgentTool(await member.agent.createCapability({
16
+ tracer: input.tracer,
17
+ modelClient: input.modelClient,
18
+ }), {
19
+ delegation: await member.agent.createDelegation({
20
+ tracer: input.tracer,
21
+ modelClient: input.modelClient,
22
+ }),
23
+ })));
24
+ const maxTokens = input.config.limits?.maxTokens;
25
+ const thinkingBudgetTokens = input.config.limits?.thinkingBudgetTokens;
26
+ return defineAgent({
27
+ name: input.agentId.replaceAll('-', '_'),
28
+ model: input.model.model,
29
+ baseURL: input.model.baseURL,
30
+ ...(input.model.apiKey === undefined ? {} : { apiKey: input.model.apiKey }),
31
+ modelClient: input.modelClient,
32
+ systemPrompt: input.systemPrompt,
33
+ outputSchema: declaration.output,
34
+ tools: [...input.tools, ...memberTools],
35
+ ...(maxTokens === undefined ? {} : { maxTokens }),
36
+ maxTurns: input.config.limits?.maxTurns ?? 10,
37
+ thinkingConfig: thinkingBudgetTokens === undefined
38
+ ? { type: 'disabled' }
39
+ : { type: 'enabled', budgetTokens: maxTokens === undefined
40
+ ? thinkingBudgetTokens
41
+ : clampThinkingBudgetTokens(thinkingBudgetTokens, maxTokens) },
42
+ ...(input.submitOutputEndTurn === undefined ? {} : { submitOutputEndTurn: input.submitOutputEndTurn }),
43
+ tracer: input.tracer ?? createTracer({ kind: 'noop' }),
44
+ workspace: false,
45
+ });
46
+ },
47
+ });
@@ -89,8 +89,9 @@ export type AgentTemplateDeclaration<I, O, C = undefined> = {
89
89
  */
90
90
  promptStore?: VersionedResourceStore;
91
91
  /**
92
- * 可选限额。缺省:maxTokens 16384、maxTurns 10、thinking 关闭;
93
- * thinkingBudgetTokens 给了才开 thinking(按 clampThinkingBudgetTokens 钳制到 maxTokens 以内)。
92
+ * 可选限额。maxTokens 未给时由 AgentLattice 按模型端点决定默认值;
93
+ * maxTurns 缺省 10,thinking 缺省关闭。thinkingBudgetTokens 给了才开 thinking;
94
+ * 显式 maxTokens 时在这里钳制思考预算,否则交给 SDK 按实际输出上限钳制。
94
95
  */
95
96
  limits?: {
96
97
  maxTokens?: number;
@@ -15,8 +15,6 @@ export const promptManifestSchema = z.object({
15
15
  provenance: z.string().min(1),
16
16
  systemPrompt: resourceFileReferenceSchema,
17
17
  });
18
- /** 缺省输出预算:无工具的问答/判定类交付,16k 足够。 */
19
- const DEFAULT_MAX_TOKENS = 16_384;
20
18
  /** 缺省轮次上限:无工具模板一次 loop 典型路径是读入即交付。 */
21
19
  const DEFAULT_MAX_TURNS = 10;
22
20
  /**
@@ -103,7 +101,7 @@ export const defineAgentTemplate = (declaration) => {
103
101
  const tracer = options.tracer ?? createTracer({ kind: 'noop' });
104
102
  // prompt 版本在装配处还不知道,加载完版本化资源后回填进版本链。
105
103
  tracer.setVersions({ prompt: promptVersion });
106
- const maxTokens = declaration.limits?.maxTokens ?? DEFAULT_MAX_TOKENS;
104
+ const maxTokens = declaration.limits?.maxTokens;
107
105
  const maxTurns = declaration.limits?.maxTurns ?? DEFAULT_MAX_TURNS;
108
106
  const thinkingBudgetTokens = declaration.limits?.thinkingBudgetTokens;
109
107
  // workspace: false = 裸会话:不装内建工作区工具,同构简单模板不需要文件/Bash 权限面。
@@ -115,11 +113,13 @@ export const defineAgentTemplate = (declaration) => {
115
113
  apiKey: options.model.apiKey,
116
114
  modelClient: options.modelClient,
117
115
  systemPrompt,
118
- maxTokens,
116
+ ...(maxTokens === undefined ? {} : { maxTokens }),
119
117
  maxTurns,
120
118
  thinkingConfig: thinkingBudgetTokens === undefined
121
119
  ? { type: 'disabled' }
122
- : { type: 'enabled', budgetTokens: clampThinkingBudgetTokens(thinkingBudgetTokens, maxTokens) },
120
+ : { type: 'enabled', budgetTokens: maxTokens === undefined
121
+ ? thinkingBudgetTokens
122
+ : clampThinkingBudgetTokens(thinkingBudgetTokens, maxTokens) },
123
123
  // 无领域校验要过,交付契约直接交给 SDK:声明 outputSchema 后 SDK 注入
124
124
  // submit_output 工具,没提交就收尾会以 error_missing_output 失败。
125
125
  outputSchema: declaration.output,
@@ -0,0 +1,152 @@
1
+ import type { AgentSpec, ModelClient } from 'agent-lattice';
2
+ import { z } from 'zod';
3
+ import type { Capability } from '@onco-foundry/capability-registry';
4
+ import type { CapabilityDelegation } from '@onco-foundry/agent-runtime';
5
+ import type { Tracer } from '@onco-foundry/trace-port';
6
+ import type { AgentTemplateCard, TemplateToolDefinition } from './agent_template.ts';
7
+ export declare const agentResourceVersionSchema: z.ZodString;
8
+ export declare const agentVersionSchema: z.ZodObject<{
9
+ schemaVersion: z.ZodLiteral<"agent-config-v1">;
10
+ executor: z.ZodObject<{
11
+ id: z.ZodString;
12
+ version: z.ZodString;
13
+ }, z.core.$strict>;
14
+ model: z.ZodObject<{
15
+ configVersion: z.ZodString;
16
+ model: z.ZodString;
17
+ baseURL: z.ZodURL;
18
+ }, z.core.$strict>;
19
+ prompt: z.ZodObject<{
20
+ resource: z.ZodString;
21
+ version: z.ZodString;
22
+ }, z.core.$strict>;
23
+ commonPrompts: z.ZodArray<z.ZodObject<{
24
+ id: z.ZodString;
25
+ source: z.ZodEnum<{
26
+ card: "card";
27
+ shared: "shared";
28
+ }>;
29
+ version: z.ZodString;
30
+ placement: z.ZodEnum<{
31
+ after: "after";
32
+ before: "before";
33
+ }>;
34
+ order: z.ZodNumber;
35
+ basedOnVersion: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strict>>;
37
+ tools: z.ZodArray<z.ZodObject<{
38
+ type: z.ZodLiteral<"local">;
39
+ id: z.ZodString;
40
+ version: z.ZodString;
41
+ }, z.core.$strict>>;
42
+ members: z.ZodArray<z.ZodObject<{
43
+ type: z.ZodLiteral<"agent">;
44
+ id: z.ZodString;
45
+ version: z.ZodString;
46
+ }, z.core.$strict>>;
47
+ limits: z.ZodOptional<z.ZodObject<{
48
+ maxTurns: z.ZodOptional<z.ZodNumber>;
49
+ maxTokens: z.ZodOptional<z.ZodNumber>;
50
+ thinkingBudgetTokens: z.ZodOptional<z.ZodNumber>;
51
+ }, z.core.$strict>>;
52
+ }, z.core.$strict>;
53
+ export type AgentVersion = z.infer<typeof agentVersionSchema>;
54
+ export type AgentVersionExecutorReference = AgentVersion['executor'];
55
+ export type AgentVersionModel = AgentVersion['model'];
56
+ export type AgentVersionPromptReference = AgentVersion['prompt'];
57
+ export type AgentVersionCommonPromptReference = AgentVersion['commonPrompts'][number];
58
+ export type AgentVersionToolReference = AgentVersion['tools'][number];
59
+ export type AgentVersionMemberReference = AgentVersion['members'][number];
60
+ export type ResolvedAgentModel = AgentVersionModel & {
61
+ apiKey?: string;
62
+ };
63
+ export type ResolvedAgentVersion = {
64
+ version: string;
65
+ checksum: string;
66
+ executorVersion: string;
67
+ model: AgentVersionModel;
68
+ prompt: AgentVersionPromptReference & {
69
+ checksum: string;
70
+ };
71
+ systemPromptChecksum: string;
72
+ commonPrompts: Array<AgentVersionCommonPromptReference & {
73
+ checksum: string;
74
+ }>;
75
+ tools: AgentVersionToolReference[];
76
+ members: AgentVersionMemberReference[];
77
+ limits?: AgentVersion['limits'];
78
+ };
79
+ export type ResolvedAgentSnapshot = {
80
+ root: {
81
+ id: string;
82
+ version: string;
83
+ };
84
+ agents: Record<string, ResolvedAgentVersion>;
85
+ overrides?: {
86
+ promptVersion?: string;
87
+ memberPromptVersions?: Record<string, string>;
88
+ };
89
+ configurationFingerprint: string;
90
+ };
91
+ export type CreateResolvedAgentSpecOptions = {
92
+ tracer?: Tracer;
93
+ modelClient?: ModelClient;
94
+ submitOutputEndTurn?: boolean;
95
+ };
96
+ export type ResolvedAgent = {
97
+ createSpec(options?: CreateResolvedAgentSpecOptions): Promise<AgentSpec>;
98
+ createDelegation(options?: CreateResolvedAgentSpecOptions): Promise<CapabilityDelegation>;
99
+ createCapability(options?: CreateResolvedAgentSpecOptions): Promise<Capability>;
100
+ readSystemPrompt(): {
101
+ content: string;
102
+ version: string;
103
+ };
104
+ readSnapshot(): ResolvedAgentSnapshot;
105
+ };
106
+ export type ResolvedAgentMember = {
107
+ id: string;
108
+ version: string;
109
+ agent: ResolvedAgent;
110
+ };
111
+ export type AgentExecutorSpecInput<C> = {
112
+ agentId: string;
113
+ config: AgentVersion;
114
+ model: ResolvedAgentModel;
115
+ systemPrompt: string;
116
+ tools: TemplateToolDefinition[];
117
+ members: ResolvedAgentMember[];
118
+ context: C;
119
+ tracer?: Tracer;
120
+ modelClient?: ModelClient;
121
+ submitOutputEndTurn?: boolean;
122
+ };
123
+ export type AgentVersionExecutor<C = unknown> = {
124
+ readonly card: AgentTemplateCard;
125
+ readonly task: (input: any, context: C) => string;
126
+ validate?(input: {
127
+ agentId: string;
128
+ config: AgentVersion;
129
+ }): void;
130
+ createSpec(input: AgentExecutorSpecInput<C>): Promise<AgentSpec>;
131
+ };
132
+ export type AgentVersionPorts<C = unknown> = {
133
+ storeFor(agentId: string): import('@onco-foundry/resource-versioning').VersionedResourceStore;
134
+ resolveModel(reference: AgentVersionModel): Promise<{
135
+ apiKey?: string;
136
+ }>;
137
+ readPrompt(reference: AgentVersionPromptReference): Promise<{
138
+ content: string;
139
+ }>;
140
+ readCommonPrompt(reference: AgentVersionCommonPromptReference): Promise<{
141
+ content: string;
142
+ }>;
143
+ createTool(reference: AgentVersionToolReference, context: C): TemplateToolDefinition | Promise<TemplateToolDefinition>;
144
+ resolveExecutor(reference: AgentVersionExecutorReference): AgentVersionExecutor<C>;
145
+ };
146
+ export type ResolveAgentVersionInput<C = unknown> = {
147
+ agentId: string;
148
+ version?: string;
149
+ context: C;
150
+ promptVersion?: string;
151
+ memberPromptVersions?: Record<string, string>;
152
+ };
@@ -0,0 +1,49 @@
1
+ import { z } from 'zod';
2
+ export const agentResourceVersionSchema = z.string().regex(/^v[1-9]\d{0,8}$/, '版本必须形如 v15');
3
+ const executorReferenceSchema = z.object({
4
+ id: z.string().min(1),
5
+ version: agentResourceVersionSchema,
6
+ }).strict();
7
+ const promptReferenceSchema = z.object({
8
+ resource: z.string().min(1),
9
+ version: agentResourceVersionSchema,
10
+ }).strict();
11
+ const commonPromptReferenceSchema = z.object({
12
+ id: z.string().min(1),
13
+ source: z.enum(['shared', 'card']),
14
+ version: agentResourceVersionSchema,
15
+ placement: z.enum(['before', 'after']),
16
+ order: z.number().int().min(1).max(1000),
17
+ basedOnVersion: agentResourceVersionSchema.optional(),
18
+ }).strict();
19
+ const localToolReferenceSchema = z.object({
20
+ type: z.literal('local'),
21
+ id: z.string().min(1),
22
+ version: agentResourceVersionSchema,
23
+ }).strict();
24
+ const memberReferenceSchema = z.object({
25
+ type: z.literal('agent'),
26
+ id: z.string().min(1),
27
+ version: agentResourceVersionSchema,
28
+ }).strict();
29
+ export const agentVersionSchema = z.object({
30
+ schemaVersion: z.literal('agent-config-v1'),
31
+ executor: executorReferenceSchema,
32
+ model: z.object({
33
+ configVersion: z.string().min(1),
34
+ model: z.string().min(1),
35
+ baseURL: z.url().refine(value => {
36
+ const url = new URL(value);
37
+ return url.username === '' && url.password === '';
38
+ }, '模型 baseURL 不能包含凭据'),
39
+ }).strict(),
40
+ prompt: promptReferenceSchema,
41
+ commonPrompts: z.array(commonPromptReferenceSchema),
42
+ tools: z.array(localToolReferenceSchema),
43
+ members: z.array(memberReferenceSchema),
44
+ limits: z.object({
45
+ maxTurns: z.number().int().positive().optional(),
46
+ maxTokens: z.number().int().min(2).optional(),
47
+ thinkingBudgetTokens: z.number().int().positive().optional(),
48
+ }).strict().optional(),
49
+ }).strict();
@@ -0,0 +1,4 @@
1
+ import { type AgentVersionPorts, type ResolveAgentVersionInput, type ResolvedAgent } from './agent_version.ts';
2
+ export declare const createAgentVersionResolver: <C>(ports: AgentVersionPorts<C>) => {
3
+ resolve: (input: ResolveAgentVersionInput<C>) => Promise<ResolvedAgent>;
4
+ };
@@ -0,0 +1,188 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { AppError } from '@onco-foundry/errors';
3
+ import { defineCapability } from '@onco-foundry/capability-registry';
4
+ import { loadActiveVersionedResource, versionedFilesManifestSchema, } from '@onco-foundry/resource-versioning';
5
+ import { agentVersionSchema, } from './agent_version.js';
6
+ const checksum = (content) => createHash('sha256').update(content).digest('hex');
7
+ export const createAgentVersionResolver = (ports) => {
8
+ const loadConfig = async (agentId, version) => {
9
+ const resource = await loadActiveVersionedResource({
10
+ store: ports.storeFor(agentId),
11
+ manifestSchema: versionedFilesManifestSchema,
12
+ ...(version === undefined ? {} : { versionOverride: version }),
13
+ });
14
+ const raw = resource.files.get('agent.json');
15
+ if (raw === undefined)
16
+ throw new AppError(`智能体 ${agentId} 的 ${resource.version} 缺少 agent.json`);
17
+ return {
18
+ config: agentVersionSchema.parse(JSON.parse(raw)),
19
+ version: resource.version,
20
+ configChecksum: checksum(raw),
21
+ };
22
+ };
23
+ const resolve = async (input) => {
24
+ const records = new Map();
25
+ const visiting = new Set();
26
+ const snapshotFor = (rootId) => {
27
+ const agents = {};
28
+ const collect = (id) => {
29
+ if (agents[id] !== undefined)
30
+ return;
31
+ const record = records.get(id);
32
+ if (record === undefined)
33
+ throw new AppError(`智能体 ${id} 的解析记录不存在`);
34
+ agents[id] = {
35
+ version: record.version,
36
+ checksum: record.configChecksum,
37
+ executorVersion: record.config.executor.version,
38
+ model: { ...record.config.model },
39
+ prompt: { ...record.prompt },
40
+ systemPromptChecksum: record.systemPromptChecksum,
41
+ commonPrompts: record.commonPrompts.map(({ content: _content, ...part }) => ({ ...part })),
42
+ tools: record.config.tools.map(tool => ({ ...tool })),
43
+ members: record.config.members.map(member => ({ ...member })),
44
+ ...(record.config.limits === undefined ? {} : { limits: { ...record.config.limits } }),
45
+ };
46
+ for (const member of record.config.members)
47
+ collect(member.id);
48
+ };
49
+ collect(rootId);
50
+ const orderedAgents = Object.fromEntries(Object.keys(agents).sort().map(id => [id, agents[id]]));
51
+ const root = records.get(rootId);
52
+ if (root === undefined)
53
+ throw new AppError(`智能体 ${rootId} 的解析记录不存在`);
54
+ const overrides = input.promptVersion === undefined && input.memberPromptVersions === undefined
55
+ ? undefined
56
+ : {
57
+ ...(input.promptVersion === undefined ? {} : { promptVersion: input.promptVersion }),
58
+ ...(input.memberPromptVersions === undefined ? {} : { memberPromptVersions: { ...input.memberPromptVersions } }),
59
+ };
60
+ const configurationFingerprint = checksum(JSON.stringify({
61
+ root: { id: rootId, version: root.version },
62
+ agents: orderedAgents,
63
+ ...(overrides === undefined ? {} : { overrides }),
64
+ }));
65
+ return {
66
+ root: { id: rootId, version: root.version },
67
+ agents: orderedAgents,
68
+ ...(overrides === undefined ? {} : { overrides }),
69
+ configurationFingerprint,
70
+ };
71
+ };
72
+ const visit = async (agentId, version) => {
73
+ if (visiting.has(agentId))
74
+ throw new AppError(`智能体版本图存在循环引用:${agentId}`);
75
+ const loaded = await loadConfig(agentId, version);
76
+ const existing = records.get(agentId);
77
+ if (existing !== undefined) {
78
+ if (existing.version !== loaded.version) {
79
+ throw new AppError(`智能体 ${agentId} 在同一版本图中引用了不同版本:${existing.version}、${loaded.version}`);
80
+ }
81
+ if (existing.agent !== undefined)
82
+ return existing.agent;
83
+ }
84
+ visiting.add(agentId);
85
+ try {
86
+ const executor = ports.resolveExecutor(loaded.config.executor);
87
+ executor.validate?.({ agentId, config: loaded.config });
88
+ const promptVersion = agentId === input.agentId
89
+ ? input.promptVersion
90
+ : input.memberPromptVersions?.[agentId];
91
+ const promptReference = {
92
+ ...loaded.config.prompt,
93
+ ...(promptVersion === undefined ? {} : { version: agentVersionSchema.shape.prompt.shape.version.parse(promptVersion) }),
94
+ };
95
+ const [prompt, modelCredential] = await Promise.all([
96
+ ports.readPrompt(promptReference),
97
+ ports.resolveModel(loaded.config.model),
98
+ ]);
99
+ const commonPrompts = await Promise.all(loaded.config.commonPrompts.map(async (reference) => {
100
+ const { content } = await ports.readCommonPrompt(reference);
101
+ return { ...reference, content, checksum: checksum(content) };
102
+ }));
103
+ const ordered = [...commonPrompts].sort((a, b) => a.placement === b.placement
104
+ ? a.order - b.order || a.id.localeCompare(b.id)
105
+ : a.placement === 'before' ? -1 : 1);
106
+ const before = ordered.filter(part => part.placement === 'before');
107
+ const after = ordered.filter(part => part.placement === 'after');
108
+ const systemPrompt = [
109
+ ...before.map(part => part.content),
110
+ prompt.content,
111
+ ...after.map(part => part.content),
112
+ ].join('\n\n');
113
+ const record = {
114
+ id: agentId,
115
+ version: loaded.version,
116
+ configChecksum: loaded.configChecksum,
117
+ config: loaded.config,
118
+ executor,
119
+ model: { ...loaded.config.model, ...modelCredential },
120
+ prompt: { ...promptReference, checksum: checksum(prompt.content) },
121
+ commonPrompts,
122
+ systemPrompt,
123
+ systemPromptChecksum: checksum(systemPrompt),
124
+ };
125
+ records.set(agentId, record);
126
+ const createSpec = async (options = {}) => {
127
+ options.tracer?.setVersions({
128
+ template: `${agentId}@${record.version}`,
129
+ prompt: `${record.prompt.resource}/${record.prompt.version}`,
130
+ model: record.model.model,
131
+ });
132
+ const tools = await Promise.all(record.config.tools.map(reference => ports.createTool(reference, input.context)));
133
+ return await record.executor.createSpec({
134
+ agentId,
135
+ config: record.config,
136
+ model: record.model,
137
+ systemPrompt: record.systemPrompt,
138
+ tools,
139
+ members: await Promise.all(record.config.members.map(async (member) => ({
140
+ id: member.id,
141
+ version: member.version,
142
+ agent: await visit(member.id, member.version),
143
+ }))),
144
+ context: input.context,
145
+ ...(options.tracer === undefined ? {} : { tracer: options.tracer }),
146
+ ...(options.modelClient === undefined ? {} : { modelClient: options.modelClient }),
147
+ ...(options.submitOutputEndTurn === undefined ? {} : { submitOutputEndTurn: options.submitOutputEndTurn }),
148
+ });
149
+ };
150
+ const agent = {
151
+ createSpec,
152
+ createDelegation: async (options) => ({
153
+ spec: await createSpec(options),
154
+ mapInput: rawInput => record.executor.task(rawInput, input.context),
155
+ }),
156
+ createCapability: async (options) => {
157
+ const spec = await createSpec(options);
158
+ return defineCapability({
159
+ ...record.executor.card,
160
+ version: record.version,
161
+ run: async (rawInput) => {
162
+ const parsedInput = record.executor.card.input.parse(rawInput);
163
+ const response = await spec.spawn().prompt(record.executor.task(parsedInput, input.context));
164
+ if (response.is_error)
165
+ throw response.error ?? new Error(`智能体 ${agentId} 运行失败:${response.subtype}`);
166
+ if (response.structuredResult === undefined) {
167
+ throw new Error(`智能体 ${agentId} 的模型未提交结构化交付,本次运行不算完成`);
168
+ }
169
+ return record.executor.card.output.parse(response.structuredResult);
170
+ },
171
+ });
172
+ },
173
+ readSystemPrompt: () => ({ content: record.systemPrompt, version: record.prompt.version }),
174
+ readSnapshot: () => structuredClone(snapshotFor(agentId)),
175
+ };
176
+ record.agent = agent;
177
+ for (const member of record.config.members)
178
+ await visit(member.id, member.version);
179
+ return agent;
180
+ }
181
+ finally {
182
+ visiting.delete(agentId);
183
+ }
184
+ };
185
+ return await visit(input.agentId, input.version);
186
+ };
187
+ return { resolve };
188
+ };
@@ -0,0 +1,12 @@
1
+ import type { TemplateToolDefinition } from './agent_template.ts';
2
+ import type { AgentVersion, AgentVersionCommonPromptReference, AgentVersionExecutor, AgentVersionPorts, AgentVersionPromptReference } from './agent_version.ts';
3
+ export declare const createFakeAgentVersionPorts: <C>(options: {
4
+ executors: Record<string, AgentVersionExecutor<C>>;
5
+ modelApiKey?: string;
6
+ tools?: Record<string, (context: C) => TemplateToolDefinition>;
7
+ }) => AgentVersionPorts<C> & {
8
+ writeAgentVersion(agentId: string, version: string, config: AgentVersion, activate?: boolean): Promise<void>;
9
+ activateAgentVersion(agentId: string, version: string): Promise<void>;
10
+ setPrompt(reference: AgentVersionPromptReference, content: string): void;
11
+ setCommonPrompt(reference: AgentVersionCommonPromptReference, content: string): void;
12
+ };
@@ -0,0 +1,65 @@
1
+ import { AppError } from '@onco-foundry/errors';
2
+ import { activateVersion, createFakeVersionedResourceStore, createVersionedResource, } from '@onco-foundry/resource-versioning';
3
+ const promptKey = (reference) => `${reference.resource}@${reference.version}`;
4
+ const commonPromptKey = (reference) => `${reference.source}:${reference.id}@${reference.version}`;
5
+ const executorKey = (reference) => `${reference.id}@${reference.version}`;
6
+ const toolKey = (reference) => `${reference.id}@${reference.version}`;
7
+ export const createFakeAgentVersionPorts = (options) => {
8
+ const stores = new Map();
9
+ const prompts = new Map();
10
+ const commonPrompts = new Map();
11
+ const ports = {
12
+ storeFor(agentId) {
13
+ let store = stores.get(agentId);
14
+ if (store === undefined) {
15
+ store = createFakeVersionedResourceStore();
16
+ stores.set(agentId, store);
17
+ }
18
+ return store;
19
+ },
20
+ resolveModel: async () => options.modelApiKey === undefined ? {} : { apiKey: options.modelApiKey },
21
+ readPrompt: async (reference) => {
22
+ const content = prompts.get(promptKey(reference));
23
+ if (content === undefined)
24
+ throw new AppError(`fake prompt 不存在:${promptKey(reference)}`);
25
+ return { content };
26
+ },
27
+ readCommonPrompt: async (reference) => {
28
+ const content = commonPrompts.get(commonPromptKey(reference));
29
+ if (content === undefined)
30
+ throw new AppError(`fake 共同 prompt 不存在:${commonPromptKey(reference)}`);
31
+ return { content };
32
+ },
33
+ createTool(reference, context) {
34
+ const create = options.tools?.[toolKey(reference)];
35
+ if (create === undefined)
36
+ throw new AppError(`fake 工具不存在:${toolKey(reference)}`);
37
+ return create(context);
38
+ },
39
+ resolveExecutor(reference) {
40
+ const executor = options.executors[executorKey(reference)];
41
+ if (executor === undefined)
42
+ throw new AppError(`fake 执行器不存在:${executorKey(reference)}`);
43
+ return executor;
44
+ },
45
+ async writeAgentVersion(agentId, version, config, activate = true) {
46
+ await createVersionedResource({
47
+ store: ports.storeFor(agentId),
48
+ version,
49
+ files: { 'agent.json': JSON.stringify(config) },
50
+ });
51
+ if (activate)
52
+ await ports.activateAgentVersion(agentId, version);
53
+ },
54
+ activateAgentVersion: async (agentId, version) => {
55
+ await activateVersion({ store: ports.storeFor(agentId), version });
56
+ },
57
+ setPrompt(reference, content) {
58
+ prompts.set(promptKey(reference), content);
59
+ },
60
+ setCommonPrompt(reference, content) {
61
+ commonPrompts.set(commonPromptKey(reference), content);
62
+ },
63
+ };
64
+ return ports;
65
+ };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,6 @@
1
1
  export { clampThinkingBudgetTokens, defineAgentTemplate, promptManifestSchema, type AgentTemplate, type AgentTemplateCard, type AgentTemplateDeclaration, type CreateTemplateAgentOptions, type PromptManifestAdapter, type TemplateToolDefinition, } from './agent_template.ts';
2
2
  export type { CapabilityDelegation } from '@onco-foundry/agent-runtime';
3
+ export { createAgentSpecExecutor, type AgentSpecExecutorDeclaration } from './agent_spec_executor.ts';
4
+ export { agentResourceVersionSchema, agentVersionSchema, type AgentVersion, type AgentVersionCommonPromptReference, type AgentVersionExecutor, type AgentVersionExecutorReference, type AgentVersionMemberReference, type AgentVersionModel, type AgentVersionPorts, type AgentVersionPromptReference, type AgentVersionToolReference, type CreateResolvedAgentSpecOptions, type ResolveAgentVersionInput, type ResolvedAgent, type ResolvedAgentMember, type ResolvedAgentModel, type ResolvedAgentSnapshot, type ResolvedAgentVersion, } from './agent_version.ts';
5
+ export { createAgentVersionResolver } from './agent_version_resolver.ts';
6
+ export { createFakeAgentVersionPorts } from './fake_agent_version_ports.ts';
package/dist/index.js CHANGED
@@ -1 +1,5 @@
1
1
  export { clampThinkingBudgetTokens, defineAgentTemplate, promptManifestSchema, } from './agent_template.js';
2
+ export { createAgentSpecExecutor } from './agent_spec_executor.js';
3
+ export { agentResourceVersionSchema, agentVersionSchema, } from './agent_version.js';
4
+ export { createAgentVersionResolver } from './agent_version_resolver.js';
5
+ export { createFakeAgentVersionPorts } from './fake_agent_version_ports.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onco-foundry/agent-template",
3
- "version": "0.4.1",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -15,10 +15,10 @@
15
15
  "agent-lattice": "0.26.0",
16
16
  "zod": "^4.4.3",
17
17
  "@onco-foundry/agent-runtime": "0.3.0",
18
- "@onco-foundry/errors": "0.1.1",
19
18
  "@onco-foundry/capability-registry": "0.1.1",
19
+ "@onco-foundry/resource-versioning": "0.3.0",
20
20
  "@onco-foundry/trace-port": "0.3.3",
21
- "@onco-foundry/resource-versioning": "0.3.0"
21
+ "@onco-foundry/errors": "0.1.1"
22
22
  },
23
23
  "publishConfig": {
24
24
  "access": "public"