@nextclaw/ncp-agent-runtime-next 0.0.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +175 -0
- package/dist/index.js.map +1 -0
- package/package.json +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NextClaw contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ToolResultContentManager } from "@nextclaw/ncp-agent-runtime";
|
|
2
|
+
import { NcpAssistantReasoningNormalizationMode, NcpEndpointEvent, NcpLLMApi, NcpLLMApiInput, NcpMessage, NcpStreamEncoder, NcpTool } from "@nextclaw/ncp";
|
|
3
|
+
|
|
4
|
+
//#region src/runtime/types/agent-model-input.types.d.ts
|
|
5
|
+
type DefaultNcpAgentRunSpec = {
|
|
6
|
+
runId: string;
|
|
7
|
+
agentId: string;
|
|
8
|
+
model: string;
|
|
9
|
+
maxTokens?: number;
|
|
10
|
+
thinkingEffort?: string | null;
|
|
11
|
+
correlationId?: string;
|
|
12
|
+
};
|
|
13
|
+
type AgentModelInputBuildRequest = {
|
|
14
|
+
spec: DefaultNcpAgentRunSpec;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
messages: readonly NcpMessage[];
|
|
17
|
+
contextBlocks: readonly string[];
|
|
18
|
+
tools: readonly NcpTool[];
|
|
19
|
+
};
|
|
20
|
+
interface AgentModelInputBuilder {
|
|
21
|
+
build(request: AgentModelInputBuildRequest): Promise<NcpLLMApiInput>;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/runtime/agent-runtime.service.d.ts
|
|
25
|
+
type AgentRuntimeSessionStateSnapshot = {
|
|
26
|
+
messages: readonly NcpMessage[];
|
|
27
|
+
};
|
|
28
|
+
type AgentRuntimeSessionState = {
|
|
29
|
+
readonly sessionId: string;
|
|
30
|
+
readonly inbox: {
|
|
31
|
+
drain(): NcpMessage[];
|
|
32
|
+
isEmpty(): boolean;
|
|
33
|
+
};
|
|
34
|
+
getSnapshot(): AgentRuntimeSessionStateSnapshot;
|
|
35
|
+
applyEvents(events: readonly NcpEndpointEvent[]): Promise<void>;
|
|
36
|
+
};
|
|
37
|
+
type DefaultNcpAgentRuntimeRunOptions = {
|
|
38
|
+
sessionRun: AgentRuntimeSessionState;
|
|
39
|
+
contextBlocks: readonly string[];
|
|
40
|
+
tools: readonly NcpTool[];
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
};
|
|
43
|
+
type AgentRunPreflight = (input: {
|
|
44
|
+
spec: DefaultNcpAgentRunSpec;
|
|
45
|
+
sessionRun: AgentRuntimeSessionState;
|
|
46
|
+
}) => Promise<readonly NcpEndpointEvent[]>;
|
|
47
|
+
type DefaultNcpAgentRuntimeConfig = {
|
|
48
|
+
llmApi: NcpLLMApi;
|
|
49
|
+
modelInputBuilder: AgentModelInputBuilder;
|
|
50
|
+
runPreflight?: AgentRunPreflight;
|
|
51
|
+
reasoningNormalizationMode?: NcpAssistantReasoningNormalizationMode;
|
|
52
|
+
streamEncoder?: NcpStreamEncoder;
|
|
53
|
+
toolResultContentManager?: ToolResultContentManager;
|
|
54
|
+
};
|
|
55
|
+
declare class DefaultNcpAgentRuntime {
|
|
56
|
+
private readonly llmApi;
|
|
57
|
+
private readonly modelInputBuilder;
|
|
58
|
+
private readonly runPreflight?;
|
|
59
|
+
private readonly reasoningNormalizationMode;
|
|
60
|
+
private readonly streamEncoder;
|
|
61
|
+
private readonly toolResultContentManager;
|
|
62
|
+
constructor(config: DefaultNcpAgentRuntimeConfig);
|
|
63
|
+
run(spec: DefaultNcpAgentRunSpec, options: DefaultNcpAgentRuntimeRunOptions): AsyncIterable<NcpEndpointEvent>;
|
|
64
|
+
private tapRuntimeStream;
|
|
65
|
+
private drainInbox;
|
|
66
|
+
private isAbortRequested;
|
|
67
|
+
private toAbortEvent;
|
|
68
|
+
private applyEvent;
|
|
69
|
+
private executeToolCall;
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { type AgentModelInputBuildRequest, type AgentModelInputBuilder, type AgentRunPreflight, type AgentRuntimeSessionState, type AgentRuntimeSessionStateSnapshot, type DefaultNcpAgentRunSpec, DefaultNcpAgentRuntime, type DefaultNcpAgentRuntimeConfig, type DefaultNcpAgentRuntimeRunOptions };
|
|
73
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/runtime/types/agent-model-input.types.ts","../src/runtime/agent-runtime.service.ts"],"mappings":";;;;KAMY,sBAAA;EACV,KAAA;EACA,OAAA;EACA,KAAA;EACA,SAAA;EACA,cAAA;EACA,aAAA;AAAA;AAAA,KAGU,2BAAA;EACV,IAAA,EAAM,sBAAA;EACN,SAAA;EACA,QAAA,WAAmB,UAAA;EACnB,aAAA;EACA,KAAA,WAAgB,OAAA;AAAA;AAAA,UAGD,sBAAA;EACf,KAAA,CAAM,OAAA,EAAS,2BAAA,GAA8B,OAAA,CAAQ,cAAA;AAAA;;;KCA3C,gCAAA;EACV,QAAA,WAAmB,UAAA;AAAA;AAAA,KAGT,wBAAA;EAAA,SACD,SAAA;EAAA,SACA,KAAA;IACP,KAAA,IAAS,UAAA;IACT,OAAA;EAAA;EAEF,WAAA,IAAe,gCAAA;EACf,WAAA,CAAY,MAAA,WAAiB,gBAAA,KAAqB,OAAA;AAAA;AAAA,KAGxC,gCAAA;EACV,UAAA,EAAY,wBAAA;EACZ,aAAA;EACA,KAAA,WAAgB,OAAA;EAChB,MAAA,GAAS,WAAA;AAAA;AAAA,KAGC,iBAAA,IAAqB,KAAA;EAC/B,IAAA,EAAM,sBAAA;EACN,UAAA,EAAY,wBAAA;AAAA,MACR,OAAA,UAAiB,gBAAA;AAAA,KAEX,4BAAA;EACV,MAAA,EAAQ,SAAA;EACR,iBAAA,EAAmB,sBAAA;EACnB,YAAA,GAAe,iBAAA;EACf,0BAAA,GAA6B,sCAAA;EAC7B,aAAA,GAAgB,gBAAA;EAChB,wBAAA,GAA2B,wBAAA;AAAA;AAAA,cAQhB,sBAAA;EAAA,iBACM,MAAA;EAAA,iBACA,iBAAA;EAAA,iBACA,YAAA;EAAA,iBACA,0BAAA;EAAA,iBACA,aAAA;EAAA,iBACA,wBAAA;cAEL,MAAA,EAAQ,4BAAA;EAuBb,GAAA,CACL,IAAA,EAAM,sBAAA,EACN,OAAA,EAAS,gCAAA,GACR,aAAA,CAAc,gBAAA;EAAA,QAuIF,gBAAA;EAAA,QAiBP,UAAA;EAAA,QAkBA,gBAAA;EAAA,QAEA,YAAA;EAAA,QAaA,UAAA;EAAA,QAQA,eAAA;AAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { DefaultNcpRoundCollector, DefaultNcpStreamEncoder, defaultToolResultContentManager, executeCollectedToolCall } from "@nextclaw/ncp-agent-runtime";
|
|
3
|
+
import { NcpEventType } from "@nextclaw/ncp";
|
|
4
|
+
//#region src/runtime/agent-runtime.service.ts
|
|
5
|
+
var DefaultNcpAgentRuntime = class {
|
|
6
|
+
llmApi;
|
|
7
|
+
modelInputBuilder;
|
|
8
|
+
runPreflight;
|
|
9
|
+
reasoningNormalizationMode;
|
|
10
|
+
streamEncoder;
|
|
11
|
+
toolResultContentManager;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
const { llmApi, modelInputBuilder, runPreflight, reasoningNormalizationMode, streamEncoder, toolResultContentManager } = config;
|
|
14
|
+
this.llmApi = llmApi;
|
|
15
|
+
this.modelInputBuilder = modelInputBuilder;
|
|
16
|
+
this.runPreflight = runPreflight;
|
|
17
|
+
this.reasoningNormalizationMode = reasoningNormalizationMode ?? "off";
|
|
18
|
+
this.streamEncoder = streamEncoder ?? new DefaultNcpStreamEncoder({ reasoningNormalizationMode: this.reasoningNormalizationMode });
|
|
19
|
+
this.toolResultContentManager = toolResultContentManager ?? defaultToolResultContentManager;
|
|
20
|
+
}
|
|
21
|
+
async *run(spec, options) {
|
|
22
|
+
const { contextBlocks, sessionRun, signal, tools } = options;
|
|
23
|
+
const sessionId = sessionRun.sessionId;
|
|
24
|
+
const messageId = `assistant-message-${randomUUID()}`;
|
|
25
|
+
try {
|
|
26
|
+
for (const event of this.drainInbox(sessionRun, spec).events) {
|
|
27
|
+
if (this.isAbortRequested(signal)) break;
|
|
28
|
+
yield await this.applyEvent(sessionRun, event);
|
|
29
|
+
}
|
|
30
|
+
const preflightEvents = this.runPreflight ? await this.runPreflight({
|
|
31
|
+
spec,
|
|
32
|
+
sessionRun
|
|
33
|
+
}) : [];
|
|
34
|
+
for (const event of preflightEvents) {
|
|
35
|
+
if (this.isAbortRequested(signal)) break;
|
|
36
|
+
yield await this.applyEvent(sessionRun, event);
|
|
37
|
+
}
|
|
38
|
+
yield await this.applyEvent(sessionRun, {
|
|
39
|
+
type: NcpEventType.RunStarted,
|
|
40
|
+
payload: {
|
|
41
|
+
messageId,
|
|
42
|
+
runId: spec.runId,
|
|
43
|
+
sessionId,
|
|
44
|
+
correlationId: spec.correlationId
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
if (this.isAbortRequested(signal)) {
|
|
48
|
+
yield await this.applyEvent(sessionRun, this.toAbortEvent(sessionId, messageId, spec));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
while (!this.isAbortRequested(signal)) {
|
|
52
|
+
const round = new DefaultNcpRoundCollector(this.reasoningNormalizationMode);
|
|
53
|
+
const modelInput = await this.modelInputBuilder.build({
|
|
54
|
+
spec,
|
|
55
|
+
sessionId,
|
|
56
|
+
messages: sessionRun.getSnapshot().messages,
|
|
57
|
+
contextBlocks,
|
|
58
|
+
tools
|
|
59
|
+
});
|
|
60
|
+
if (this.isAbortRequested(signal)) break;
|
|
61
|
+
const encoded = this.streamEncoder.encode(this.tapRuntimeStream(this.llmApi.generate(modelInput, { signal }), (chunk) => round.consumeChunk(chunk), signal), {
|
|
62
|
+
sessionId,
|
|
63
|
+
messageId,
|
|
64
|
+
runId: spec.runId,
|
|
65
|
+
correlationId: spec.correlationId
|
|
66
|
+
});
|
|
67
|
+
for await (const event of encoded) {
|
|
68
|
+
if (this.isAbortRequested(signal)) break;
|
|
69
|
+
yield await this.applyEvent(sessionRun, event);
|
|
70
|
+
}
|
|
71
|
+
if (this.isAbortRequested(signal)) break;
|
|
72
|
+
const toolCalls = round.getToolCalls();
|
|
73
|
+
for (const toolCall of toolCalls) {
|
|
74
|
+
if (this.isAbortRequested(signal)) break;
|
|
75
|
+
const toolResultEvent = await this.executeToolCall(tools, sessionId, spec, toolCall);
|
|
76
|
+
if (this.isAbortRequested(signal)) break;
|
|
77
|
+
yield await this.applyEvent(sessionRun, toolResultEvent);
|
|
78
|
+
}
|
|
79
|
+
if (this.isAbortRequested(signal)) break;
|
|
80
|
+
const drainedInbox = this.drainInbox(sessionRun, spec);
|
|
81
|
+
for (const event of drainedInbox.events) {
|
|
82
|
+
if (this.isAbortRequested(signal)) break;
|
|
83
|
+
yield await this.applyEvent(sessionRun, event);
|
|
84
|
+
}
|
|
85
|
+
if (this.isAbortRequested(signal)) break;
|
|
86
|
+
if (toolCalls.length > 0 || drainedInbox.drained) continue;
|
|
87
|
+
yield await this.applyEvent(sessionRun, {
|
|
88
|
+
type: NcpEventType.RunFinished,
|
|
89
|
+
payload: {
|
|
90
|
+
messageId,
|
|
91
|
+
runId: spec.runId,
|
|
92
|
+
sessionId,
|
|
93
|
+
correlationId: spec.correlationId
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
yield await this.applyEvent(sessionRun, this.toAbortEvent(sessionId, messageId, spec));
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (this.isAbortRequested(signal)) {
|
|
101
|
+
yield await this.applyEvent(sessionRun, this.toAbortEvent(sessionId, messageId, spec));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
yield await this.applyEvent(sessionRun, {
|
|
105
|
+
type: NcpEventType.RunError,
|
|
106
|
+
payload: {
|
|
107
|
+
sessionId,
|
|
108
|
+
runId: spec.runId,
|
|
109
|
+
correlationId: spec.correlationId,
|
|
110
|
+
error: error instanceof Error ? error.message : String(error)
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async *tapRuntimeStream(stream, consumeChunk, signal) {
|
|
116
|
+
for await (const chunk of stream) {
|
|
117
|
+
if (signal?.aborted) break;
|
|
118
|
+
consumeChunk(chunk);
|
|
119
|
+
yield chunk;
|
|
120
|
+
if (signal?.aborted) break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
drainInbox = (sessionRun, spec) => {
|
|
124
|
+
const messages = sessionRun.inbox.drain();
|
|
125
|
+
return {
|
|
126
|
+
drained: messages.length > 0,
|
|
127
|
+
events: messages.map((message) => ({
|
|
128
|
+
type: NcpEventType.MessageSent,
|
|
129
|
+
payload: {
|
|
130
|
+
sessionId: sessionRun.sessionId,
|
|
131
|
+
message,
|
|
132
|
+
correlationId: spec.correlationId
|
|
133
|
+
}
|
|
134
|
+
}))
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
isAbortRequested = (signal) => signal?.aborted ?? false;
|
|
138
|
+
toAbortEvent = (sessionId, messageId, spec) => ({
|
|
139
|
+
type: NcpEventType.MessageAbort,
|
|
140
|
+
payload: {
|
|
141
|
+
messageId,
|
|
142
|
+
sessionId,
|
|
143
|
+
correlationId: spec.correlationId
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
applyEvent = async (sessionRun, event) => {
|
|
147
|
+
await sessionRun.applyEvents([event]);
|
|
148
|
+
return event;
|
|
149
|
+
};
|
|
150
|
+
executeToolCall = async (tools, sessionId, spec, toolCall) => {
|
|
151
|
+
const tool = tools.find((candidate) => candidate.name === toolCall.toolName);
|
|
152
|
+
const result = this.toolResultContentManager.normalizeToolCallResult(await executeCollectedToolCall({
|
|
153
|
+
toolCall,
|
|
154
|
+
tool,
|
|
155
|
+
execute: (availableTool, args) => {
|
|
156
|
+
if (!availableTool) throw new Error("Tool is not available in this run.");
|
|
157
|
+
return availableTool.execute(args);
|
|
158
|
+
}
|
|
159
|
+
}));
|
|
160
|
+
return {
|
|
161
|
+
type: NcpEventType.MessageToolCallResult,
|
|
162
|
+
payload: {
|
|
163
|
+
sessionId,
|
|
164
|
+
toolCallId: toolCall.toolCallId,
|
|
165
|
+
correlationId: spec.correlationId,
|
|
166
|
+
content: result.result,
|
|
167
|
+
contentItems: result.contentItems
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
//#endregion
|
|
173
|
+
export { DefaultNcpAgentRuntime };
|
|
174
|
+
|
|
175
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/runtime/agent-runtime.service.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n defaultToolResultContentManager,\n DefaultNcpRoundCollector,\n DefaultNcpStreamEncoder,\n executeCollectedToolCall,\n type CollectedToolCall,\n type ToolResultContentManager,\n} from \"@nextclaw/ncp-agent-runtime\";\nimport {\n NcpEventType,\n type NcpAssistantReasoningNormalizationMode,\n type NcpEndpointEvent,\n type NcpLLMApi,\n type NcpMessage,\n type NcpStreamEncoder,\n type NcpTool,\n type OpenAIChatChunk,\n} from \"@nextclaw/ncp\";\nimport type {\n AgentModelInputBuilder,\n DefaultNcpAgentRunSpec,\n} from \"./types/agent-model-input.types.js\";\n\nexport type AgentRuntimeSessionStateSnapshot = {\n messages: readonly NcpMessage[];\n};\n\nexport type AgentRuntimeSessionState = {\n readonly sessionId: string;\n readonly inbox: {\n drain(): NcpMessage[];\n isEmpty(): boolean;\n };\n getSnapshot(): AgentRuntimeSessionStateSnapshot;\n applyEvents(events: readonly NcpEndpointEvent[]): Promise<void>;\n};\n\nexport type DefaultNcpAgentRuntimeRunOptions = {\n sessionRun: AgentRuntimeSessionState;\n contextBlocks: readonly string[];\n tools: readonly NcpTool[];\n signal?: AbortSignal;\n};\n\nexport type AgentRunPreflight = (input: {\n spec: DefaultNcpAgentRunSpec;\n sessionRun: AgentRuntimeSessionState;\n}) => Promise<readonly NcpEndpointEvent[]>;\n\nexport type DefaultNcpAgentRuntimeConfig = {\n llmApi: NcpLLMApi;\n modelInputBuilder: AgentModelInputBuilder;\n runPreflight?: AgentRunPreflight;\n reasoningNormalizationMode?: NcpAssistantReasoningNormalizationMode;\n streamEncoder?: NcpStreamEncoder;\n toolResultContentManager?: ToolResultContentManager;\n};\n\ntype InboxDrainResult = {\n drained: boolean;\n events: NcpEndpointEvent[];\n};\n\nexport class DefaultNcpAgentRuntime {\n private readonly llmApi: NcpLLMApi;\n private readonly modelInputBuilder: AgentModelInputBuilder;\n private readonly runPreflight?: AgentRunPreflight;\n private readonly reasoningNormalizationMode: NcpAssistantReasoningNormalizationMode;\n private readonly streamEncoder: NcpStreamEncoder;\n private readonly toolResultContentManager: ToolResultContentManager;\n\n constructor(config: DefaultNcpAgentRuntimeConfig) {\n const {\n llmApi,\n modelInputBuilder,\n runPreflight,\n reasoningNormalizationMode,\n streamEncoder,\n toolResultContentManager,\n } = config;\n this.llmApi = llmApi;\n this.modelInputBuilder = modelInputBuilder;\n this.runPreflight = runPreflight;\n this.reasoningNormalizationMode = reasoningNormalizationMode ?? \"off\";\n this.streamEncoder =\n streamEncoder ??\n new DefaultNcpStreamEncoder({\n reasoningNormalizationMode: this.reasoningNormalizationMode,\n });\n this.toolResultContentManager =\n toolResultContentManager ?? defaultToolResultContentManager;\n }\n\n // eslint-disable-next-line max-statements\n async *run(\n spec: DefaultNcpAgentRunSpec,\n options: DefaultNcpAgentRuntimeRunOptions,\n ): AsyncIterable<NcpEndpointEvent> {\n const {\n contextBlocks,\n sessionRun,\n signal,\n tools,\n } = options;\n const sessionId = sessionRun.sessionId;\n const messageId = `assistant-message-${randomUUID()}`;\n\n try {\n for (const event of this.drainInbox(sessionRun, spec).events) {\n if (this.isAbortRequested(signal)) {\n break;\n }\n yield await this.applyEvent(sessionRun, event);\n }\n const preflightEvents = this.runPreflight\n ? await this.runPreflight({ spec, sessionRun })\n : [];\n for (const event of preflightEvents) {\n if (this.isAbortRequested(signal)) {\n break;\n }\n yield await this.applyEvent(sessionRun, event);\n }\n yield await this.applyEvent(sessionRun, {\n type: NcpEventType.RunStarted,\n payload: {\n messageId,\n runId: spec.runId,\n sessionId,\n correlationId: spec.correlationId,\n },\n });\n if (this.isAbortRequested(signal)) {\n yield await this.applyEvent(sessionRun, this.toAbortEvent(sessionId, messageId, spec));\n return;\n }\n\n while (!this.isAbortRequested(signal)) {\n const round = new DefaultNcpRoundCollector(this.reasoningNormalizationMode);\n const modelInput = await this.modelInputBuilder.build({\n spec,\n sessionId,\n messages: sessionRun.getSnapshot().messages,\n contextBlocks,\n tools,\n });\n if (this.isAbortRequested(signal)) {\n break;\n }\n\n const encoded = this.streamEncoder.encode(\n this.tapRuntimeStream(\n this.llmApi.generate(modelInput, { signal }),\n (chunk) => round.consumeChunk(chunk),\n signal,\n ),\n {\n sessionId,\n messageId,\n runId: spec.runId,\n correlationId: spec.correlationId,\n },\n );\n for await (const event of encoded) {\n if (this.isAbortRequested(signal)) {\n break;\n }\n yield await this.applyEvent(sessionRun, event);\n }\n if (this.isAbortRequested(signal)) {\n break;\n }\n\n const toolCalls = round.getToolCalls();\n for (const toolCall of toolCalls) {\n if (this.isAbortRequested(signal)) {\n break;\n }\n const toolResultEvent = await this.executeToolCall(tools, sessionId, spec, toolCall);\n if (this.isAbortRequested(signal)) {\n break;\n }\n yield await this.applyEvent(sessionRun, toolResultEvent);\n }\n if (this.isAbortRequested(signal)) {\n break;\n }\n\n const drainedInbox = this.drainInbox(sessionRun, spec);\n for (const event of drainedInbox.events) {\n if (this.isAbortRequested(signal)) {\n break;\n }\n yield await this.applyEvent(sessionRun, event);\n }\n if (this.isAbortRequested(signal)) {\n break;\n }\n if (toolCalls.length > 0 || drainedInbox.drained) {\n continue;\n }\n\n yield await this.applyEvent(sessionRun, {\n type: NcpEventType.RunFinished,\n payload: {\n messageId,\n runId: spec.runId,\n sessionId,\n correlationId: spec.correlationId,\n },\n });\n return;\n }\n\n yield await this.applyEvent(sessionRun, this.toAbortEvent(sessionId, messageId, spec));\n } catch (error) {\n if (this.isAbortRequested(signal)) {\n yield await this.applyEvent(sessionRun, this.toAbortEvent(sessionId, messageId, spec));\n return;\n }\n yield await this.applyEvent(sessionRun, {\n type: NcpEventType.RunError,\n payload: {\n sessionId,\n runId: spec.runId,\n correlationId: spec.correlationId,\n error: error instanceof Error ? error.message : String(error),\n },\n });\n }\n }\n\n private async *tapRuntimeStream(\n stream: AsyncIterable<OpenAIChatChunk>,\n consumeChunk: (chunk: OpenAIChatChunk) => void,\n signal?: AbortSignal,\n ): AsyncIterable<OpenAIChatChunk> {\n for await (const chunk of stream) {\n if (signal?.aborted) {\n break;\n }\n consumeChunk(chunk);\n yield chunk;\n if (signal?.aborted) {\n break;\n }\n }\n }\n\n private drainInbox = (\n sessionRun: AgentRuntimeSessionState,\n spec: DefaultNcpAgentRunSpec,\n ): InboxDrainResult => {\n const messages = sessionRun.inbox.drain();\n return {\n drained: messages.length > 0,\n events: messages.map((message) => ({\n type: NcpEventType.MessageSent,\n payload: {\n sessionId: sessionRun.sessionId,\n message,\n correlationId: spec.correlationId,\n },\n })),\n };\n };\n\n private isAbortRequested = (signal?: AbortSignal): boolean => signal?.aborted ?? false;\n\n private toAbortEvent = (\n sessionId: string,\n messageId: string,\n spec: DefaultNcpAgentRunSpec,\n ): NcpEndpointEvent => ({\n type: NcpEventType.MessageAbort,\n payload: {\n messageId,\n sessionId,\n correlationId: spec.correlationId,\n },\n });\n\n private applyEvent = async (\n sessionRun: AgentRuntimeSessionState,\n event: NcpEndpointEvent,\n ): Promise<NcpEndpointEvent> => {\n await sessionRun.applyEvents([event]);\n return event;\n };\n\n private executeToolCall = async (\n tools: readonly NcpTool[],\n sessionId: string,\n spec: DefaultNcpAgentRunSpec,\n toolCall: CollectedToolCall,\n ): Promise<NcpEndpointEvent> => {\n const tool = tools.find((candidate) => candidate.name === toolCall.toolName);\n const result = this.toolResultContentManager.normalizeToolCallResult(\n await executeCollectedToolCall({\n toolCall,\n tool,\n execute: (availableTool, args) => {\n if (!availableTool) {\n throw new Error(\"Tool is not available in this run.\");\n }\n return availableTool.execute(args);\n },\n }),\n );\n return {\n type: NcpEventType.MessageToolCallResult,\n payload: {\n sessionId,\n toolCallId: toolCall.toolCallId,\n correlationId: spec.correlationId,\n content: result.result,\n contentItems: result.contentItems,\n },\n };\n };\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nextclaw/ncp-agent-runtime-next",
|
|
3
|
+
"version": "0.0.1-beta.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Next-generation NCP agent runtime implementation for review before replacing @nextclaw/ncp-agent-runtime.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"development": "./src/index.ts",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@nextclaw/ncp": "0.5.18-beta.0",
|
|
19
|
+
"@nextclaw/ncp-agent-runtime": "0.3.29-beta.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^20.17.6",
|
|
23
|
+
"typescript": "^5.6.3"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsdown src/index.ts --dts.sourcemap --clean --target es2022 --no-fixedExtension",
|
|
27
|
+
"lint": "eslint .",
|
|
28
|
+
"tsc": "tsc -p tsconfig.json"
|
|
29
|
+
}
|
|
30
|
+
}
|