@nextclaw/ncp-agent-runtime 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +314 -56
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -67,6 +67,7 @@ declare class DefaultNcpAgentRuntime implements NcpAgentRuntime {
|
|
|
67
67
|
* The stream encoder does not emit RunFinished; it only converts chunks to NCP events.
|
|
68
68
|
*/
|
|
69
69
|
private runLoop;
|
|
70
|
+
private tapStream;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
export { DefaultNcpAgentRuntime, type DefaultNcpAgentRuntimeConfig, DefaultNcpContextBuilder, DefaultNcpRoundBuffer, DefaultNcpStreamEncoder, DefaultNcpToolRegistry, EchoNcpLLMApi };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,35 @@
|
|
|
1
1
|
// src/context-builder.ts
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function readOptionalString(value) {
|
|
6
|
+
if (typeof value !== "string") {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
const trimmed = value.trim();
|
|
10
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
11
|
+
}
|
|
12
|
+
function mergeMessageAndRequestMetadata(input) {
|
|
13
|
+
const messageMetadata = input.messages.slice().reverse().find((message) => isRecord(message.metadata))?.metadata;
|
|
14
|
+
return {
|
|
15
|
+
...isRecord(messageMetadata) ? messageMetadata : {},
|
|
16
|
+
...isRecord(input.metadata) ? input.metadata : {}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function readRequestedToolNames(metadata) {
|
|
20
|
+
const raw = metadata.requested_tools ?? metadata.requestedTools ?? metadata.requested_skills ?? metadata.requestedSkills;
|
|
21
|
+
if (!Array.isArray(raw)) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const deduped = /* @__PURE__ */ new Set();
|
|
25
|
+
for (const item of raw) {
|
|
26
|
+
const value = readOptionalString(item);
|
|
27
|
+
if (value) {
|
|
28
|
+
deduped.add(value);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return [...deduped];
|
|
32
|
+
}
|
|
2
33
|
function messageToOpenAI(msg) {
|
|
3
34
|
const role = msg.role;
|
|
4
35
|
const parts = msg.parts ?? [];
|
|
@@ -8,8 +39,12 @@ function messageToOpenAI(msg) {
|
|
|
8
39
|
}
|
|
9
40
|
if (role === "assistant") {
|
|
10
41
|
const texts = [];
|
|
42
|
+
const reasonings = [];
|
|
11
43
|
const toolInvocations = [];
|
|
12
44
|
for (const p of parts) {
|
|
45
|
+
if (p.type === "reasoning") {
|
|
46
|
+
reasonings.push(p.text);
|
|
47
|
+
}
|
|
13
48
|
if (p.type === "text") {
|
|
14
49
|
texts.push(p.text);
|
|
15
50
|
}
|
|
@@ -23,11 +58,13 @@ function messageToOpenAI(msg) {
|
|
|
23
58
|
}
|
|
24
59
|
}
|
|
25
60
|
const text = texts.join("");
|
|
61
|
+
const reasoning = reasonings.join("");
|
|
26
62
|
const out = [];
|
|
27
63
|
if (toolInvocations.length > 0) {
|
|
28
64
|
out.push({
|
|
29
65
|
role: "assistant",
|
|
30
66
|
content: text || null,
|
|
67
|
+
...reasoning ? { reasoning_content: reasoning } : {},
|
|
31
68
|
tool_calls: toolInvocations.map((t) => ({
|
|
32
69
|
id: t.toolCallId,
|
|
33
70
|
type: "function",
|
|
@@ -45,7 +82,11 @@ function messageToOpenAI(msg) {
|
|
|
45
82
|
});
|
|
46
83
|
}
|
|
47
84
|
} else {
|
|
48
|
-
out.push({
|
|
85
|
+
out.push({
|
|
86
|
+
role: "assistant",
|
|
87
|
+
content: text,
|
|
88
|
+
...reasoning ? { reasoning_content: reasoning } : {}
|
|
89
|
+
});
|
|
49
90
|
}
|
|
50
91
|
return out;
|
|
51
92
|
}
|
|
@@ -59,6 +100,8 @@ var DefaultNcpContextBuilder = class {
|
|
|
59
100
|
const maxMessages = options?.maxMessages ?? 50;
|
|
60
101
|
const sessionMessages = options?.sessionMessages ?? [];
|
|
61
102
|
const systemPrompt = options?.systemPrompt;
|
|
103
|
+
const requestMetadata = mergeMessageAndRequestMetadata(input);
|
|
104
|
+
const requestedToolNames = readRequestedToolNames(requestMetadata);
|
|
62
105
|
const messages = [];
|
|
63
106
|
if (systemPrompt) {
|
|
64
107
|
messages.push({ role: "system", content: systemPrompt });
|
|
@@ -69,17 +112,21 @@ var DefaultNcpContextBuilder = class {
|
|
|
69
112
|
for (const msg of input.messages) {
|
|
70
113
|
messages.push(...messageToOpenAI(msg));
|
|
71
114
|
}
|
|
72
|
-
const
|
|
115
|
+
const toolDefinitions = this.toolRegistry?.getToolDefinitions() ?? [];
|
|
116
|
+
const filteredToolDefinitions = requestedToolNames.length > 0 ? toolDefinitions.filter((definition) => requestedToolNames.includes(definition.name)) : toolDefinitions;
|
|
117
|
+
const tools = filteredToolDefinitions.map((definition) => ({
|
|
73
118
|
type: "function",
|
|
74
119
|
function: {
|
|
75
|
-
name:
|
|
76
|
-
description:
|
|
77
|
-
parameters:
|
|
120
|
+
name: definition.name,
|
|
121
|
+
description: definition.description,
|
|
122
|
+
parameters: definition.parameters
|
|
78
123
|
}
|
|
79
|
-
}))
|
|
124
|
+
}));
|
|
80
125
|
return {
|
|
81
126
|
messages,
|
|
82
|
-
tools: tools && tools.length > 0 ? tools : void 0
|
|
127
|
+
tools: tools && tools.length > 0 ? tools : void 0,
|
|
128
|
+
model: readOptionalString(requestMetadata.model) ?? readOptionalString(requestMetadata.llm_model) ?? readOptionalString(requestMetadata.agent_model) ?? void 0,
|
|
129
|
+
thinkingLevel: readOptionalString(requestMetadata.thinking) ?? readOptionalString(requestMetadata.thinking_level) ?? readOptionalString(requestMetadata.thinkingLevel) ?? readOptionalString(requestMetadata.thinking_effort) ?? readOptionalString(requestMetadata.thinkingEffort) ?? null
|
|
83
130
|
};
|
|
84
131
|
};
|
|
85
132
|
};
|
|
@@ -206,9 +253,9 @@ var DefaultNcpStreamEncoder = class {
|
|
|
206
253
|
if (!choice) continue;
|
|
207
254
|
const delta = choice.delta;
|
|
208
255
|
if (delta) {
|
|
256
|
+
yield* emitReasoningDelta(delta, { sessionId, messageId });
|
|
209
257
|
const nextState = yield* emitTextDeltas(delta, { sessionId, messageId }, state);
|
|
210
258
|
state = nextState;
|
|
211
|
-
yield* emitReasoningDelta(delta, { sessionId, messageId });
|
|
212
259
|
yield* emitToolCallDeltas(delta, toolCallBuffers, { sessionId, messageId });
|
|
213
260
|
}
|
|
214
261
|
const finishReason = choice.finish_reason;
|
|
@@ -296,26 +343,162 @@ import {
|
|
|
296
343
|
function genId() {
|
|
297
344
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
|
|
298
345
|
}
|
|
299
|
-
function
|
|
346
|
+
function stringifyRawArgs(args) {
|
|
300
347
|
if (typeof args === "string") {
|
|
348
|
+
return args;
|
|
349
|
+
}
|
|
350
|
+
if (args && typeof args === "object" && !Array.isArray(args)) {
|
|
301
351
|
try {
|
|
302
|
-
return JSON.
|
|
352
|
+
return JSON.stringify(args);
|
|
303
353
|
} catch {
|
|
304
|
-
return
|
|
354
|
+
return "[unserializable-object]";
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return String(args ?? "");
|
|
358
|
+
}
|
|
359
|
+
function parseToolArgs(args) {
|
|
360
|
+
if (args && typeof args === "object" && !Array.isArray(args)) {
|
|
361
|
+
return {
|
|
362
|
+
ok: true,
|
|
363
|
+
rawText: stringifyRawArgs(args),
|
|
364
|
+
value: args
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
const rawText = stringifyRawArgs(args);
|
|
368
|
+
if (typeof args !== "string") {
|
|
369
|
+
return {
|
|
370
|
+
ok: false,
|
|
371
|
+
rawText,
|
|
372
|
+
issues: ["Tool arguments must be a JSON object string."]
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
const trimmed = args.trim();
|
|
376
|
+
if (!trimmed) {
|
|
377
|
+
return {
|
|
378
|
+
ok: false,
|
|
379
|
+
rawText,
|
|
380
|
+
issues: ["Tool arguments are empty."]
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
try {
|
|
384
|
+
const parsed = JSON.parse(trimmed);
|
|
385
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
386
|
+
return {
|
|
387
|
+
ok: false,
|
|
388
|
+
rawText,
|
|
389
|
+
issues: ["Tool arguments JSON must decode to an object."]
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
ok: true,
|
|
394
|
+
rawText,
|
|
395
|
+
value: parsed
|
|
396
|
+
};
|
|
397
|
+
} catch (error) {
|
|
398
|
+
return {
|
|
399
|
+
ok: false,
|
|
400
|
+
rawText,
|
|
401
|
+
issues: [error instanceof Error ? error.message : "Failed to parse tool arguments JSON."]
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function validateToolArgs(args, schema) {
|
|
406
|
+
if (!schema) {
|
|
407
|
+
return [];
|
|
408
|
+
}
|
|
409
|
+
return validateToolValue(args, schema, "");
|
|
410
|
+
}
|
|
411
|
+
function validateToolValue(value, schema, path) {
|
|
412
|
+
const label = path || "parameter";
|
|
413
|
+
const type = typeof schema.type === "string" ? schema.type : void 0;
|
|
414
|
+
if (type && !matchesSchemaType(value, type)) {
|
|
415
|
+
return [`${label} should be ${type}`];
|
|
416
|
+
}
|
|
417
|
+
const errors = [];
|
|
418
|
+
if (schema.enum && !schema.enum.includes(value)) {
|
|
419
|
+
errors.push(`${label} must be one of ${JSON.stringify(schema.enum)}`);
|
|
420
|
+
}
|
|
421
|
+
if (typeof value === "number") {
|
|
422
|
+
if (schema.minimum !== void 0 && value < schema.minimum) {
|
|
423
|
+
errors.push(`${label} must be >= ${schema.minimum}`);
|
|
305
424
|
}
|
|
425
|
+
if (schema.maximum !== void 0 && value > schema.maximum) {
|
|
426
|
+
errors.push(`${label} must be <= ${schema.maximum}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (typeof value === "string") {
|
|
430
|
+
if (schema.minLength !== void 0 && value.length < schema.minLength) {
|
|
431
|
+
errors.push(`${label} must be at least ${schema.minLength} chars`);
|
|
432
|
+
}
|
|
433
|
+
if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
|
|
434
|
+
errors.push(`${label} must be at most ${schema.maxLength} chars`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (type === "object") {
|
|
438
|
+
const objectValue = value;
|
|
439
|
+
for (const key of schema.required ?? []) {
|
|
440
|
+
if (!(key in objectValue)) {
|
|
441
|
+
errors.push(`missing required ${path ? `${path}.${key}` : key}`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
const properties = schema.properties ?? {};
|
|
445
|
+
for (const [key, childValue] of Object.entries(objectValue)) {
|
|
446
|
+
const childSchema = properties[key];
|
|
447
|
+
if (!childSchema) {
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
errors.push(...validateToolValue(childValue, childSchema, path ? `${path}.${key}` : key));
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (type === "array" && schema.items && Array.isArray(value)) {
|
|
454
|
+
value.forEach((item, index) => {
|
|
455
|
+
errors.push(...validateToolValue(item, schema.items, `${label}[${index}]`));
|
|
456
|
+
});
|
|
306
457
|
}
|
|
307
|
-
return
|
|
458
|
+
return errors;
|
|
308
459
|
}
|
|
309
|
-
function
|
|
460
|
+
function matchesSchemaType(value, type) {
|
|
461
|
+
switch (type) {
|
|
462
|
+
case "string":
|
|
463
|
+
return typeof value === "string";
|
|
464
|
+
case "integer":
|
|
465
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
466
|
+
case "number":
|
|
467
|
+
return typeof value === "number";
|
|
468
|
+
case "boolean":
|
|
469
|
+
return typeof value === "boolean";
|
|
470
|
+
case "array":
|
|
471
|
+
return Array.isArray(value);
|
|
472
|
+
case "object":
|
|
473
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
474
|
+
default:
|
|
475
|
+
return true;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
function createInvalidToolArgumentsResult(params) {
|
|
479
|
+
return {
|
|
480
|
+
ok: false,
|
|
481
|
+
error: {
|
|
482
|
+
code: "invalid_tool_arguments",
|
|
483
|
+
message: "Tool arguments are invalid.",
|
|
484
|
+
toolCallId: params.toolCallId,
|
|
485
|
+
toolName: params.toolName,
|
|
486
|
+
rawArgumentsText: params.rawArgumentsText,
|
|
487
|
+
issues: params.issues
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
function appendToolRoundToInput(input, reasoning, text, toolResults) {
|
|
310
492
|
const assistantMsg = {
|
|
311
493
|
role: "assistant",
|
|
312
494
|
content: text || null,
|
|
495
|
+
...reasoning ? { reasoning_content: reasoning } : {},
|
|
313
496
|
tool_calls: toolResults.map((tr) => ({
|
|
314
497
|
id: tr.toolCallId,
|
|
315
498
|
type: "function",
|
|
316
499
|
function: {
|
|
317
500
|
name: tr.toolName,
|
|
318
|
-
arguments:
|
|
501
|
+
arguments: tr.rawArgsText
|
|
319
502
|
}
|
|
320
503
|
}))
|
|
321
504
|
};
|
|
@@ -330,6 +513,66 @@ function appendToolRoundToInput(input, text, toolResults) {
|
|
|
330
513
|
};
|
|
331
514
|
}
|
|
332
515
|
|
|
516
|
+
// src/round-collector.ts
|
|
517
|
+
var DefaultNcpRoundCollector = class {
|
|
518
|
+
text = "";
|
|
519
|
+
reasoning = "";
|
|
520
|
+
toolCallBuffers = /* @__PURE__ */ new Map();
|
|
521
|
+
clear() {
|
|
522
|
+
this.text = "";
|
|
523
|
+
this.reasoning = "";
|
|
524
|
+
this.toolCallBuffers.clear();
|
|
525
|
+
}
|
|
526
|
+
consumeChunk(chunk) {
|
|
527
|
+
const choice = chunk.choices?.[0];
|
|
528
|
+
if (!choice) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const delta = choice.delta;
|
|
532
|
+
if (!delta) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
536
|
+
this.text += delta.content;
|
|
537
|
+
}
|
|
538
|
+
const reasoning = delta.reasoning_content ?? delta.reasoning;
|
|
539
|
+
if (typeof reasoning === "string" && reasoning.length > 0) {
|
|
540
|
+
this.reasoning += reasoning;
|
|
541
|
+
}
|
|
542
|
+
const toolDeltas = delta.tool_calls;
|
|
543
|
+
if (!Array.isArray(toolDeltas)) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
for (const toolDelta of toolDeltas) {
|
|
547
|
+
const index = getToolCallIndex(toolDelta, this.toolCallBuffers.size);
|
|
548
|
+
const previous = this.toolCallBuffers.get(index) ?? { argumentsText: "" };
|
|
549
|
+
const current = applyToolDelta(previous, toolDelta);
|
|
550
|
+
this.toolCallBuffers.set(index, current);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
getText() {
|
|
554
|
+
return this.text;
|
|
555
|
+
}
|
|
556
|
+
getReasoning() {
|
|
557
|
+
return this.reasoning;
|
|
558
|
+
}
|
|
559
|
+
getToolCalls() {
|
|
560
|
+
const orderedEntries = Array.from(this.toolCallBuffers.entries()).sort(([left], [right]) => left - right);
|
|
561
|
+
const toolCalls = [];
|
|
562
|
+
for (const [, buffer] of orderedEntries) {
|
|
563
|
+
if (!buffer.id || !buffer.name) {
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
toolCalls.push({
|
|
567
|
+
toolCallId: buffer.id,
|
|
568
|
+
toolName: buffer.name,
|
|
569
|
+
args: buffer.argumentsText
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
return toolCalls;
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
333
576
|
// src/runtime.ts
|
|
334
577
|
var DefaultNcpAgentRuntime = class {
|
|
335
578
|
contextBuilder;
|
|
@@ -379,55 +622,63 @@ var DefaultNcpAgentRuntime = class {
|
|
|
379
622
|
* The stream encoder does not emit RunFinished; it only converts chunks to NCP events.
|
|
380
623
|
*/
|
|
381
624
|
async *runLoop(llmInput, ctx, options) {
|
|
382
|
-
const
|
|
625
|
+
const roundCollector = new DefaultNcpRoundCollector();
|
|
383
626
|
let currentInput = llmInput;
|
|
384
627
|
let done = false;
|
|
385
628
|
while (!done && !options?.signal?.aborted) {
|
|
386
|
-
|
|
629
|
+
roundCollector.clear();
|
|
387
630
|
const stream = this.llmApi.generate(currentInput, { signal: options?.signal });
|
|
388
|
-
|
|
631
|
+
const tappedStream = this.tapStream(stream, (chunk) => roundCollector.consumeChunk(chunk));
|
|
632
|
+
for await (const event of this.streamEncoder.encode(tappedStream, ctx)) {
|
|
389
633
|
yield event;
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
}
|
|
421
|
-
break;
|
|
634
|
+
}
|
|
635
|
+
const toolResults = [];
|
|
636
|
+
for (const toolCall of roundCollector.getToolCalls()) {
|
|
637
|
+
const tool = this.toolRegistry.getTool(toolCall.toolName);
|
|
638
|
+
const parsedArgs = parseToolArgs(toolCall.args);
|
|
639
|
+
let result;
|
|
640
|
+
let args = null;
|
|
641
|
+
if (!parsedArgs.ok) {
|
|
642
|
+
result = createInvalidToolArgumentsResult({
|
|
643
|
+
toolCallId: toolCall.toolCallId,
|
|
644
|
+
toolName: toolCall.toolName,
|
|
645
|
+
rawArgumentsText: parsedArgs.rawText,
|
|
646
|
+
issues: parsedArgs.issues
|
|
647
|
+
});
|
|
648
|
+
} else {
|
|
649
|
+
const schemaIssues = validateToolArgs(parsedArgs.value, tool?.parameters);
|
|
650
|
+
if (schemaIssues.length > 0) {
|
|
651
|
+
result = createInvalidToolArgumentsResult({
|
|
652
|
+
toolCallId: toolCall.toolCallId,
|
|
653
|
+
toolName: toolCall.toolName,
|
|
654
|
+
rawArgumentsText: parsedArgs.rawText,
|
|
655
|
+
issues: schemaIssues
|
|
656
|
+
});
|
|
657
|
+
} else {
|
|
658
|
+
args = parsedArgs.value;
|
|
659
|
+
result = await this.toolRegistry.execute(
|
|
660
|
+
toolCall.toolCallId,
|
|
661
|
+
toolCall.toolName,
|
|
662
|
+
parsedArgs.value
|
|
663
|
+
);
|
|
422
664
|
}
|
|
423
|
-
case NcpEventType3.MessageTextDelta:
|
|
424
|
-
roundBuffer.appendText(event.payload.delta);
|
|
425
|
-
break;
|
|
426
|
-
default:
|
|
427
|
-
break;
|
|
428
665
|
}
|
|
666
|
+
toolResults.push({
|
|
667
|
+
toolCallId: toolCall.toolCallId,
|
|
668
|
+
toolName: toolCall.toolName,
|
|
669
|
+
args,
|
|
670
|
+
rawArgsText: parsedArgs.rawText,
|
|
671
|
+
result
|
|
672
|
+
});
|
|
673
|
+
yield {
|
|
674
|
+
type: NcpEventType3.MessageToolCallResult,
|
|
675
|
+
payload: {
|
|
676
|
+
sessionId: ctx.sessionId,
|
|
677
|
+
toolCallId: toolCall.toolCallId,
|
|
678
|
+
content: result
|
|
679
|
+
}
|
|
680
|
+
};
|
|
429
681
|
}
|
|
430
|
-
const toolResults = roundBuffer.getToolCalls();
|
|
431
682
|
if (toolResults.length === 0) {
|
|
432
683
|
yield {
|
|
433
684
|
type: NcpEventType3.RunFinished,
|
|
@@ -438,11 +689,18 @@ var DefaultNcpAgentRuntime = class {
|
|
|
438
689
|
}
|
|
439
690
|
currentInput = appendToolRoundToInput(
|
|
440
691
|
currentInput,
|
|
441
|
-
|
|
692
|
+
roundCollector.getReasoning(),
|
|
693
|
+
roundCollector.getText(),
|
|
442
694
|
toolResults
|
|
443
695
|
);
|
|
444
696
|
}
|
|
445
697
|
}
|
|
698
|
+
async *tapStream(stream, onChunk) {
|
|
699
|
+
for await (const chunk of stream) {
|
|
700
|
+
onChunk(chunk);
|
|
701
|
+
yield chunk;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
446
704
|
};
|
|
447
705
|
export {
|
|
448
706
|
DefaultNcpAgentRuntime,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/ncp-agent-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Default agent runtime implementation built on NCP interfaces.",
|
|
6
6
|
"type": "module",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@nextclaw/ncp": "0.
|
|
18
|
+
"@nextclaw/ncp": "0.3.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/node": "^20.17.6",
|