@gt-fe/eap-runtime 0.0.20 → 0.0.21
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.
- package/README.md +3 -2
- package/dist/api/handlers/invoke.handler.d.ts +7 -0
- package/dist/api/handlers/invoke.handler.js +48 -9
- package/dist/api/handlers/stream.handler.d.ts +6 -0
- package/dist/api/handlers/stream.handler.js +56 -39
- package/dist/api/routes/agent.routes.d.ts +8 -1
- package/dist/common/types.d.ts +2 -2
- package/dist/common/types.js +1 -1
- package/dist/execution/index.d.ts +2 -0
- package/dist/execution/index.js +2 -0
- package/dist/execution/interceptors.d.ts +40 -0
- package/dist/execution/interceptors.js +23 -0
- package/dist/execution/ports.d.ts +18 -0
- package/dist/execution/ports.js +13 -0
- package/dist/governance/audit-reporter.d.ts +14 -0
- package/dist/governance/audit-reporter.js +18 -0
- package/dist/governance/index.d.ts +2 -0
- package/dist/governance/index.js +1 -0
- package/dist/governance/permission-guard.d.ts +6 -2
- package/dist/governance/permission-guard.js +38 -5
- package/dist/graph/adapters/graph-nesting.d.ts +12 -0
- package/dist/graph/adapters/graph-nesting.js +29 -0
- package/dist/graph/adapters/index.d.ts +2 -0
- package/dist/graph/adapters/index.js +2 -0
- package/dist/graph/adapters/langgraph.adapter.d.ts +25 -11
- package/dist/graph/adapters/langgraph.adapter.js +142 -82
- package/dist/graph/adapters/skill-isolate.d.ts +17 -0
- package/dist/graph/adapters/skill-isolate.js +50 -0
- package/dist/graph/adapters/subgraph-compiler.d.ts +7 -2
- package/dist/graph/adapters/subgraph-compiler.js +68 -32
- package/dist/graph/contracts/executable-graph.d.ts +27 -5
- package/dist/graph/hitl/hitl-handler.js +2 -0
- package/dist/graph/nodes/index.d.ts +1 -0
- package/dist/graph/nodes/index.js +1 -0
- package/dist/graph/nodes/llm-node.d.ts +3 -1
- package/dist/graph/nodes/llm-node.js +26 -2
- package/dist/graph/nodes/rag/dedup.d.ts +20 -0
- package/dist/graph/nodes/rag/dedup.js +77 -0
- package/dist/graph/nodes/rag/denoise.d.ts +58 -0
- package/dist/graph/nodes/rag/denoise.js +220 -0
- package/dist/graph/nodes/rag/fusion/fuse.d.ts +11 -0
- package/dist/graph/nodes/rag/fusion/fuse.js +25 -0
- package/dist/graph/nodes/rag/fusion/normalize.d.ts +9 -0
- package/dist/graph/nodes/rag/fusion/normalize.js +135 -0
- package/dist/graph/nodes/rag/index.d.ts +18 -0
- package/dist/graph/nodes/rag/index.js +17 -0
- package/dist/graph/nodes/rag/prompts.d.ts +12 -0
- package/dist/graph/nodes/rag/prompts.js +40 -0
- package/dist/graph/nodes/rag/rag-node.d.ts +21 -0
- package/dist/graph/nodes/rag/rag-node.js +135 -0
- package/dist/graph/nodes/rag/rag-search-tool.d.ts +48 -0
- package/dist/graph/nodes/rag/rag-search-tool.js +230 -0
- package/dist/graph/nodes/rag/react-loop.d.ts +57 -0
- package/dist/graph/nodes/rag/react-loop.js +467 -0
- package/dist/graph/nodes/rag/retrievers/http-embedder.d.ts +29 -0
- package/dist/graph/nodes/rag/retrievers/http-embedder.js +66 -0
- package/dist/graph/nodes/rag/retrievers/in-memory-retriever.d.ts +17 -0
- package/dist/graph/nodes/rag/retrievers/in-memory-retriever.js +18 -0
- package/dist/graph/nodes/rag/retrievers/local-sqlite-retriever.d.ts +46 -0
- package/dist/graph/nodes/rag/retrievers/local-sqlite-retriever.js +85 -0
- package/dist/graph/nodes/rag/tools.d.ts +90 -0
- package/dist/graph/nodes/rag/tools.js +260 -0
- package/dist/graph/nodes/rag/types.d.ts +226 -0
- package/dist/graph/nodes/rag/types.js +9 -0
- package/dist/graph/nodes/tool-node.d.ts +19 -1
- package/dist/graph/nodes/tool-node.js +162 -33
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/memory/semantic-retrieval.service.d.ts +1 -1
- package/dist/memory/semantic-retrieval.service.js +13 -23
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +1 -1
- package/dist/providers/routing-llm-provider.d.ts +5 -0
- package/dist/providers/routing-llm-provider.js +66 -1
- package/dist/runtime/agent-runtime.d.ts +5 -0
- package/dist/runtime/agent-runtime.js +86 -66
- package/dist/runtime/dev-rag-deps.d.ts +21 -0
- package/dist/runtime/dev-rag-deps.js +186 -0
- package/dist/runtime/dev-runtime.d.ts +16 -1
- package/dist/runtime/dev-runtime.js +59 -5
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/types.d.ts +10 -9
- package/dist/session/apply-session-compression.d.ts +81 -0
- package/dist/session/apply-session-compression.js +262 -0
- package/dist/session/apply-session-memory.d.ts +21 -0
- package/dist/session/apply-session-memory.js +48 -0
- package/dist/session/index.d.ts +2 -0
- package/dist/session/index.js +2 -0
- package/dist/session/persist-turn-messages.d.ts +51 -0
- package/dist/session/persist-turn-messages.js +140 -3
- package/dist/sse/events/index.d.ts +13 -4
- package/dist/sse/events/index.js +9 -1
- package/dist/sse/events/rag-events.d.ts +63 -0
- package/dist/sse/events/rag-events.js +9 -0
- package/dist/sse/events/session-events.d.ts +38 -0
- package/dist/sse/events/session-events.js +4 -0
- package/dist/token/index.d.ts +2 -1
- package/dist/token/index.js +2 -1
- package/dist/token/record-task-token-usage.d.ts +2 -0
- package/dist/token/record-task-token-usage.js +24 -0
- package/dist/token/token-detail-mode.d.ts +4 -4
- package/dist/token/token-detail-mode.js +4 -4
- package/dist/token/token-detail.d.ts +8 -0
- package/dist/token/token-detail.js +22 -0
- package/dist/token/token-stats.service.d.ts +2 -2
- package/dist/token/token-stats.service.js +1 -1
- package/dist/tool/create-tool-executor.d.ts +6 -0
- package/dist/tool/create-tool-executor.js +4 -3
- package/dist/tool/harness-primitives.d.ts +9 -1
- package/dist/tool/harness-primitives.js +43 -12
- package/dist/tool/index.d.ts +2 -1
- package/dist/tool/index.js +2 -1
- package/dist/tool/tool-executor.interface.d.ts +27 -0
- package/dist/tool/tool-orchestrator.d.ts +3 -1
- package/dist/tool/tool-orchestrator.js +15 -6
- package/dist/tool/tool-retry.d.ts +15 -0
- package/dist/tool/tool-retry.js +69 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,8 @@ Enterprise Agent Platform **执行引擎**(LangGraph.js):Agent Graph 编
|
|
|
8
8
|
|
|
9
9
|
| 日期 | 摘要 |
|
|
10
10
|
|------|------|
|
|
11
|
-
| 2026-08
|
|
11
|
+
| 2026-09-08 | [`docs/TODO.md`](./docs/TODO.md) 改为主路径状态(已落地 / 不在本包),不是排期 |
|
|
12
|
+
| 2026-08-29 | 待办收口:[`docs/TODO.md`](./docs/TODO.md)。此后压缩已挂主路径(默认关);窗口展示不在 Runtime;Gateway 须 `tools/list` |
|
|
12
13
|
| 2026-08-24 | 0.0.10:官方 Skill / Harness、`ForkParams`、对话详情、存储两档。依赖 `@eap/contracts@0.0.9`。详见 [CHANGELOG.md](./CHANGELOG.md) |
|
|
13
14
|
| 2026-08-21 | 0.0.9:Gateway `/mcp` JSON-RPC 补 `Accept`;`tools/call` 透传工具版本。详见 [CHANGELOG.md](./CHANGELOG.md) |
|
|
14
15
|
| 2026-08-19 | 0.0.8:Skill 子图 SSE 闭环;`ExecuteParams.traceId`;`tool.called` 改为 Tool 节点开始执行。依赖 `@eap/contracts@0.0.8`。详见 [CHANGELOG.md](./CHANGELOG.md) |
|
|
@@ -29,7 +30,7 @@ Enterprise Agent Platform **执行引擎**(LangGraph.js):Agent Graph 编
|
|
|
29
30
|
| 环境变量总表 | [`docs/governance/governance-env-config.md`](../docs/governance/governance-env-config.md) |
|
|
30
31
|
| 预装联调契约 | [`docs/contracts/preload-hosting-runtime-contract.md`](../docs/contracts/preload-hosting-runtime-contract.md) |
|
|
31
32
|
| 预装加载与请求流转 | [`docs/contracts/runtime-preinstall-load-flow.md`](../docs/contracts/runtime-preinstall-load-flow.md) |
|
|
32
|
-
| Runtime
|
|
33
|
+
| Runtime 主路径状态 | [`docs/TODO.md`](./docs/TODO.md) |
|
|
33
34
|
| 技能 FS 待办 | [`docs/TODO-skill-fs.md`](./docs/TODO-skill-fs.md) |
|
|
34
35
|
| 本地 Agent 闭环 | [`docs/workflows/local-agent-dev-loop.md`](../docs/workflows/local-agent-dev-loop.md) |
|
|
35
36
|
|
|
@@ -25,6 +25,8 @@ import type { InvokeRequest, InvokeResponse } from '../routes/agent.routes.js';
|
|
|
25
25
|
import { type GraphLoader } from '../../registry/graph-loader.js';
|
|
26
26
|
import type { ICheckpointSaver } from '../../checkpoint/contracts/checkpoint-saver.contract.js';
|
|
27
27
|
import type { ITraceCollector } from '../../contracts/trace-collector.js';
|
|
28
|
+
import { type SessionCompressionOptions } from '../../session/apply-session-compression.js';
|
|
29
|
+
import { type SessionMemoryOptions } from '../../session/apply-session-memory.js';
|
|
28
30
|
/**
|
|
29
31
|
* InvokeOrchestrator 构造器依赖
|
|
30
32
|
*/
|
|
@@ -42,6 +44,8 @@ export interface InvokeOrchestratorDeps {
|
|
|
42
44
|
/** 用于判断 session Checkpoint 是否已有历史,避免双重 append */
|
|
43
45
|
checkpointSaver?: ICheckpointSaver;
|
|
44
46
|
traceCollector?: ITraceCollector;
|
|
47
|
+
sessionCompression?: SessionCompressionOptions;
|
|
48
|
+
sessionMemory?: SessionMemoryOptions;
|
|
45
49
|
}
|
|
46
50
|
/**
|
|
47
51
|
* InvokeOrchestrator — 同步调用全流程编排
|
|
@@ -60,6 +64,8 @@ export declare class InvokeOrchestrator {
|
|
|
60
64
|
private readonly graphLoader?;
|
|
61
65
|
private readonly checkpointSaver?;
|
|
62
66
|
private readonly traceCollector?;
|
|
67
|
+
private readonly sessionCompression?;
|
|
68
|
+
private readonly sessionMemory?;
|
|
63
69
|
constructor(deps: InvokeOrchestratorDeps);
|
|
64
70
|
/**
|
|
65
71
|
* 执行同步调用编排
|
|
@@ -72,6 +78,7 @@ export declare class InvokeOrchestrator {
|
|
|
72
78
|
private buildResponse;
|
|
73
79
|
private buildErrorResponse;
|
|
74
80
|
private isTimeoutError;
|
|
81
|
+
private persistInvokeUsages;
|
|
75
82
|
}
|
|
76
83
|
/** @deprecated 请直接从 `graph/hitl/hitl-handler` 导入;此处保留 re-export 兼容旧测试引用 */
|
|
77
84
|
export { unwrapHitlPaused } from '../../graph/hitl/hitl-handler.js';
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
* @see requirements.md Requirement 11 AC1-AC2
|
|
16
16
|
*/
|
|
17
17
|
import { randomUUID } from 'node:crypto';
|
|
18
|
-
import { buildHitlWaitingTaskOutput, buildTurnGraphMessages, messageRecordsToGraphMessages, persistHitlWaitingPlaceholder, persistTurnTranscript, persistUserTurnMessage, } from '../../session/persist-turn-messages.js';
|
|
18
|
+
import { buildHitlWaitingTaskOutput, buildTurnGraphMessages, messageRecordsToGraphMessages, persistHitlWaitingPlaceholder, persistTurnTranscript, persistUserTurnMessage, resolveCheckpointThreadId, sessionVisibleGraphMessages, } from '../../session/persist-turn-messages.js';
|
|
19
19
|
import { SessionBudgetExhaustedError } from '../../token/session-budget-checker.js';
|
|
20
20
|
import { TokenBudgetExhaustedError } from '../../token/token-budget-guard.js';
|
|
21
|
-
import { recordTaskTokenUsages } from '../../token/record-task-token-usage.js';
|
|
21
|
+
import { recordTaskTokenUsages, tokenUsagesFromLlmChannel, } from '../../token/record-task-token-usage.js';
|
|
22
22
|
import { resolveExecutionContext } from '../../governance/governance-client.js';
|
|
23
23
|
import { resolveSkillInputFromInvokeInput } from '../../registry/skill-io-guard.js';
|
|
24
24
|
import { resolveAgentSystemPromptFromLoader } from '../../registry/graph-loader.js';
|
|
@@ -28,6 +28,8 @@ import { assembleLoadedTools } from '../../tool/harness-primitives.js';
|
|
|
28
28
|
import { resolveAgentCode } from '../../common/agent-code.js';
|
|
29
29
|
import { unwrapHitlPaused } from '../../graph/hitl/hitl-handler.js';
|
|
30
30
|
import { resolveTraceId } from '../../common/trace-id.js';
|
|
31
|
+
import { applySessionCompression, } from '../../session/apply-session-compression.js';
|
|
32
|
+
import { applySessionMemory, } from '../../session/apply-session-memory.js';
|
|
31
33
|
// ─────────────────────────────────────────────
|
|
32
34
|
// Default Graph DSL fallback
|
|
33
35
|
// ─────────────────────────────────────────────
|
|
@@ -64,6 +66,8 @@ export class InvokeOrchestrator {
|
|
|
64
66
|
graphLoader;
|
|
65
67
|
checkpointSaver;
|
|
66
68
|
traceCollector;
|
|
69
|
+
sessionCompression;
|
|
70
|
+
sessionMemory;
|
|
67
71
|
constructor(deps) {
|
|
68
72
|
this.sessionContextService = deps.sessionContextService;
|
|
69
73
|
this.taskService = deps.taskService;
|
|
@@ -75,6 +79,8 @@ export class InvokeOrchestrator {
|
|
|
75
79
|
this.graphLoader = deps.graphLoader;
|
|
76
80
|
this.checkpointSaver = deps.checkpointSaver;
|
|
77
81
|
this.traceCollector = deps.traceCollector;
|
|
82
|
+
this.sessionCompression = deps.sessionCompression;
|
|
83
|
+
this.sessionMemory = deps.sessionMemory;
|
|
78
84
|
}
|
|
79
85
|
/**
|
|
80
86
|
* 执行同步调用编排
|
|
@@ -159,6 +165,7 @@ export class InvokeOrchestrator {
|
|
|
159
165
|
});
|
|
160
166
|
// ─── Step 5: 构建/执行 Graph ───
|
|
161
167
|
let graphResult;
|
|
168
|
+
let finishPoints;
|
|
162
169
|
try {
|
|
163
170
|
// 构建图 — 每次请求创建独立 StateGraph 实例,确保请求间无共享可变状态
|
|
164
171
|
const loadOpts = { agentVersion: req.agentVersion };
|
|
@@ -166,6 +173,7 @@ export class InvokeOrchestrator {
|
|
|
166
173
|
? await this.graphLoader.loadGraph(agentCode, loadOpts)
|
|
167
174
|
: DEFAULT_GRAPH_DSL;
|
|
168
175
|
const graph = await this.graphEngine.buildGraph(graphDsl);
|
|
176
|
+
finishPoints = graph.finishPoints;
|
|
169
177
|
const loadedToolsBase = this.graphLoader
|
|
170
178
|
? toLoadedToolMap(await this.graphLoader.loadToolDefinitions(agentCode, loadOpts))
|
|
171
179
|
: undefined;
|
|
@@ -185,7 +193,19 @@ export class InvokeOrchestrator {
|
|
|
185
193
|
: undefined;
|
|
186
194
|
const agentSystemPrompt = await resolveAgentSystemPromptFromLoader(this.graphLoader, agentCode, req.agentVersion);
|
|
187
195
|
// 组装 GraphState:有 Checkpoint 历史则只追加本轮 user,避免双重 append
|
|
188
|
-
const history =
|
|
196
|
+
const history = await applySessionMemory({
|
|
197
|
+
history: await applySessionCompression({
|
|
198
|
+
history: messageRecordsToGraphMessages(sessionContext.messages),
|
|
199
|
+
sessionId,
|
|
200
|
+
userId: effectiveUserId,
|
|
201
|
+
taskId: task.id,
|
|
202
|
+
options: this.sessionCompression,
|
|
203
|
+
}),
|
|
204
|
+
userId: effectiveUserId,
|
|
205
|
+
agentCode,
|
|
206
|
+
query: typeof req.input === 'string' ? req.input : undefined,
|
|
207
|
+
options: this.sessionMemory,
|
|
208
|
+
});
|
|
189
209
|
const messages = await buildTurnGraphMessages({
|
|
190
210
|
history,
|
|
191
211
|
input: req.input,
|
|
@@ -205,6 +225,8 @@ export class InvokeOrchestrator {
|
|
|
205
225
|
sessionId,
|
|
206
226
|
executionContext: ctx,
|
|
207
227
|
forceToolServer: req.config?.forceToolServer,
|
|
228
|
+
ragScope: req.ragScope,
|
|
229
|
+
ragSources: req.ragSources,
|
|
208
230
|
loadedTools,
|
|
209
231
|
loadedSkills,
|
|
210
232
|
skillDefinitions,
|
|
@@ -217,6 +239,8 @@ export class InvokeOrchestrator {
|
|
|
217
239
|
});
|
|
218
240
|
}
|
|
219
241
|
catch (error) {
|
|
242
|
+
const usages = await this.persistInvokeUsages(task.id, sessionId);
|
|
243
|
+
const tokenUsage = tokenUsageTotals(usages);
|
|
220
244
|
const hitlPaused = unwrapHitlPaused(error);
|
|
221
245
|
if (hitlPaused) {
|
|
222
246
|
await this.taskService.updateStatus(task.id, 'waiting_hitl', buildHitlWaitingTaskOutput({
|
|
@@ -236,7 +260,7 @@ export class InvokeOrchestrator {
|
|
|
236
260
|
taskId: task.id,
|
|
237
261
|
sessionId,
|
|
238
262
|
output: hitlPaused.question,
|
|
239
|
-
tokenUsage
|
|
263
|
+
tokenUsage,
|
|
240
264
|
duration: Date.now() - startTime,
|
|
241
265
|
status: 'waiting_hitl',
|
|
242
266
|
hitl: {
|
|
@@ -253,7 +277,7 @@ export class InvokeOrchestrator {
|
|
|
253
277
|
taskId: task.id,
|
|
254
278
|
sessionId,
|
|
255
279
|
output: error.message,
|
|
256
|
-
tokenUsage
|
|
280
|
+
tokenUsage,
|
|
257
281
|
duration: Date.now() - startTime,
|
|
258
282
|
status: 'token_exhausted',
|
|
259
283
|
});
|
|
@@ -265,7 +289,7 @@ export class InvokeOrchestrator {
|
|
|
265
289
|
taskId: task.id,
|
|
266
290
|
sessionId,
|
|
267
291
|
output: 'Task execution timed out',
|
|
268
|
-
tokenUsage
|
|
292
|
+
tokenUsage,
|
|
269
293
|
duration: Date.now() - startTime,
|
|
270
294
|
status: 'timeout',
|
|
271
295
|
});
|
|
@@ -277,7 +301,7 @@ export class InvokeOrchestrator {
|
|
|
277
301
|
taskId: task.id,
|
|
278
302
|
sessionId,
|
|
279
303
|
output: errorMessage,
|
|
280
|
-
tokenUsage
|
|
304
|
+
tokenUsage,
|
|
281
305
|
duration: Date.now() - startTime,
|
|
282
306
|
status: 'failed',
|
|
283
307
|
});
|
|
@@ -326,11 +350,12 @@ export class InvokeOrchestrator {
|
|
|
326
350
|
// ─── Step 7: 完成 Task (running → success) ───
|
|
327
351
|
await this.taskService.updateStatus(task.id, 'success', graphResult.output);
|
|
328
352
|
// ─── Step 7b: 持久化本轮 transcript(统一顺序:assistant tool_calls → tool → assistant 文本)───
|
|
329
|
-
|
|
353
|
+
// 按 Session 已有行数切 Graph 增量。多段正文收成一条后 Session 比 Graph 短,切点可能提前;finishPoints 只含一个实际节点 id 时靠最后一条纯文本仍落到 merge。
|
|
354
|
+
const initialMessagesCount = sessionContext.messages.length + 1;
|
|
330
355
|
const allMessages = Array.isArray(graphResult.finalState?.messages)
|
|
331
356
|
? graphResult.finalState.messages
|
|
332
357
|
: [];
|
|
333
|
-
const newMessages = allMessages.slice(initialMessagesCount);
|
|
358
|
+
const newMessages = sessionVisibleGraphMessages(allMessages.slice(initialMessagesCount), finishPoints);
|
|
334
359
|
await persistTurnTranscript(this.messageService, {
|
|
335
360
|
sessionId,
|
|
336
361
|
taskId: task.id,
|
|
@@ -369,6 +394,20 @@ export class InvokeOrchestrator {
|
|
|
369
394
|
}
|
|
370
395
|
return false;
|
|
371
396
|
}
|
|
397
|
+
async persistInvokeUsages(taskId, sessionId) {
|
|
398
|
+
if (!this.checkpointSaver)
|
|
399
|
+
return [];
|
|
400
|
+
const threadId = resolveCheckpointThreadId({ sessionId, taskId });
|
|
401
|
+
const ck = await this.checkpointSaver.load(threadId);
|
|
402
|
+
const usages = tokenUsagesFromLlmChannel(ck?.state);
|
|
403
|
+
await recordTaskTokenUsages(this.taskService, taskId, usages);
|
|
404
|
+
return usages;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function tokenUsageTotals(usages) {
|
|
408
|
+
const input = usages.reduce((sum, row) => sum + row.inputTokens, 0);
|
|
409
|
+
const output = usages.reduce((sum, row) => sum + row.outputTokens, 0);
|
|
410
|
+
return { input, output, total: input + output };
|
|
372
411
|
}
|
|
373
412
|
// ─────────────────────────────────────────────
|
|
374
413
|
// Module-level Helpers
|
|
@@ -27,6 +27,8 @@ import type { IStateGraphEngine } from '../../graph/contracts/state-graph.contra
|
|
|
27
27
|
import type { TokenStatsService } from '../../token/token-stats.service.js';
|
|
28
28
|
import type { TokenBudgetGuard } from '../../token/token-budget-guard.js';
|
|
29
29
|
import type { SessionBudgetChecker } from '../../token/session-budget-checker.js';
|
|
30
|
+
import { type SessionCompressionOptions } from '../../session/apply-session-compression.js';
|
|
31
|
+
import { type SessionMemoryOptions } from '../../session/apply-session-memory.js';
|
|
30
32
|
import type { StreamRequest } from '../routes/agent.routes.js';
|
|
31
33
|
import { type GraphLoader } from '../../registry/graph-loader.js';
|
|
32
34
|
import type { ICheckpointSaver } from '../../checkpoint/contracts/checkpoint-saver.contract.js';
|
|
@@ -48,6 +50,8 @@ export interface StreamOrchestratorDeps {
|
|
|
48
50
|
checkpointSaver?: ICheckpointSaver;
|
|
49
51
|
/** Hosting 注入的 Trace 采集器;与 traceId 同时存在时创建 Skill/Tool span */
|
|
50
52
|
traceCollector?: ITraceCollector;
|
|
53
|
+
sessionCompression?: SessionCompressionOptions;
|
|
54
|
+
sessionMemory?: SessionMemoryOptions;
|
|
51
55
|
}
|
|
52
56
|
/**
|
|
53
57
|
* StreamOrchestrator — 流式调用全流程编排
|
|
@@ -66,6 +70,8 @@ export declare class StreamOrchestrator {
|
|
|
66
70
|
private readonly graphLoader?;
|
|
67
71
|
private readonly checkpointSaver?;
|
|
68
72
|
private readonly traceCollector?;
|
|
73
|
+
private readonly sessionCompression?;
|
|
74
|
+
private readonly sessionMemory?;
|
|
69
75
|
constructor(deps: StreamOrchestratorDeps);
|
|
70
76
|
/**
|
|
71
77
|
* 执行流式调用编排
|
|
@@ -19,10 +19,13 @@
|
|
|
19
19
|
* @see design.md §1.5 /stream 内部执行逻辑
|
|
20
20
|
* @see requirements.md Requirement 11 AC2
|
|
21
21
|
*/
|
|
22
|
-
import { buildHitlWaitingTaskOutput, buildTurnGraphMessages, buildTurnTranscriptFromStreamEvents, extractStreamReasoning,
|
|
22
|
+
import { buildHitlWaitingTaskOutput, buildTurnGraphMessages, buildTurnTranscriptFromStreamEvents, extractStreamReasoning, applyStreamTextDelta, createStreamAssistantBuckets, visibleStreamAssistantText, streamAssistantTexts, messageRecordsToGraphMessages, persistHitlWaitingPlaceholder, persistTurnTranscript, persistUserTurnMessage, appendTerminalToolResult, } from '../../session/persist-turn-messages.js';
|
|
23
23
|
import { SessionBudgetExhaustedError } from '../../token/session-budget-checker.js';
|
|
24
24
|
import { TokenBudgetExhaustedError } from '../../token/token-budget-guard.js';
|
|
25
25
|
import { recordTaskTokenUsages } from '../../token/record-task-token-usage.js';
|
|
26
|
+
import { iterSessionCompression, } from '../../session/apply-session-compression.js';
|
|
27
|
+
import { applySessionMemory, } from '../../session/apply-session-memory.js';
|
|
28
|
+
import { resolveTokenDetail, shouldEmitTokenSse } from '../../token/token-detail.js';
|
|
26
29
|
import { SSEEmitter } from '../../sse/sse-emitter.js';
|
|
27
30
|
import { resolveExecutionContext } from '../../governance/governance-client.js';
|
|
28
31
|
import { resolveSkillInputFromInvokeInput } from '../../registry/skill-io-guard.js';
|
|
@@ -72,6 +75,8 @@ export class StreamOrchestrator {
|
|
|
72
75
|
graphLoader;
|
|
73
76
|
checkpointSaver;
|
|
74
77
|
traceCollector;
|
|
78
|
+
sessionCompression;
|
|
79
|
+
sessionMemory;
|
|
75
80
|
constructor(deps) {
|
|
76
81
|
this.sessionContextService = deps.sessionContextService;
|
|
77
82
|
this.taskService = deps.taskService;
|
|
@@ -83,6 +88,8 @@ export class StreamOrchestrator {
|
|
|
83
88
|
this.graphLoader = deps.graphLoader;
|
|
84
89
|
this.checkpointSaver = deps.checkpointSaver;
|
|
85
90
|
this.traceCollector = deps.traceCollector;
|
|
91
|
+
this.sessionCompression = deps.sessionCompression;
|
|
92
|
+
this.sessionMemory = deps.sessionMemory;
|
|
86
93
|
}
|
|
87
94
|
/**
|
|
88
95
|
* 执行流式调用编排
|
|
@@ -207,7 +214,28 @@ export class StreamOrchestrator {
|
|
|
207
214
|
: undefined;
|
|
208
215
|
const agentSystemPrompt = await resolveAgentSystemPromptFromLoader(this.graphLoader, agentCode, req.agentVersion);
|
|
209
216
|
// 组装 GraphState:有 Checkpoint 历史则只追加本轮 user,避免双重 append
|
|
210
|
-
|
|
217
|
+
let history = messageRecordsToGraphMessages(sessionContext.messages);
|
|
218
|
+
for await (const step of iterSessionCompression({
|
|
219
|
+
history,
|
|
220
|
+
sessionId,
|
|
221
|
+
userId,
|
|
222
|
+
taskId,
|
|
223
|
+
options: this.sessionCompression,
|
|
224
|
+
})) {
|
|
225
|
+
if (step.kind === 'history') {
|
|
226
|
+
history = step.messages;
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
emitter.emit(this.buildSSEEvent(step.kind === 'started' ? 'session.compression.started' : 'session.compression.completed', correlationId, taskId, { ...step.payload }));
|
|
230
|
+
}
|
|
231
|
+
history = await applySessionMemory({
|
|
232
|
+
history,
|
|
233
|
+
userId,
|
|
234
|
+
agentCode,
|
|
235
|
+
query: typeof req.input === 'string' ? req.input : undefined,
|
|
236
|
+
options: this.sessionMemory,
|
|
237
|
+
});
|
|
238
|
+
const tokenDetail = resolveTokenDetail(req.config?.tokenDetail);
|
|
211
239
|
const messages = await buildTurnGraphMessages({
|
|
212
240
|
history,
|
|
213
241
|
input: req.input,
|
|
@@ -215,7 +243,7 @@ export class StreamOrchestrator {
|
|
|
215
243
|
threadId: sessionId,
|
|
216
244
|
});
|
|
217
245
|
const skillInput = resolveSkillInputFromInvokeInput(req.input);
|
|
218
|
-
|
|
246
|
+
const assistantBuckets = createStreamAssistantBuckets();
|
|
219
247
|
let toolCallReasoningContent;
|
|
220
248
|
let assistantReasoningContent;
|
|
221
249
|
const pendingToolCalls = [];
|
|
@@ -233,6 +261,8 @@ export class StreamOrchestrator {
|
|
|
233
261
|
sessionId,
|
|
234
262
|
executionContext,
|
|
235
263
|
forceToolServer: req.config?.forceToolServer,
|
|
264
|
+
ragScope: req.ragScope,
|
|
265
|
+
ragSources: req.ragSources,
|
|
236
266
|
loadedTools,
|
|
237
267
|
loadedSkills,
|
|
238
268
|
skillDefinitions,
|
|
@@ -272,33 +302,14 @@ export class StreamOrchestrator {
|
|
|
272
302
|
toolCallReasoningContent = p.reasoningContent;
|
|
273
303
|
}
|
|
274
304
|
}
|
|
275
|
-
|
|
276
|
-
const p = runtimeEvent.payload;
|
|
277
|
-
if (p.toolCallId && p.toolName) {
|
|
278
|
-
toolResults.push({
|
|
279
|
-
toolCallId: p.toolCallId,
|
|
280
|
-
toolName: p.toolName,
|
|
281
|
-
content: p.content,
|
|
282
|
-
success: p.success !== false,
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
}
|
|
305
|
+
appendTerminalToolResult(runtimeEvent.type, runtimeEvent.payload, toolResults);
|
|
286
306
|
const streamedReasoning = extractStreamReasoning(runtimeEvent.type, runtimeEvent.payload);
|
|
287
307
|
if (streamedReasoning)
|
|
288
308
|
assistantReasoningContent = streamedReasoning;
|
|
289
|
-
|
|
290
|
-
if (
|
|
291
|
-
|
|
292
|
-
// final 若带完整文本则覆盖累加,避免与 chunk 重复拼接
|
|
293
|
-
if (delta.trim())
|
|
294
|
-
assistantText = delta;
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
assistantText += delta;
|
|
298
|
-
}
|
|
309
|
+
applyStreamTextDelta(assistantBuckets, runtimeEvent.type, runtimeEvent.payload);
|
|
310
|
+
if (shouldEmitTokenSse(tokenDetail, runtimeEvent.type)) {
|
|
311
|
+
emitter.emit(this.runtimeEventToSSE(runtimeEvent, correlationId, taskId));
|
|
299
312
|
}
|
|
300
|
-
// 将 RuntimeEvent 转为 SSEEvent 并推送
|
|
301
|
-
emitter.emit(this.runtimeEventToSSE(runtimeEvent, correlationId, taskId));
|
|
302
313
|
}
|
|
303
314
|
}
|
|
304
315
|
catch (error) {
|
|
@@ -325,12 +336,14 @@ export class StreamOrchestrator {
|
|
|
325
336
|
}
|
|
326
337
|
// ─── 错误处理:TokenBudgetExhausted ───
|
|
327
338
|
if (error instanceof TokenBudgetExhaustedError) {
|
|
339
|
+
await recordTaskTokenUsages(this.taskService, taskId, this.tokenStatsService.list(taskId));
|
|
328
340
|
await this.taskService.updateStatus(taskId, 'token_exhausted', error.message);
|
|
329
341
|
this.emitErrorAndClose(emitter, correlationId, taskId, error);
|
|
330
342
|
return;
|
|
331
343
|
}
|
|
332
344
|
// ─── 错误处理:Timeout ───
|
|
333
345
|
if (this.isTimeoutError(error)) {
|
|
346
|
+
await recordTaskTokenUsages(this.taskService, taskId, this.tokenStatsService.list(taskId));
|
|
334
347
|
await this.taskService.updateStatus(taskId, 'timeout');
|
|
335
348
|
emitter.emit(this.buildSSEEvent('task.error', correlationId, taskId, {
|
|
336
349
|
code: ErrorCodes.TASK_TIMEOUT,
|
|
@@ -342,6 +355,7 @@ export class StreamOrchestrator {
|
|
|
342
355
|
}
|
|
343
356
|
// ─── 错误处理:通用错误 ───
|
|
344
357
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
358
|
+
await recordTaskTokenUsages(this.taskService, taskId, this.tokenStatsService.list(taskId));
|
|
345
359
|
await this.taskService.updateStatus(taskId, 'failed', errorMessage);
|
|
346
360
|
this.emitErrorAndClose(emitter, correlationId, taskId, error);
|
|
347
361
|
return;
|
|
@@ -350,21 +364,22 @@ export class StreamOrchestrator {
|
|
|
350
364
|
// Emit: response.final(带完整 assistant 文本,供客户端兜底)
|
|
351
365
|
const tokenStats = this.tokenStatsService.getTaskStats(taskId);
|
|
352
366
|
emitter.emit(this.buildSSEEvent('response.final', correlationId, taskId, {
|
|
353
|
-
content:
|
|
367
|
+
content: visibleStreamAssistantText(assistantBuckets),
|
|
354
368
|
format: 'text',
|
|
355
369
|
}));
|
|
356
|
-
// Emit: stats.token_usage
|
|
357
370
|
const totalTokens = (tokenStats.total.input ?? 0) + (tokenStats.total.output ?? 0);
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
371
|
+
if (shouldEmitTokenSse(tokenDetail, 'stats.token_usage')) {
|
|
372
|
+
emitter.emit(this.buildSSEEvent('stats.token_usage', correlationId, taskId, {
|
|
373
|
+
total: {
|
|
374
|
+
input: tokenStats.total.input,
|
|
375
|
+
output: tokenStats.total.output,
|
|
376
|
+
total: tokenStats.total.total ?? totalTokens,
|
|
377
|
+
},
|
|
378
|
+
byNode: tokenStats.byNode,
|
|
379
|
+
byModel: tokenStats.byModel,
|
|
380
|
+
costEstimate: tokenStats.costEstimate,
|
|
381
|
+
}));
|
|
382
|
+
}
|
|
368
383
|
// ─── Step 8: 记录 Token + 完成 Task + 关闭 SSE ───
|
|
369
384
|
const duration = Date.now() - startTime;
|
|
370
385
|
// Emit: task.completed
|
|
@@ -383,7 +398,9 @@ export class StreamOrchestrator {
|
|
|
383
398
|
messages: buildTurnTranscriptFromStreamEvents({
|
|
384
399
|
pendingToolCalls,
|
|
385
400
|
toolResults,
|
|
386
|
-
|
|
401
|
+
assistantTexts: streamAssistantTexts(assistantBuckets),
|
|
402
|
+
assistantText: visibleStreamAssistantText(assistantBuckets),
|
|
403
|
+
finishPoints: graph.finishPoints,
|
|
387
404
|
toolCallReasoningContent,
|
|
388
405
|
assistantReasoningContent,
|
|
389
406
|
}),
|
|
@@ -11,10 +11,17 @@ import type { IStateGraphEngine } from '../../graph/contracts/executable-graph.j
|
|
|
11
11
|
import type { SSEEmitter } from '../../sse/sse-emitter.js';
|
|
12
12
|
export type { InvokeConfig, InvokeResponseData } from '@gt-fe/eap-contracts';
|
|
13
13
|
/**
|
|
14
|
-
* dev HTTP 层 Invoke 请求(扩展 userId,Hosting 从 auth
|
|
14
|
+
* dev HTTP 层 Invoke 请求(扩展 userId,Hosting 从 auth 注入;ragScope 为请求级
|
|
15
|
+
* 检索范围——前端圈定已向量化文件/目录,仅 rag 节点本地检索源生效)
|
|
15
16
|
*/
|
|
16
17
|
export type InvokeRequest = ContractInvokeRequest & {
|
|
17
18
|
userId?: string;
|
|
19
|
+
ragScope?: {
|
|
20
|
+
fileIds?: string[];
|
|
21
|
+
dirPaths?: string[];
|
|
22
|
+
};
|
|
23
|
+
/** 会话级数据源勾选(数据源 id 列表;缺省 = 智能体预定义目录全部启用) */
|
|
24
|
+
ragSources?: string[];
|
|
18
25
|
};
|
|
19
26
|
export type InvokeResponse = ContractInvokeResponse;
|
|
20
27
|
/** 流式调用请求 — 与 InvokeRequest 相同 */
|
package/dist/common/types.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Token 统计输出粒度控制
|
|
10
10
|
* - none: 不输出任何 Token 统计事件
|
|
11
11
|
* - summary: 仅 Task 结束时输出 stats.token_usage 汇总
|
|
12
|
-
* - detail: 每次 LLM 调用输出 stats.
|
|
12
|
+
* - detail: 每次 LLM 调用输出 stats.node_token_usage + 结束时汇总
|
|
13
13
|
*/
|
|
14
14
|
export type TokenDetailLevel = 'none' | 'summary' | 'detail';
|
|
15
15
|
/**
|
|
@@ -79,7 +79,7 @@ export type MessageRole = 'user' | 'assistant' | 'system' | 'tool';
|
|
|
79
79
|
*
|
|
80
80
|
* 与 @gt-fe/eap-contracts.TokenUsage 的区别:
|
|
81
81
|
* - contracts 版本是 Task 级聚合结果(含 byNode/byModel)
|
|
82
|
-
* - 本类型是单次调用粒度的原始记录,用于 Runtime 内部累计和 stats.
|
|
82
|
+
* - 本类型是单次调用粒度的原始记录,用于 Runtime 内部累计和 stats.node_token_usage 事件
|
|
83
83
|
*/
|
|
84
84
|
export interface TokenUsage {
|
|
85
85
|
/** 输入 Token 数 */
|
package/dist/common/types.js
CHANGED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { decideBeforeModel, decideBeforeTool, type AfterModelInterceptor, type AfterToolInterceptor, type BeforeModelInput, type BeforeModelInterceptor, type BeforeToolInterceptor, type ExecutionInterceptors, type ModelInterceptorDecision, type ToolInterceptorDecision, } from './interceptors.js';
|
|
2
|
+
export { sandboxFromJail, type ISandbox, type IApproval } from './ports.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 执行拦截:Tool / LLM 调用前可拒绝,默认无注入则与未装配时相同。
|
|
3
|
+
* 不是规格 R13 Hook,不做插件发现、不读项目 hook 目录。
|
|
4
|
+
*/
|
|
5
|
+
import type { ExecutionContext } from '@gt-fe/eap-contracts';
|
|
6
|
+
import type { GraphMessage } from '../graph/contracts/executable-graph.js';
|
|
7
|
+
import type { LLMNodeConfig, LLMResponse } from '../graph/nodes/llm-node.js';
|
|
8
|
+
import type { ToolCallRequest, ToolCallResult } from '../tool/tool-executor.interface.js';
|
|
9
|
+
export type ToolInterceptorDecision = {
|
|
10
|
+
action: 'allow';
|
|
11
|
+
} | {
|
|
12
|
+
action: 'deny';
|
|
13
|
+
reason: string;
|
|
14
|
+
} | {
|
|
15
|
+
action: 'ask';
|
|
16
|
+
};
|
|
17
|
+
export type BeforeToolInterceptor = (request: ToolCallRequest, ctx?: ExecutionContext) => Promise<ToolInterceptorDecision | void> | ToolInterceptorDecision | void;
|
|
18
|
+
export type AfterToolInterceptor = (request: ToolCallRequest, result: ToolCallResult) => Promise<void> | void;
|
|
19
|
+
export interface BeforeModelInput {
|
|
20
|
+
messages: GraphMessage[];
|
|
21
|
+
config: LLMNodeConfig;
|
|
22
|
+
nodeId: string;
|
|
23
|
+
}
|
|
24
|
+
export type ModelInterceptorDecision = {
|
|
25
|
+
action: 'allow';
|
|
26
|
+
messages?: GraphMessage[];
|
|
27
|
+
} | {
|
|
28
|
+
action: 'deny';
|
|
29
|
+
reason: string;
|
|
30
|
+
};
|
|
31
|
+
export type BeforeModelInterceptor = (input: BeforeModelInput) => Promise<ModelInterceptorDecision | void> | ModelInterceptorDecision | void;
|
|
32
|
+
export type AfterModelInterceptor = (input: BeforeModelInput, response: LLMResponse) => Promise<void> | void;
|
|
33
|
+
export interface ExecutionInterceptors {
|
|
34
|
+
beforeTool?: BeforeToolInterceptor;
|
|
35
|
+
afterTool?: AfterToolInterceptor;
|
|
36
|
+
beforeModel?: BeforeModelInterceptor;
|
|
37
|
+
afterModel?: AfterModelInterceptor;
|
|
38
|
+
}
|
|
39
|
+
export declare function decideBeforeTool(interceptor: BeforeToolInterceptor | undefined, request: ToolCallRequest, ctx?: ExecutionContext): Promise<ToolInterceptorDecision>;
|
|
40
|
+
export declare function decideBeforeModel(interceptor: BeforeModelInterceptor | undefined, input: BeforeModelInput): Promise<ModelInterceptorDecision>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 执行拦截:Tool / LLM 调用前可拒绝,默认无注入则与未装配时相同。
|
|
3
|
+
* 不是规格 R13 Hook,不做插件发现、不读项目 hook 目录。
|
|
4
|
+
*/
|
|
5
|
+
export async function decideBeforeTool(interceptor, request, ctx) {
|
|
6
|
+
if (!interceptor)
|
|
7
|
+
return { action: 'allow' };
|
|
8
|
+
const raw = await interceptor(request, ctx);
|
|
9
|
+
if (!raw || raw.action === 'allow')
|
|
10
|
+
return { action: 'allow' };
|
|
11
|
+
if (raw.action === 'ask')
|
|
12
|
+
return { action: 'ask' };
|
|
13
|
+
return { action: 'deny', reason: raw.reason || '拦截拒绝' };
|
|
14
|
+
}
|
|
15
|
+
export async function decideBeforeModel(interceptor, input) {
|
|
16
|
+
if (!interceptor)
|
|
17
|
+
return { action: 'allow' };
|
|
18
|
+
const raw = await interceptor(input);
|
|
19
|
+
if (!raw || raw.action === 'allow') {
|
|
20
|
+
return { action: 'allow', messages: raw && raw.action === 'allow' ? raw.messages : undefined };
|
|
21
|
+
}
|
|
22
|
+
return { action: 'deny', reason: raw.reason || '拦截拒绝' };
|
|
23
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 执行口类型:不另起引擎,也不改现有调用路径。
|
|
3
|
+
* ISandbox 描述 jail 根目录;execute_command 仍走 harness jail,未经过本接口。
|
|
4
|
+
* IApproval 即 HitlHandler;确认仍走 require_confirmation。
|
|
5
|
+
* OS 级沙箱见 TODO-skill-fs FS-2。
|
|
6
|
+
*/
|
|
7
|
+
import type { HitlHandler } from '../graph/hitl/hitl-handler.js';
|
|
8
|
+
/** 命令路径约束。默认:用户目录读写 + 技能包只读。 */
|
|
9
|
+
export interface ISandbox {
|
|
10
|
+
allowedWriteRoots: string[];
|
|
11
|
+
allowedReadRoots: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare function sandboxFromJail(jail: {
|
|
14
|
+
writeRoot: string;
|
|
15
|
+
extraRoots?: string[];
|
|
16
|
+
}): ISandbox;
|
|
17
|
+
/** 人工确认。默认实现是 HitlHandler + require_confirmation。 */
|
|
18
|
+
export type IApproval = HitlHandler;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 执行口类型:不另起引擎,也不改现有调用路径。
|
|
3
|
+
* ISandbox 描述 jail 根目录;execute_command 仍走 harness jail,未经过本接口。
|
|
4
|
+
* IApproval 即 HitlHandler;确认仍走 require_confirmation。
|
|
5
|
+
* OS 级沙箱见 TODO-skill-fs FS-2。
|
|
6
|
+
*/
|
|
7
|
+
export function sandboxFromJail(jail) {
|
|
8
|
+
const extra = jail.extraRoots ?? [];
|
|
9
|
+
return {
|
|
10
|
+
allowedWriteRoots: [jail.writeRoot],
|
|
11
|
+
allowedReadRoots: [jail.writeRoot, ...extra],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 权限拒绝审计。未注入则只抛错(A-4)。上报失败不挡执行。
|
|
3
|
+
*/
|
|
4
|
+
export interface PermissionDenialAudit {
|
|
5
|
+
kind: 'tool' | 'skill';
|
|
6
|
+
resourceId: string;
|
|
7
|
+
reason: string;
|
|
8
|
+
userId?: string | null;
|
|
9
|
+
correlationId?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface IAuditReporter {
|
|
12
|
+
recordDenial(event: PermissionDenialAudit): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export declare function reportPermissionDenial(reporter: IAuditReporter | undefined, event: PermissionDenialAudit): Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 权限拒绝审计。未注入则只抛错(A-4)。上报失败不挡执行。
|
|
3
|
+
*/
|
|
4
|
+
import { emitRuntimeLog } from '../common/logger.js';
|
|
5
|
+
export async function reportPermissionDenial(reporter, event) {
|
|
6
|
+
if (!reporter)
|
|
7
|
+
return;
|
|
8
|
+
try {
|
|
9
|
+
await reporter.recordDenial(event);
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
emitRuntimeLog('warn', 'runtime.audit', 'permission denial audit failed', {
|
|
13
|
+
event: 'runtime.audit.denial_failed',
|
|
14
|
+
resourceId: event.resourceId,
|
|
15
|
+
error: err instanceof Error ? err.message : String(err),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -5,3 +5,5 @@ export type { CallerType, ExecutionContext, GovernancePermissionCheckParams, Gov
|
|
|
5
5
|
export type { IGovernanceClient } from './governance-client.js';
|
|
6
6
|
export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, } from './governance-client.js';
|
|
7
7
|
export { assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './permission-guard.js';
|
|
8
|
+
export type { IAuditReporter, PermissionDenialAudit } from './audit-reporter.js';
|
|
9
|
+
export { reportPermissionDenial } from './audit-reporter.js';
|
package/dist/governance/index.js
CHANGED
|
@@ -3,3 +3,4 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, } from './governance-client.js';
|
|
5
5
|
export { assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './permission-guard.js';
|
|
6
|
+
export { reportPermissionDenial } from './audit-reporter.js';
|