@gt-fe/eap-runtime 0.0.32 → 0.0.33

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.
@@ -27,7 +27,7 @@ import { classifyRuntimeError } from '../../utils/http-error.js';
27
27
  import { DEFAULT_GRAPH_TIMEOUT_MS } from '../../common/types.js';
28
28
  import { resolveTaskTimeoutMs } from '../../task/resolve-task-timeout.js';
29
29
  import { runWithExecutionTrace } from '../../graph/execution-trace-context.js';
30
- import { resolveAgentSystemPromptFromLoader } from '../../registry/graph-loader.js';
30
+ import { resolveAgentDisplayNameFromLoader, resolveAgentSystemPromptFromLoader, } from '../../registry/graph-loader.js';
31
31
  import { toLoadedToolMap } from '../../tool/loaded-tool-definition.js';
32
32
  import { toLoadedSkillMap } from '../../tool/system-prompt-builder.js';
33
33
  import { assembleLoadedTools } from '../../tool/harness-primitives.js';
@@ -204,6 +204,7 @@ export class InvokeOrchestrator {
204
204
  ? (await this.graphLoader.resolveAgentDir(agentCode, req.agentVersion)) ?? undefined
205
205
  : undefined;
206
206
  const agentSystemPrompt = await resolveAgentSystemPromptFromLoader(this.graphLoader, agentCode, req.agentVersion);
207
+ const agentName = await resolveAgentDisplayNameFromLoader(this.graphLoader, agentCode, req.agentVersion);
207
208
  // 模型上下文:Checkpoint 已有 messages 则压它;压成功用 __set 写回最新 Checkpoint。Message 库不改。
208
209
  const facing = await loadModelFacingHistory({
209
210
  sessionHistory: messageRecordsToGraphMessages(sessionContext.messages),
@@ -261,6 +262,7 @@ export class InvokeOrchestrator {
261
262
  promptRoots,
262
263
  agentDir,
263
264
  agentSystemPrompt,
265
+ agentName,
264
266
  traceId: resolveTraceId(req),
265
267
  traceCollector: this.traceCollector,
266
268
  abortSignal,
@@ -31,7 +31,7 @@ import { SSEEmitter } from '../../sse/sse-emitter.js';
31
31
  import { resolveExecutionContext } from '../../governance/governance-client.js';
32
32
  import { resolveSkillInputFromInvokeInput } from '../../registry/skill-io-guard.js';
33
33
  import { ErrorCodes } from '@gt-fe/eap-contracts';
34
- import { resolveAgentSystemPromptFromLoader } from '../../registry/graph-loader.js';
34
+ import { resolveAgentDisplayNameFromLoader, resolveAgentSystemPromptFromLoader, } from '../../registry/graph-loader.js';
35
35
  import { classifyRuntimeError } from '../../utils/http-error.js';
36
36
  import { toLoadedToolMap } from '../../tool/loaded-tool-definition.js';
37
37
  import { toLoadedSkillMap } from '../../tool/system-prompt-builder.js';
@@ -222,6 +222,7 @@ export class StreamOrchestrator {
222
222
  ? (await this.graphLoader.resolveAgentDir(agentCode, req.agentVersion)) ?? undefined
223
223
  : undefined;
224
224
  const agentSystemPrompt = await resolveAgentSystemPromptFromLoader(this.graphLoader, agentCode, req.agentVersion);
225
+ const agentName = await resolveAgentDisplayNameFromLoader(this.graphLoader, agentCode, req.agentVersion);
225
226
  // 模型上下文:Checkpoint 已有 messages 则压它;压成功用 __set 写回最新 Checkpoint。Message 库不改。
226
227
  const facing = await loadModelFacingHistory({
227
228
  sessionHistory: messageRecordsToGraphMessages(sessionContext.messages),
@@ -293,6 +294,7 @@ export class StreamOrchestrator {
293
294
  promptRoots,
294
295
  agentDir,
295
296
  agentSystemPrompt,
297
+ agentName,
296
298
  traceId: resolveTraceId(req),
297
299
  traceCollector: this.traceCollector,
298
300
  abortSignal,
@@ -127,7 +127,6 @@ export declare class LangGraphAdapter implements IStateGraphEngine {
127
127
  private createNodeFunction;
128
128
  private createNodeFunctionBody;
129
129
  private createSkillBindNodeFunction;
130
- private buildSkillCatalog;
131
130
  private createToolNodeFunction;
132
131
  private createLLMNodeFunction;
133
132
  /**
@@ -23,7 +23,7 @@ import { ToolResultInjector } from '../../tool/tool-result-injector.js';
23
23
  import { fileArtifactFromToolOutput } from '../../tool/file-artifact.js';
24
24
  import { EchoLLMProvider } from '../../providers/echo-llm-provider.js';
25
25
  import { ConditionEvaluator } from '../condition-evaluator.js';
26
- import { SystemPromptBuilder, buildToolCatalog, loadedToolsToApiTools, resolveLlmPromptInputs } from '../../tool/system-prompt-builder.js';
26
+ import { SystemPromptBuilder, buildSkillCatalog, buildToolCatalog, loadedToolsToApiTools, resolveLlmPromptInputs, spokenName } from '../../tool/system-prompt-builder.js';
27
27
  import { resolveJailFromState, resolveJailRoots } from '../../tool/harness-primitives.js';
28
28
  import os from 'node:os';
29
29
  import { bindSelectedSkill } from '../nodes/skill-bind-node.js';
@@ -306,6 +306,7 @@ export class LangGraphAdapter {
306
306
  alreadyInSkillSpan: progress.inSkillSubgraph,
307
307
  });
308
308
  if (catalogSkill) {
309
+ const skillName = spokenName(progress.skillName, catalogSkill.skillId) ?? catalogSkill.skillId;
309
310
  stream.sink({
310
311
  type: 'skill.started',
311
312
  taskId,
@@ -313,7 +314,7 @@ export class LangGraphAdapter {
313
314
  timestamp,
314
315
  payload: {
315
316
  skillId: catalogSkill.skillId,
316
- skillName: progress.skillName || catalogSkill.skillId,
317
+ skillName,
317
318
  path: catalogSkill.path,
318
319
  ...(progress.skillSpace ? { skillSpace: progress.skillSpace } : {}),
319
320
  ...(progress.skillVersion ? { skillVersion: progress.skillVersion } : {}),
@@ -326,7 +327,7 @@ export class LangGraphAdapter {
326
327
  timestamp,
327
328
  payload: {
328
329
  skillId: catalogSkill.skillId,
329
- skillName: catalogSkill.skillId,
330
+ skillName,
330
331
  },
331
332
  });
332
333
  }
@@ -460,6 +461,7 @@ export class LangGraphAdapter {
460
461
  // agentId 已废弃:channel 保留仅为旧 Checkpoint 反序列化兼容,新代码只写 agentCode
461
462
  agentId: ephemeral(''),
462
463
  agentCode: ephemeral(''),
464
+ agentName: ephemeral(undefined),
463
465
  agentVersion: ephemeral(undefined),
464
466
  delegationToken: ephemeral(''),
465
467
  correlationId: ephemeral(''),
@@ -856,7 +858,7 @@ export class LangGraphAdapter {
856
858
  correlationId: undefined,
857
859
  timestamp: new Date().toISOString(),
858
860
  payload: {
859
- skillName: patch.skillName || patch.activatedSkill,
861
+ skillName: spokenName(patch.skillName, patch.activatedSkill) ?? patch.activatedSkill,
860
862
  skillId: patch.activatedSkill,
861
863
  confidence: 1,
862
864
  },
@@ -898,20 +900,6 @@ export class LangGraphAdapter {
898
900
  };
899
901
  };
900
902
  }
901
- buildSkillCatalog(defs) {
902
- if (!defs)
903
- return undefined;
904
- const rows = Object.values(defs).map((skill) => {
905
- const desc = (skill.description ?? '').replace(/\s+/g, ' ').trim();
906
- const entry = skill.entryFile ?? (skill.bundlePath ? `${skill.bundlePath}/SKILL.md` : '');
907
- const title = skill.name && skill.name !== skill.skillId ? `${skill.skillId}(${skill.name})` : skill.skillId;
908
- const pathLine = entry ? `\n SKILL.md: ${entry}` : '';
909
- return `- **${title}**${desc ? `:${desc}` : ''}${pathLine}`;
910
- });
911
- if (rows.length === 0)
912
- return undefined;
913
- return `# 可用技能\n要用某个技能时,调用 read_file 读取其 SKILL.md。脚本和参考文档默认在同一目录。\n${rows.join('\n')}`;
914
- }
915
903
  createToolNodeFunction(node) {
916
904
  const toolName = node.config?.['tool'] ?? node.id;
917
905
  const defaultArgs = node.config?.['arguments'] ?? {};
@@ -1061,6 +1049,7 @@ export class LangGraphAdapter {
1061
1049
  const resolvedPrompt = resolveGraphPrompt(baseConfig.systemPrompt, promptRoots);
1062
1050
  const loadedToolsBase = state['loadedTools'];
1063
1051
  const agentCode = typeof state['agentCode'] === 'string' ? state['agentCode'] : undefined;
1052
+ const agentName = typeof state['agentName'] === 'string' ? state['agentName'] : undefined;
1064
1053
  const skillDefs = state['skillDefinitions'];
1065
1054
  const execCtx = state['executionContext'];
1066
1055
  const userId = (typeof execCtx?.userId === 'string' && execCtx.userId) || state['userId'];
@@ -1092,7 +1081,7 @@ export class LangGraphAdapter {
1092
1081
  const toolNames = loadedTools ? Object.keys(loadedTools) : [];
1093
1082
  console.log(`[LLM-DEBUG] node=${node.id} loadedTools=${toolNames.length}:`, toolNames);
1094
1083
  }
1095
- const catalog = includeSkillCatalog ? this.buildSkillCatalog(skillDefs) : undefined;
1084
+ const catalog = includeSkillCatalog ? buildSkillCatalog(skillDefs) : undefined;
1096
1085
  const toolCatalog = disableTools ? undefined : buildToolCatalog(loadedTools);
1097
1086
  const jail = resolveJailFromState({
1098
1087
  agentDir: state['agentDir'],
@@ -1123,6 +1112,7 @@ export class LangGraphAdapter {
1123
1112
  nodePrompt: promptInputs.nodePrompt,
1124
1113
  skillCatalog: catalog,
1125
1114
  toolCatalog,
1115
+ agentName,
1126
1116
  agentCode,
1127
1117
  userId,
1128
1118
  workingDirectory,
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import { classifySkillFile, classifySkillSpace, isReadTool, } from './skill-read.js';
12
12
  import { completeGraphSpan, startGraphSpan } from '../trace-span.js';
13
+ import { spokenName } from '../../tool/system-prompt-builder.js';
13
14
  function declaredSkillVersion(skillId, version) {
14
15
  const raw = version?.trim();
15
16
  if (!raw || raw === skillId)
@@ -27,9 +28,10 @@ export function skillTraceIdentity(state, skillId, fallbackPath) {
27
28
  const bundle = info?.bundlePath || fallbackPath;
28
29
  const skillSpace = bundle ? classifySkillSpace(bundle, { agentDir, userId }) : undefined;
29
30
  const skillVersion = declaredSkillVersion(skillId, info?.version);
31
+ const skillName = spokenName(info?.name, undefined);
30
32
  return {
31
33
  skillId,
32
- ...(info?.name ? { skillName: info.name } : {}),
34
+ ...(skillName ? { skillName } : {}),
33
35
  ...(skillVersion ? { skillVersion } : {}),
34
36
  ...(skillSpace ? { skillSpace } : {}),
35
37
  };
@@ -39,6 +41,7 @@ export function skillSpanFields(identity, extra) {
39
41
  ...(identity.skillVersion ? { version: identity.skillVersion } : {}),
40
42
  input: {
41
43
  skillId: identity.skillId,
44
+ ...(identity.skillName ? { skillName: identity.skillName } : {}),
42
45
  ...(identity.skillSpace ? { skillSpace: identity.skillSpace } : {}),
43
46
  ...(extra?.path ? { path: extra.path } : {}),
44
47
  ...(extra?.source ? { source: extra.source } : {}),
@@ -13,7 +13,7 @@ import { LangGraphAdapter } from './langgraph.adapter.js';
13
13
  import { assertSkillGraphHasNoSubgraphNodes } from './graph-nesting.js';
14
14
  import { resolveExecutionTrace, warnTraceSpanFailure, } from '../execution-trace-context.js';
15
15
  import { skillSpanFields, skillTraceIdentity } from './skill-entry-span.js';
16
- import { filterLoadedToolsForSkill, } from '../../tool/system-prompt-builder.js';
16
+ import { filterLoadedToolsForSkill, spokenName, } from '../../tool/system-prompt-builder.js';
17
17
  import { unwrapHitlPaused } from '../hitl/hitl-handler.js';
18
18
  import { pickContextFields } from '../../token/context-window.js';
19
19
  import { assertSkillIoIfEnabled, coerceSkillInputFromMessages, } from '../../registry/skill-io-guard.js';
@@ -65,11 +65,14 @@ export class SubGraphCompiler {
65
65
  ? state['skillSpanId']
66
66
  : '';
67
67
  const resuming = Boolean(existingSpanId);
68
+ const identity = skillTraceIdentity(state, resolvedSkillId);
69
+ const spanName = resolvedSkillId || dsl.name || 'skill';
70
+ const skillName = spokenName(identity.skillName, resolvedSkillId) ?? spanName;
68
71
  const auditCtx = resuming
69
72
  ? undefined
70
73
  : this.skillAuditRecorder?.startInvocation({
71
74
  skillId: resolvedSkillId,
72
- skillName: dsl.name,
75
+ skillName,
73
76
  agentCode: (state['agentCode'] ?? state['agentId']),
74
77
  userId: state['userId'] ?? '',
75
78
  taskId: state['taskId'],
@@ -77,8 +80,6 @@ export class SubGraphCompiler {
77
80
  });
78
81
  // 用父图这次调用上的 collector;内层 invoke 只补 collector/traceId,沿用外层流式袋。
79
82
  const { collector: traceCollector, traceId } = resolveExecutionTrace(state);
80
- const skillName = dsl.name || resolvedSkillId;
81
- const identity = skillTraceIdentity(state, resolvedSkillId);
82
83
  if (!resuming) {
83
84
  adapter.emitStreamEvent({
84
85
  type: 'skill.started',
@@ -87,7 +88,7 @@ export class SubGraphCompiler {
87
88
  timestamp: new Date().toISOString(),
88
89
  payload: {
89
90
  skillId: resolvedSkillId,
90
- skillName: identity.skillName || skillName,
91
+ skillName,
91
92
  ...(identity.skillSpace ? { skillSpace: identity.skillSpace } : {}),
92
93
  ...(identity.skillVersion ? { skillVersion: identity.skillVersion } : {}),
93
94
  },
@@ -99,7 +100,7 @@ export class SubGraphCompiler {
99
100
  const fields = skillSpanFields(identity, { source: 'subgraph' });
100
101
  skillSpanId = await traceCollector.createNode({
101
102
  traceId,
102
- name: resolvedSkillId || dsl.name || 'skill',
103
+ name: spanName,
103
104
  type: 'skill',
104
105
  agentCode: state['agentCode'] ?? state['agentId'],
105
106
  ...(fields.version ? { version: fields.version } : {}),
@@ -111,7 +112,7 @@ export class SubGraphCompiler {
111
112
  });
112
113
  }
113
114
  catch (err) {
114
- warnTraceSpanFailure('createNode', { type: 'skill', name: resolvedSkillId || dsl.name || 'skill', traceId }, err);
115
+ warnTraceSpanFailure('createNode', { type: 'skill', name: spanName, traceId }, err);
115
116
  skillSpanId = null;
116
117
  }
117
118
  }
@@ -154,6 +155,7 @@ export class SubGraphCompiler {
154
155
  userId,
155
156
  delegationToken,
156
157
  agentCode,
158
+ agentName: typeof state['agentName'] === 'string' ? state['agentName'] : undefined,
157
159
  taskId: state['taskId'],
158
160
  correlationId: state['correlationId'],
159
161
  sessionId: state['sessionId'],
@@ -194,7 +196,7 @@ export class SubGraphCompiler {
194
196
  });
195
197
  }
196
198
  catch (err) {
197
- warnTraceSpanFailure('completeNode', { type: 'skill', name: skillName, traceId, spanId: skillSpanId }, err);
199
+ warnTraceSpanFailure('completeNode', { type: 'skill', name: spanName, traceId, spanId: skillSpanId }, err);
198
200
  }
199
201
  }
200
202
  // 4. 只回写子图本步新增消息(含内部 tool 回合),禁止把入口历史再 append
@@ -269,7 +271,7 @@ export class SubGraphCompiler {
269
271
  });
270
272
  }
271
273
  catch (completeErr) {
272
- warnTraceSpanFailure('completeNode', { type: 'skill', name: skillName, traceId, spanId: skillSpanId }, completeErr);
274
+ warnTraceSpanFailure('completeNode', { type: 'skill', name: spanName, traceId, spanId: skillSpanId }, completeErr);
273
275
  }
274
276
  }
275
277
  adapter.emitStreamEvent({
@@ -181,6 +181,8 @@ export interface GraphState {
181
181
  agentId?: string;
182
182
  /** Agent 对外主键 */
183
183
  agentCode?: string;
184
+ /** Agent 展示名(manifest.name);身份段对用户说话用,缺省回退 agentCode */
185
+ agentName?: string;
184
186
  /** Hosting 路由选定的预装版本(AR-3b;写入 Checkpoint 供 HITL/Fork 恢复) */
185
187
  agentVersion?: string;
186
188
  correlationId?: string;
@@ -2,7 +2,7 @@
2
2
  * 可选图胶水:把 silent LLM 的结构化输出写成 skillRoute / activatedSkill。
3
3
  * 不是 Graph 节点类型。技能正文走短目录 + read_file,不灌 system。
4
4
  */
5
- import type { LoadedSkillInfo, LoadedSkillMap } from '../../tool/system-prompt-builder.js';
5
+ import { type LoadedSkillInfo, type LoadedSkillMap } from '../../tool/system-prompt-builder.js';
6
6
  export type SkillRoute = 'skill' | 'clarify' | 'none';
7
7
  export interface SkillBindPatch {
8
8
  skillRoute: SkillRoute;
@@ -1,3 +1,8 @@
1
+ /**
2
+ * 可选图胶水:把 silent LLM 的结构化输出写成 skillRoute / activatedSkill。
3
+ * 不是 Graph 节点类型。技能正文走短目录 + read_file,不灌 system。
4
+ */
5
+ import { spokenName } from '../../tool/system-prompt-builder.js';
1
6
  function lastAssistantText(messages) {
2
7
  for (let i = messages.length - 1; i >= 0; i--) {
3
8
  const msg = messages[i];
@@ -89,7 +94,7 @@ export function bindSelectedSkill(state) {
89
94
  return {
90
95
  skillRoute: 'skill',
91
96
  activatedSkill: skill.skillId,
92
- skillName: skill.name || skill.skillId,
97
+ skillName: spokenName(skill.name, skill.skillId),
93
98
  skillInput: params,
94
99
  messages: nextMessages(),
95
100
  };
@@ -203,6 +203,7 @@ export class ToolNode {
203
203
  correlationId: req.correlationId,
204
204
  skillId,
205
205
  ...(identity.toolset ? { toolset: identity.toolset } : {}),
206
+ ...(identity.toolDisplayName ? { toolDisplayName: identity.toolDisplayName } : {}),
206
207
  },
207
208
  });
208
209
  }
@@ -20,8 +20,13 @@ export interface LoadAgentOptions {
20
20
  export declare function resolveAgentSystemPromptFromLoader(loader: {
21
21
  resolveAgentSystemPrompt?: (agentCode: string, version?: string) => Promise<string | undefined>;
22
22
  } | undefined, agentCode: string, version?: string): Promise<string | undefined>;
23
+ export declare function resolveAgentDisplayNameFromLoader(loader: {
24
+ resolveAgentDisplayName?: (agentCode: string, version?: string) => Promise<string | undefined>;
25
+ } | undefined, agentCode: string, version?: string): Promise<string | undefined>;
23
26
  /** manifest.prompts.system;空白视为缺省。 */
24
27
  export declare function extractAgentSystemPrompt(manifest: unknown): string | undefined;
28
+ /** manifest.name;空白视为缺省。身份段对用户说话用,不当路由键。 */
29
+ export declare function extractAgentDisplayName(manifest: unknown): string | undefined;
25
30
  export interface GraphLoaderConfig {
26
31
  registryClient?: AgentRegistryClient;
27
32
  deploymentContext?: DeploymentContext;
@@ -116,6 +121,12 @@ export declare class GraphLoader {
116
121
  * 每轮 execute/stream 注入 GraphState.agentSystemPrompt;不写进节点 config。
117
122
  */
118
123
  resolveAgentSystemPrompt(agentCode: string, version?: string): Promise<string | undefined>;
124
+ /**
125
+ * Agent 展示名(manifest.name)。
126
+ * 每轮 execute/stream 注入 GraphState.agentName;身份段对用户说话用。
127
+ */
128
+ resolveAgentDisplayName(agentCode: string, version?: string): Promise<string | undefined>;
129
+ private fromAgentManifest;
119
130
  /**
120
131
  * 解析 agent tools[] + graph tool 节点 union;
121
132
  * server+预装:以预装 manifest 为准;desktop 合并 ILocalToolInstallStore。
@@ -64,6 +64,11 @@ export async function resolveAgentSystemPromptFromLoader(loader, agentCode, vers
64
64
  return undefined;
65
65
  return loader.resolveAgentSystemPrompt(agentCode, version);
66
66
  }
67
+ export async function resolveAgentDisplayNameFromLoader(loader, agentCode, version) {
68
+ if (!loader || typeof loader.resolveAgentDisplayName !== 'function')
69
+ return undefined;
70
+ return loader.resolveAgentDisplayName(agentCode, version);
71
+ }
67
72
  /** manifest.prompts.system;空白视为缺省。 */
68
73
  export function extractAgentSystemPrompt(manifest) {
69
74
  if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest))
@@ -77,6 +82,16 @@ export function extractAgentSystemPrompt(manifest) {
77
82
  const trimmed = system.trim();
78
83
  return trimmed ? trimmed : undefined;
79
84
  }
85
+ /** manifest.name;空白视为缺省。身份段对用户说话用,不当路由键。 */
86
+ export function extractAgentDisplayName(manifest) {
87
+ if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest))
88
+ return undefined;
89
+ const name = manifest.name;
90
+ if (typeof name !== 'string')
91
+ return undefined;
92
+ const trimmed = name.trim();
93
+ return trimmed ? trimmed : undefined;
94
+ }
80
95
  function extractSkillPrompt(manifest) {
81
96
  const prompt = manifest.prompt;
82
97
  if (typeof prompt === 'string' && prompt.trim())
@@ -769,18 +784,27 @@ export class GraphLoader {
769
784
  * 每轮 execute/stream 注入 GraphState.agentSystemPrompt;不写进节点 config。
770
785
  */
771
786
  async resolveAgentSystemPrompt(agentCode, version) {
787
+ return this.fromAgentManifest(agentCode, version, extractAgentSystemPrompt);
788
+ }
789
+ /**
790
+ * Agent 展示名(manifest.name)。
791
+ * 每轮 execute/stream 注入 GraphState.agentName;身份段对用户说话用。
792
+ */
793
+ async resolveAgentDisplayName(agentCode, version) {
794
+ return this.fromAgentManifest(agentCode, version, extractAgentDisplayName);
795
+ }
796
+ async fromAgentManifest(agentCode, version, extract) {
772
797
  if (this.deploymentSnapshot) {
773
798
  const snap = await this.deploymentSnapshot.loadAgentSnapshot(agentCode, version);
774
- if (snap) {
775
- return extractAgentSystemPrompt(snap.manifest);
776
- }
799
+ if (snap)
800
+ return extract(snap.manifest);
777
801
  if (this.blockRegistryDefinitions)
778
802
  return undefined;
779
803
  }
780
804
  if (this.blockRegistryDefinitions || !this.registryClient)
781
805
  return undefined;
782
806
  const record = await this.registryClient.getAgent(agentCode);
783
- return extractAgentSystemPrompt(record?.manifest);
807
+ return extract(record?.manifest);
784
808
  }
785
809
  /**
786
810
  * 解析 agent tools[] + graph tool 节点 union;
@@ -11,7 +11,7 @@ import { DEFAULT_GRAPH_TIMEOUT_MS } from '../common/types.js';
11
11
  import { resolveTaskTimeoutMs } from '../task/resolve-task-timeout.js';
12
12
  import { runWithExecutionTrace } from '../graph/execution-trace-context.js';
13
13
  import { HITL_TIMEOUT_ERROR_CODE, HITL_TIMEOUT_MESSAGE, HitlAlreadyTimedOutError, HitlNotWaitingError, buildHitlWaitedPayload, isHitlDeadlinePassed, loadHitlCheckpoint, readPersistedHitlWaiting, unwrapHitlPaused, } from '../graph/hitl/hitl-handler.js';
14
- import { resolveAgentSystemPromptFromLoader } from '../registry/graph-loader.js';
14
+ import { resolveAgentDisplayNameFromLoader, resolveAgentSystemPromptFromLoader, } from '../registry/graph-loader.js';
15
15
  import { toLoadedSkillMap } from '../tool/system-prompt-builder.js';
16
16
  import { assembleLoadedTools } from '../tool/harness-primitives.js';
17
17
  import { createFileLlmTurnLogFromEnv, } from '../debug/llm-turn-log.js';
@@ -330,6 +330,7 @@ export class AgentRuntime {
330
330
  ? (await this.deps.graphLoader.resolveAgentDir(agentCode, params.agentVersion)) ?? undefined
331
331
  : undefined;
332
332
  const agentSystemPrompt = await resolveAgentSystemPromptFromLoader(this.deps.graphLoader, agentCode, params.agentVersion);
333
+ const agentName = await resolveAgentDisplayNameFromLoader(this.deps.graphLoader, agentCode, params.agentVersion);
333
334
  const facing = await loadModelFacingHistory({
334
335
  sessionHistory: messageRecordsToGraphMessages(sessionContext.messages),
335
336
  checkpointSaver: this.deps.checkpointSaver,
@@ -402,6 +403,7 @@ export class AgentRuntime {
402
403
  promptRoots,
403
404
  agentDir,
404
405
  agentSystemPrompt,
406
+ agentName,
405
407
  skillInput: resolveSkillInputFromInvokeInput(params.input),
406
408
  traceId: resolveTraceId(params),
407
409
  traceCollector: this.deps.traceCollector,
@@ -617,6 +619,9 @@ export class AgentRuntime {
617
619
  agentSystemPrompt: (await resolveAgentSystemPromptFromLoader(this.deps.graphLoader, agentCode, agentVersion)) ?? (typeof resumedState.agentSystemPrompt === 'string'
618
620
  ? resumedState.agentSystemPrompt
619
621
  : undefined),
622
+ agentName: (await resolveAgentDisplayNameFromLoader(this.deps.graphLoader, agentCode, agentVersion)) ?? (typeof resumedState.agentName === 'string' && resumedState.agentName.trim()
623
+ ? resumedState.agentName.trim()
624
+ : undefined),
620
625
  activatedSkill: resumedState.activatedSkill,
621
626
  skillRoute: resumedState.skillRoute ??
622
627
  (typeof resumedState.activatedSkill === 'string' && resumedState.activatedSkill
@@ -814,6 +819,9 @@ export class AgentRuntime {
814
819
  const agentSystemPrompt = (await resolveAgentSystemPromptFromLoader(this.deps.graphLoader, agentCode, agentVersion)) ?? (typeof forkedCheckpoint.state.agentSystemPrompt === 'string'
815
820
  ? forkedCheckpoint.state.agentSystemPrompt
816
821
  : undefined);
822
+ const agentName = (await resolveAgentDisplayNameFromLoader(this.deps.graphLoader, agentCode, agentVersion)) ?? (typeof forkedCheckpoint.state.agentName === 'string' && forkedCheckpoint.state.agentName.trim()
823
+ ? forkedCheckpoint.state.agentName.trim()
824
+ : undefined);
817
825
  const abortDeadlineMs = Date.now() + timeout;
818
826
  try {
819
827
  const forkState = { ...forkedCheckpoint.state };
@@ -827,6 +835,7 @@ export class AgentRuntime {
827
835
  agentVersion,
828
836
  agentDir,
829
837
  agentSystemPrompt,
838
+ agentName,
830
839
  userId,
831
840
  delegationToken: overrides.executionContext?.delegationToken,
832
841
  executionContext: overrides.executionContext,
@@ -22,4 +22,4 @@ export { expandSkillScriptRefs, isSkillEntryFile, EAP_SKILL_DIR_ENV, } from './s
22
22
  export { ToolResultInjector, type ToolMessage, } from './tool-result-injector.js';
23
23
  export { ToolEventEmitter } from './tool-event-emitter.js';
24
24
  export { ToolConfirmationInterceptor } from './tool-confirmation.js';
25
- export { SystemPromptBuilder, naturalTimeWindows, loadedToolsToApiTools, toLoadedSkillMap, filterLoadedToolsForSkill, type PromptBuildContext, type PromptSection, type AssembledSystemPrompt, type ApiToolDefinition, type LoadedSkillInfo, type LoadedSkillMap, } from './system-prompt-builder.js';
25
+ export { SystemPromptBuilder, naturalTimeWindows, buildSkillCatalog, buildToolCatalog, catalogEntryTitle, spokenName, loadedToolsToApiTools, toLoadedSkillMap, filterLoadedToolsForSkill, type PromptBuildContext, type PromptSection, type AssembledSystemPrompt, type ApiToolDefinition, type LoadedSkillInfo, type LoadedSkillMap, } from './system-prompt-builder.js';
@@ -21,4 +21,4 @@ export { expandSkillScriptRefs, isSkillEntryFile, EAP_SKILL_DIR_ENV, } from './s
21
21
  export { ToolResultInjector, } from './tool-result-injector.js';
22
22
  export { ToolEventEmitter } from './tool-event-emitter.js';
23
23
  export { ToolConfirmationInterceptor } from './tool-confirmation.js';
24
- export { SystemPromptBuilder, naturalTimeWindows, loadedToolsToApiTools, toLoadedSkillMap, filterLoadedToolsForSkill, } from './system-prompt-builder.js';
24
+ export { SystemPromptBuilder, naturalTimeWindows, buildSkillCatalog, buildToolCatalog, catalogEntryTitle, spokenName, loadedToolsToApiTools, toLoadedSkillMap, filterLoadedToolsForSkill, } from './system-prompt-builder.js';
@@ -53,17 +53,19 @@ export declare function mcpToolsetCode(loaded: {
53
53
  execution?: unknown;
54
54
  };
55
55
  } | undefined): string | undefined;
56
- /** Tool Span:工具集 code + 声明版本。与 Skill 的 skillSpace/version 同一假设。 */
56
+ /** Tool Span:工具集 code + 声明版本 + 展示名(与函数名不同才写)。 */
57
57
  export declare function toolTraceIdentity(loaded: {
58
58
  toolId?: string;
59
59
  name?: string;
60
60
  manifest?: {
61
61
  id?: string;
62
+ name?: string;
62
63
  version?: string;
63
64
  };
64
65
  } | undefined, toolName: string): {
65
66
  toolset?: string;
66
67
  toolVersion?: string;
68
+ toolDisplayName?: string;
67
69
  };
68
70
  export interface HydrateMcpToolsAuth {
69
71
  authContext: AuthContext;
@@ -130,13 +130,16 @@ function declaredToolVersion(toolName, version) {
130
130
  return undefined;
131
131
  return raw;
132
132
  }
133
- /** Tool Span:工具集 code + 声明版本。与 Skill 的 skillSpace/version 同一假设。 */
133
+ /** Tool Span:工具集 code + 声明版本 + 展示名(与函数名不同才写)。 */
134
134
  export function toolTraceIdentity(loaded, toolName) {
135
135
  const toolset = toolsetCodeFromLoaded(loaded);
136
136
  const toolVersion = declaredToolVersion(toolName, loaded?.manifest?.version);
137
+ const display = loaded?.manifest?.name?.trim();
138
+ const toolDisplayName = display && display !== toolName ? display : undefined;
137
139
  return {
138
140
  ...(toolset ? { toolset } : {}),
139
141
  ...(toolVersion ? { toolVersion } : {}),
142
+ ...(toolDisplayName ? { toolDisplayName } : {}),
140
143
  };
141
144
  }
142
145
  /**
@@ -7,8 +7,8 @@
7
7
  * ```
8
8
  * [平台规则常量] ← 代码内置,安全约束 + 行为准则(最高优先级)
9
9
  * [当前时间] ← 运行时动态注入(自然周等时间规则的判定基准)
10
- * [Agent 身份] ← agentName / agentCode(目录身份,不是 prompts.system)
11
- * [可用工具短目录] ← 名称 + 一句话用途;完整 schema 仍走 API tools
10
+ * [Agent 身份] ← 展示名 agentName,缺省 agentCode(对用户说话,不是路由键)
11
+ * [可用工具短目录] ← 展示名 + 调用名 + 一句话用途;完整 schema 仍走 API tools
12
12
  * [Agent 基线] ← agent.manifest.json prompts.system;非 silent LLM
13
13
  * [节点提示词] ← Graph LLM 节点 config.systemPrompt / systemPromptFile
14
14
  * ```
@@ -109,6 +109,10 @@ export interface AssembledSystemPrompt {
109
109
  text: string;
110
110
  sections: PromptSection[];
111
111
  }
112
+ /** 对人展示的名称。有展示名用展示名,否则用编码。 */
113
+ export declare function spokenName(displayName: string | undefined, code: string | undefined): string | undefined;
114
+ /** 短目录标题:展示名在前,调用键在行内。名称与编码相同则只写编码。 */
115
+ export declare function catalogEntryTitle(code: string, displayName: string | undefined, codePhrase: string): string;
112
116
  /**
113
117
  * 非 silent LLM 才带 Agent 基线;节点提示词空则省略。
114
118
  * silent 只保留节点增量(选技能 / JSON)。
@@ -166,4 +170,6 @@ export type ApiToolDefinition = LLMToolDefinition;
166
170
  */
167
171
  /** 名称 + 一句话用途,供 system「可用工具」段。schema 仍走 loadedToolsToApiTools。 */
168
172
  export declare function buildToolCatalog(loadedTools: LoadedToolMap | undefined): string | undefined;
173
+ /** 展示名 + skillId,供 system「可用技能」段。read_file 仍用 skillId。 */
174
+ export declare function buildSkillCatalog(defs: LoadedSkillMap | undefined): string | undefined;
169
175
  export declare function loadedToolsToApiTools(loadedTools: LoadedToolMap | undefined, skillTools?: string[]): ApiToolDefinition[];
@@ -7,8 +7,8 @@
7
7
  * ```
8
8
  * [平台规则常量] ← 代码内置,安全约束 + 行为准则(最高优先级)
9
9
  * [当前时间] ← 运行时动态注入(自然周等时间规则的判定基准)
10
- * [Agent 身份] ← agentName / agentCode(目录身份,不是 prompts.system)
11
- * [可用工具短目录] ← 名称 + 一句话用途;完整 schema 仍走 API tools
10
+ * [Agent 身份] ← 展示名 agentName,缺省 agentCode(对用户说话,不是路由键)
11
+ * [可用工具短目录] ← 展示名 + 调用名 + 一句话用途;完整 schema 仍走 API tools
12
12
  * [Agent 基线] ← agent.manifest.json prompts.system;非 silent LLM
13
13
  * [节点提示词] ← Graph LLM 节点 config.systemPrompt / systemPromptFile
14
14
  * ```
@@ -86,6 +86,22 @@ function trimPrompt(value) {
86
86
  const trimmed = value.trim();
87
87
  return trimmed ? trimmed : undefined;
88
88
  }
89
+ /** 对人展示的名称。有展示名用展示名,否则用编码。 */
90
+ export function spokenName(displayName, code) {
91
+ const name = displayName?.trim();
92
+ if (name)
93
+ return name;
94
+ const id = code?.trim();
95
+ return id || undefined;
96
+ }
97
+ /** 短目录标题:展示名在前,调用键在行内。名称与编码相同则只写编码。 */
98
+ export function catalogEntryTitle(code, displayName, codePhrase) {
99
+ const id = code.trim();
100
+ const name = displayName?.trim();
101
+ if (name && name !== id)
102
+ return `**${name}**(${codePhrase})`;
103
+ return `**${id}**`;
104
+ }
89
105
  /**
90
106
  * 非 silent LLM 才带 Agent 基线;节点提示词空则省略。
91
107
  * silent 只保留节点增量(选技能 / JSON)。
@@ -154,7 +170,7 @@ export class SystemPromptBuilder {
154
170
  return lines.join('\n');
155
171
  }
156
172
  buildAgentIdentity(context) {
157
- const name = context.agentName ?? context.agentCode;
173
+ const name = spokenName(context.agentName, context.agentCode);
158
174
  return name ? `## Agent 身份\n你的名称是「${name}」。` : '';
159
175
  }
160
176
  buildJail(context) {
@@ -262,11 +278,8 @@ export function buildToolCatalog(loadedTools) {
262
278
  return undefined;
263
279
  const rows = Object.values(loadedTools).map((tool) => {
264
280
  const desc = (tool.manifest.description ?? '').replace(/\s+/g, ' ').trim();
265
- const displayName = tool.manifest.name?.trim();
266
- const title = displayName && displayName !== tool.name
267
- ? `${tool.name}(${displayName})`
268
- : tool.name;
269
- return `- **${title}**${desc ? `:${desc}` : ''}`;
281
+ const title = catalogEntryTitle(tool.name, tool.manifest.name, `调用名 ${tool.name}`);
282
+ return `- ${title}${desc ? `:${desc}` : ''}`;
270
283
  });
271
284
  if (rows.length === 0)
272
285
  return undefined;
@@ -276,6 +289,21 @@ export function buildToolCatalog(loadedTools) {
276
289
  rows.join('\n'),
277
290
  ].join('\n');
278
291
  }
292
+ /** 展示名 + skillId,供 system「可用技能」段。read_file 仍用 skillId。 */
293
+ export function buildSkillCatalog(defs) {
294
+ if (!defs)
295
+ return undefined;
296
+ const rows = Object.values(defs).map((skill) => {
297
+ const desc = (skill.description ?? '').replace(/\s+/g, ' ').trim();
298
+ const entry = skill.entryFile ?? (skill.bundlePath ? `${skill.bundlePath}/SKILL.md` : '');
299
+ const title = catalogEntryTitle(skill.skillId, skill.name, `skillId ${skill.skillId}`);
300
+ const pathLine = entry ? `\n SKILL.md: ${entry}` : '';
301
+ return `- ${title}${desc ? `:${desc}` : ''}${pathLine}`;
302
+ });
303
+ if (rows.length === 0)
304
+ return undefined;
305
+ return `# 可用技能\n要用某个技能时,调用 read_file 读取其 SKILL.md。脚本和参考文档默认在同一目录。\n${rows.join('\n')}`;
306
+ }
279
307
  export function loadedToolsToApiTools(loadedTools, skillTools) {
280
308
  if (!loadedTools)
281
309
  return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gt-fe/eap-runtime",
3
- "version": "0.0.32",
3
+ "version": "0.0.33",
4
4
  "description": "Enterprise Agent Platform — Runtime核心:Graph执行引擎、Task生命周期、Session管理、Checkpoint持久化",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",