@meetopenbot/plugin-sdk 0.4.0 → 0.5.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/agent-plugin.d.ts +2 -2
- package/dist/agent-plugin.js +2 -2
- package/dist/mcp-agent.d.ts +15 -2
- package/dist/mcp-agent.d.ts.map +1 -1
- package/dist/mcp-agent.js +38 -4
- package/dist/mcp-agent.js.map +1 -1
- package/dist/text-reply.d.ts +39 -5
- package/dist/text-reply.d.ts.map +1 -1
- package/dist/text-reply.js +101 -6
- package/dist/text-reply.js.map +1 -1
- package/package.json +1 -1
package/dist/agent-plugin.d.ts
CHANGED
|
@@ -48,8 +48,8 @@ export declare function toAgentTurnEvents(item: AgentTurnYield | OpenBotEvent, a
|
|
|
48
48
|
* Define an agent plugin with a standard invoke loop.
|
|
49
49
|
*
|
|
50
50
|
* Handles `shouldHandleInvoke`, thread id, empty prompts, and a default catch.
|
|
51
|
-
* `run` may return a string, or yield `{ kind: 'reply', content }`
|
|
52
|
-
*
|
|
51
|
+
* `run` may return a string, or yield `{ kind: 'reply', content }` and
|
|
52
|
+
* `{ kind: 'widget' }` tool traces as the vendor stream lands (see `emitTextReplies`).
|
|
53
53
|
*/
|
|
54
54
|
export declare function defineAgentPlugin(definition: AgentPluginDefinition): Promise<PluginModule>;
|
|
55
55
|
//# sourceMappingURL=agent-plugin.d.ts.map
|
package/dist/agent-plugin.js
CHANGED
|
@@ -29,8 +29,8 @@ function errorText(error) {
|
|
|
29
29
|
* Define an agent plugin with a standard invoke loop.
|
|
30
30
|
*
|
|
31
31
|
* Handles `shouldHandleInvoke`, thread id, empty prompts, and a default catch.
|
|
32
|
-
* `run` may return a string, or yield `{ kind: 'reply', content }`
|
|
33
|
-
*
|
|
32
|
+
* `run` may return a string, or yield `{ kind: 'reply', content }` and
|
|
33
|
+
* `{ kind: 'widget' }` tool traces as the vendor stream lands (see `emitTextReplies`).
|
|
34
34
|
*/
|
|
35
35
|
export async function defineAgentPlugin(definition) {
|
|
36
36
|
const { emptyPrompt, run, onWidgetResponse, mapError, setup, models, configSchema, ...plugin } = definition;
|
package/dist/mcp-agent.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type AgentPluginDefinition } from './agent-plugin.js';
|
|
1
|
+
import { type AgentPluginDefinition, type AgentTurnYield } from './agent-plugin.js';
|
|
2
|
+
import { type StreamHint } from './text-reply.js';
|
|
2
3
|
import type { PluginModule } from './plugin.js';
|
|
3
4
|
export type McpHttpTransport = {
|
|
4
5
|
url: string;
|
|
@@ -10,6 +11,16 @@ export type McpStdioTransport = {
|
|
|
10
11
|
env?: (apiKey: string) => Record<string, string>;
|
|
11
12
|
};
|
|
12
13
|
export type McpTransport = McpHttpTransport | McpStdioTransport;
|
|
14
|
+
type McpStreamPart = {
|
|
15
|
+
type: string;
|
|
16
|
+
text?: string;
|
|
17
|
+
toolCallId?: string;
|
|
18
|
+
toolName?: string;
|
|
19
|
+
input?: unknown;
|
|
20
|
+
output?: unknown;
|
|
21
|
+
error?: unknown;
|
|
22
|
+
};
|
|
23
|
+
export declare function classifyMcpPart(part: McpStreamPart): StreamHint;
|
|
13
24
|
export declare function runMcpTurn(args: {
|
|
14
25
|
mcp: McpTransport;
|
|
15
26
|
apiKey: string;
|
|
@@ -18,7 +29,8 @@ export declare function runMcpTurn(args: {
|
|
|
18
29
|
prompt: string;
|
|
19
30
|
maxSteps?: number;
|
|
20
31
|
sanitizeEmptyArgs?: boolean;
|
|
21
|
-
|
|
32
|
+
groupId?: string;
|
|
33
|
+
}): AsyncGenerator<AgentTurnYield>;
|
|
22
34
|
export type McpAgentDefinition = Omit<AgentPluginDefinition, 'run'> & {
|
|
23
35
|
secret: {
|
|
24
36
|
envKeys: string[];
|
|
@@ -33,4 +45,5 @@ export type McpAgentDefinition = Omit<AgentPluginDefinition, 'run'> & {
|
|
|
33
45
|
* Specialist agent: secret + MCP + generateText. Model picker comes from `models`.
|
|
34
46
|
*/
|
|
35
47
|
export declare function defineMcpAgent(definition: McpAgentDefinition): Promise<PluginModule>;
|
|
48
|
+
export {};
|
|
36
49
|
//# sourceMappingURL=mcp-agent.d.ts.map
|
package/dist/mcp-agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-agent.d.ts","sourceRoot":"","sources":["../src/mcp-agent.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,qBAAqB,
|
|
1
|
+
{"version":3,"file":"mcp-agent.d.ts","sourceRoot":"","sources":["../src/mcp-agent.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAMhE,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,UAAU,CAsB/D;AAED,wBAAuB,UAAU,CAAC,IAAI,EAAE;IACtC,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,cAAc,CAAC,cAAc,CAAC,CA0CjC;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,qBAAqB,EAAE,KAAK,CAAC,GAAG;IACpE,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9B,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAqD1F"}
|
package/dist/mcp-agent.js
CHANGED
|
@@ -1,16 +1,42 @@
|
|
|
1
1
|
import { createMCPClient } from '@ai-sdk/mcp';
|
|
2
2
|
import { Experimental_StdioMCPTransport } from '@ai-sdk/mcp/mcp-stdio';
|
|
3
|
-
import {
|
|
3
|
+
import { stepCountIs, streamText } from 'ai';
|
|
4
4
|
import { creditsErrorMessage, hasLlmAuth, llmAuthNotConfiguredMessage, } from './credits-auth.js';
|
|
5
5
|
import { defineAgentPlugin, } from './agent-plugin.js';
|
|
6
6
|
import { lookupSecret, missingSecretMessage, readConfigModel } from './helpers.js';
|
|
7
7
|
import { wrapMcpTools } from './mcp-args.js';
|
|
8
8
|
import { resolveOpenAiModel } from './openai-model.js';
|
|
9
|
+
import { emitTextReplies, textReply } from './text-reply.js';
|
|
9
10
|
import { loadThreadContext } from './thread-context.js';
|
|
10
11
|
function isHttpTransport(transport) {
|
|
11
12
|
return 'url' in transport;
|
|
12
13
|
}
|
|
13
|
-
export
|
|
14
|
+
export function classifyMcpPart(part) {
|
|
15
|
+
if (part.type === 'text-delta' && part.text)
|
|
16
|
+
return { type: 'delta', text: part.text };
|
|
17
|
+
if (part.type === 'tool-call' && part.toolCallId) {
|
|
18
|
+
return {
|
|
19
|
+
type: 'tool_call',
|
|
20
|
+
id: part.toolCallId,
|
|
21
|
+
name: part.toolName ?? 'tool',
|
|
22
|
+
input: part.input,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if ((part.type === 'tool-result' || part.type === 'tool-error') && part.toolCallId) {
|
|
26
|
+
return {
|
|
27
|
+
type: 'tool_result',
|
|
28
|
+
id: part.toolCallId,
|
|
29
|
+
name: part.toolName,
|
|
30
|
+
input: part.input,
|
|
31
|
+
output: part.type === 'tool-error' ? part.error : part.output,
|
|
32
|
+
error: part.type === 'tool-error',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (part.type === 'finish-step' || part.type === 'finish')
|
|
36
|
+
return { type: 'flush' };
|
|
37
|
+
return { type: 'skip' };
|
|
38
|
+
}
|
|
39
|
+
export async function* runMcpTurn(args) {
|
|
14
40
|
const transport = isHttpTransport(args.mcp)
|
|
15
41
|
? {
|
|
16
42
|
type: 'http',
|
|
@@ -32,14 +58,21 @@ export async function runMcpTurn(args) {
|
|
|
32
58
|
let tools = await client.tools();
|
|
33
59
|
if (args.sanitizeEmptyArgs)
|
|
34
60
|
tools = wrapMcpTools(tools);
|
|
35
|
-
const result =
|
|
61
|
+
const result = streamText({
|
|
36
62
|
model: resolveOpenAiModel(args.model),
|
|
37
63
|
system: args.system,
|
|
38
64
|
prompt: args.prompt,
|
|
39
65
|
tools,
|
|
40
66
|
stopWhen: stepCountIs(args.maxSteps ?? 10),
|
|
41
67
|
});
|
|
42
|
-
|
|
68
|
+
let replied = false;
|
|
69
|
+
for await (const item of emitTextReplies(result.fullStream, classifyMcpPart, { groupId: args.groupId ?? 'mcp:tools' })) {
|
|
70
|
+
if (item.kind === 'reply')
|
|
71
|
+
replied = true;
|
|
72
|
+
yield item;
|
|
73
|
+
}
|
|
74
|
+
if (!replied)
|
|
75
|
+
yield textReply('Done.');
|
|
43
76
|
}
|
|
44
77
|
finally {
|
|
45
78
|
await client.close().catch(() => undefined);
|
|
@@ -79,6 +112,7 @@ export async function defineMcpAgent(definition) {
|
|
|
79
112
|
prompt,
|
|
80
113
|
maxSteps,
|
|
81
114
|
sanitizeEmptyArgs,
|
|
115
|
+
groupId: `${plugin.name}:tools`,
|
|
82
116
|
});
|
|
83
117
|
},
|
|
84
118
|
mapError: plugin.mapError ?? ((error) => ({
|
package/dist/mcp-agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-agent.js","sourceRoot":"","sources":["../src/mcp-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"mcp-agent.js","sourceRoot":"","sources":["../src/mcp-agent.ts"],"names":[],"mappings":"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"}
|
package/dist/text-reply.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentTurnYield } from './agent-plugin.js';
|
|
2
|
-
/** How a stream event maps onto a text reply. */
|
|
2
|
+
/** How a stream event maps onto a text reply or tool widget. */
|
|
3
3
|
export type TextReplyHint = {
|
|
4
4
|
type: 'delta';
|
|
5
5
|
text: string;
|
|
@@ -10,21 +10,55 @@ export type TextReplyHint = {
|
|
|
10
10
|
type: 'flush';
|
|
11
11
|
} | {
|
|
12
12
|
type: 'skip';
|
|
13
|
+
} | {
|
|
14
|
+
type: 'tool_call';
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
input?: unknown;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'tool_result';
|
|
20
|
+
id: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
input?: unknown;
|
|
23
|
+
output?: unknown;
|
|
24
|
+
error?: boolean;
|
|
25
|
+
};
|
|
26
|
+
export type StreamHint = TextReplyHint;
|
|
27
|
+
export type TextReplyBufferOptions = {
|
|
28
|
+
/** Stacks consecutive tool widgets in the client. Default `tools`. */
|
|
29
|
+
groupId?: string;
|
|
13
30
|
};
|
|
31
|
+
/** Pretty-print a tool argument or result for a message widget. */
|
|
32
|
+
export declare function formatToolValue(value: unknown, max?: number): string;
|
|
33
|
+
/** Message-widget body: input first, then output when the result has landed. */
|
|
34
|
+
export declare function formatToolCallBody(input?: unknown, output?: unknown): string;
|
|
14
35
|
/** `{ kind: 'reply' }` yield for `defineAgentPlugin`. */
|
|
15
36
|
export declare function textReply(content: string): AgentTurnYield;
|
|
37
|
+
/** Collapsed message widget for a vendor tool call. Same `id` updates in place. */
|
|
38
|
+
export declare function toolCall(args: {
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
input?: unknown;
|
|
42
|
+
output?: unknown;
|
|
43
|
+
error?: boolean;
|
|
44
|
+
groupId?: string;
|
|
45
|
+
}): AgentTurnYield;
|
|
16
46
|
/**
|
|
17
47
|
* Collect text deltas and emit one `{ kind: 'reply' }` per completed reply.
|
|
48
|
+
* Tool calls flush pending text, then yield a message widget; the matching
|
|
49
|
+
* `tool_result` reuses the same `widgetId` and appends the output.
|
|
18
50
|
*
|
|
19
51
|
* - `delta`: append to the current reply
|
|
20
52
|
* - `text`: complete snapshot — drop in-progress deltas and yield immediately
|
|
21
53
|
* - `flush`: yield collected deltas (reply boundary)
|
|
54
|
+
* - `tool_call`: flush text, then a widget with the tool name and input
|
|
55
|
+
* - `tool_result`: same widget with input + output
|
|
22
56
|
* - `skip`: ignore
|
|
23
57
|
*/
|
|
24
|
-
export declare function createTextReplyBuffer(): {
|
|
25
|
-
apply: (hint:
|
|
58
|
+
export declare function createTextReplyBuffer(options?: TextReplyBufferOptions): {
|
|
59
|
+
apply: (hint: StreamHint | readonly StreamHint[]) => Generator<AgentTurnYield>;
|
|
26
60
|
end: () => Generator<AgentTurnYield>;
|
|
27
61
|
};
|
|
28
|
-
/** Classify each stream event and yield completed text as
|
|
29
|
-
export declare function emitTextReplies<T>(events: AsyncIterable<T>, classify: (event: T) =>
|
|
62
|
+
/** Classify each stream event and yield completed text and tool widgets as they land. */
|
|
63
|
+
export declare function emitTextReplies<T>(events: AsyncIterable<T>, classify: (event: T) => StreamHint | readonly StreamHint[], options?: TextReplyBufferOptions): AsyncGenerator<AgentTurnYield>;
|
|
30
64
|
//# sourceMappingURL=text-reply.d.ts.map
|
package/dist/text-reply.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-reply.d.ts","sourceRoot":"","sources":["../src/text-reply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,
|
|
1
|
+
{"version":3,"file":"text-reply.d.ts","sourceRoot":"","sources":["../src/text-reply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,gEAAgE;AAChE,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE;IACE,IAAI,EAAE,aAAa,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEN,MAAM,MAAM,UAAU,GAAG,aAAa,CAAC;AAEvC,MAAM,MAAM,sBAAsB,GAAG;IACnC,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AASF,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,SAAmB,GAAG,MAAM,CAkB9E;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAK5E;AAED,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAEzD;AAED,mFAAmF;AACnF,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,cAAc,CAcjB;AAUD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,sBAAsB;kBAyD9C,UAAU,GAAG,SAAS,UAAU,EAAE,KAAG,SAAS,CAAC,cAAc,CAAC;eAKnE,SAAS,CAAC,cAAc,CAAC;EAK3C;AAED,yFAAyF;AACzF,wBAAuB,eAAe,CAAC,CAAC,EACtC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,UAAU,GAAG,SAAS,UAAU,EAAE,EAC1D,OAAO,CAAC,EAAE,sBAAsB,GAC/B,cAAc,CAAC,cAAc,CAAC,CAMhC"}
|
package/dist/text-reply.js
CHANGED
|
@@ -1,18 +1,80 @@
|
|
|
1
|
+
const DEFAULT_GROUP_ID = 'tools';
|
|
2
|
+
const MAX_INPUT_CHARS = 8_000;
|
|
3
|
+
const MAX_OUTPUT_CHARS = 12_000;
|
|
4
|
+
const truncate = (text, max) => text.length > max ? `${text.slice(0, max)}\n…` : text;
|
|
5
|
+
/** Pretty-print a tool argument or result for a message widget. */
|
|
6
|
+
export function formatToolValue(value, max = MAX_OUTPUT_CHARS) {
|
|
7
|
+
if (value == null)
|
|
8
|
+
return '';
|
|
9
|
+
if (typeof value === 'string')
|
|
10
|
+
return truncate(value, max);
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
const texts = [];
|
|
13
|
+
for (const block of value) {
|
|
14
|
+
if (block && typeof block === 'object' && block.type === 'text') {
|
|
15
|
+
const text = block.text;
|
|
16
|
+
if (typeof text === 'string' && text)
|
|
17
|
+
texts.push(text);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (texts.length > 0)
|
|
21
|
+
return truncate(texts.join('\n'), max);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return truncate(JSON.stringify(value, null, 2), max);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return truncate(String(value), max);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Message-widget body: input first, then output when the result has landed. */
|
|
31
|
+
export function formatToolCallBody(input, output) {
|
|
32
|
+
const inputText = formatToolValue(input, MAX_INPUT_CHARS) || '{}';
|
|
33
|
+
if (output === undefined)
|
|
34
|
+
return `Input:\n${inputText}`;
|
|
35
|
+
const outputText = formatToolValue(output, MAX_OUTPUT_CHARS) || '(no output)';
|
|
36
|
+
return `Input:\n${inputText}\n\nOutput:\n${outputText}`;
|
|
37
|
+
}
|
|
1
38
|
/** `{ kind: 'reply' }` yield for `defineAgentPlugin`. */
|
|
2
39
|
export function textReply(content) {
|
|
3
40
|
return { kind: 'reply', content };
|
|
4
41
|
}
|
|
42
|
+
/** Collapsed message widget for a vendor tool call. Same `id` updates in place. */
|
|
43
|
+
export function toolCall(args) {
|
|
44
|
+
const done = args.output !== undefined || args.error;
|
|
45
|
+
return {
|
|
46
|
+
kind: 'widget',
|
|
47
|
+
widget: {
|
|
48
|
+
kind: 'message',
|
|
49
|
+
display: 'collapsed',
|
|
50
|
+
widgetId: args.id,
|
|
51
|
+
groupId: args.groupId ?? DEFAULT_GROUP_ID,
|
|
52
|
+
title: args.name,
|
|
53
|
+
body: formatToolCallBody(args.input, args.output),
|
|
54
|
+
...(done ? { state: args.error ? 'error' : 'submitted' } : {}),
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function isTextHint(hint) {
|
|
59
|
+
return (hint.type === 'delta' || hint.type === 'text' || hint.type === 'flush' || hint.type === 'skip');
|
|
60
|
+
}
|
|
5
61
|
/**
|
|
6
62
|
* Collect text deltas and emit one `{ kind: 'reply' }` per completed reply.
|
|
63
|
+
* Tool calls flush pending text, then yield a message widget; the matching
|
|
64
|
+
* `tool_result` reuses the same `widgetId` and appends the output.
|
|
7
65
|
*
|
|
8
66
|
* - `delta`: append to the current reply
|
|
9
67
|
* - `text`: complete snapshot — drop in-progress deltas and yield immediately
|
|
10
68
|
* - `flush`: yield collected deltas (reply boundary)
|
|
69
|
+
* - `tool_call`: flush text, then a widget with the tool name and input
|
|
70
|
+
* - `tool_result`: same widget with input + output
|
|
11
71
|
* - `skip`: ignore
|
|
12
72
|
*/
|
|
13
|
-
export function createTextReplyBuffer() {
|
|
73
|
+
export function createTextReplyBuffer(options) {
|
|
74
|
+
const groupId = options?.groupId ?? DEFAULT_GROUP_ID;
|
|
14
75
|
let buffer = '';
|
|
15
|
-
|
|
76
|
+
const pending = new Map();
|
|
77
|
+
function* applyText(hint) {
|
|
16
78
|
switch (hint.type) {
|
|
17
79
|
case 'delta': {
|
|
18
80
|
if (hint.text)
|
|
@@ -37,14 +99,47 @@ export function createTextReplyBuffer() {
|
|
|
37
99
|
return;
|
|
38
100
|
}
|
|
39
101
|
}
|
|
102
|
+
function* applyOne(hint) {
|
|
103
|
+
if (isTextHint(hint)) {
|
|
104
|
+
yield* applyText(hint);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (hint.type === 'tool_call') {
|
|
108
|
+
yield* applyText({ type: 'flush' });
|
|
109
|
+
pending.set(hint.id, { name: hint.name, input: hint.input });
|
|
110
|
+
yield toolCall({
|
|
111
|
+
id: hint.id,
|
|
112
|
+
name: hint.name,
|
|
113
|
+
input: hint.input,
|
|
114
|
+
groupId,
|
|
115
|
+
});
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
yield* applyText({ type: 'flush' });
|
|
119
|
+
const prev = pending.get(hint.id);
|
|
120
|
+
pending.delete(hint.id);
|
|
121
|
+
yield toolCall({
|
|
122
|
+
id: hint.id,
|
|
123
|
+
name: hint.name ?? prev?.name ?? 'tool',
|
|
124
|
+
input: hint.input ?? prev?.input,
|
|
125
|
+
output: hint.output,
|
|
126
|
+
error: hint.error,
|
|
127
|
+
groupId,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function* apply(hint) {
|
|
131
|
+
const hints = Array.isArray(hint) ? hint : [hint];
|
|
132
|
+
for (const item of hints)
|
|
133
|
+
yield* applyOne(item);
|
|
134
|
+
}
|
|
40
135
|
function* end() {
|
|
41
|
-
yield*
|
|
136
|
+
yield* applyText({ type: 'flush' });
|
|
42
137
|
}
|
|
43
138
|
return { apply, end };
|
|
44
139
|
}
|
|
45
|
-
/** Classify each stream event and yield completed text as
|
|
46
|
-
export async function* emitTextReplies(events, classify) {
|
|
47
|
-
const replies = createTextReplyBuffer();
|
|
140
|
+
/** Classify each stream event and yield completed text and tool widgets as they land. */
|
|
141
|
+
export async function* emitTextReplies(events, classify, options) {
|
|
142
|
+
const replies = createTextReplyBuffer(options);
|
|
48
143
|
for await (const event of events) {
|
|
49
144
|
yield* replies.apply(classify(event));
|
|
50
145
|
}
|
package/dist/text-reply.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-reply.js","sourceRoot":"","sources":["../src/text-reply.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"text-reply.js","sourceRoot":"","sources":["../src/text-reply.ts"],"names":[],"mappings":"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"}
|