modular-voice-agent-sdk 2.4.0 → 2.5.1

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.
Files changed (30) hide show
  1. package/README.md +4 -0
  2. package/dist/backends/agent/index.d.ts +16 -0
  3. package/dist/backends/agent/index.d.ts.map +1 -0
  4. package/dist/backends/agent/index.js +14 -0
  5. package/dist/backends/agent/index.js.map +1 -0
  6. package/dist/backends/agent/llm.d.ts +40 -0
  7. package/dist/backends/agent/llm.d.ts.map +1 -0
  8. package/dist/backends/agent/llm.js +110 -0
  9. package/dist/backends/agent/llm.js.map +1 -0
  10. package/dist/backends/agent/opencode-provider.d.ts +94 -0
  11. package/dist/backends/agent/opencode-provider.d.ts.map +1 -0
  12. package/dist/backends/agent/opencode-provider.js +169 -0
  13. package/dist/backends/agent/opencode-provider.js.map +1 -0
  14. package/dist/backends/agent/pi-agent-provider.d.ts +76 -0
  15. package/dist/backends/agent/pi-agent-provider.d.ts.map +1 -0
  16. package/dist/backends/agent/pi-agent-provider.js +149 -0
  17. package/dist/backends/agent/pi-agent-provider.js.map +1 -0
  18. package/dist/backends/agent/pi-coding-agent-provider.d.ts +87 -0
  19. package/dist/backends/agent/pi-coding-agent-provider.d.ts.map +1 -0
  20. package/dist/backends/agent/pi-coding-agent-provider.js +156 -0
  21. package/dist/backends/agent/pi-coding-agent-provider.js.map +1 -0
  22. package/dist/backends/agent/provider.d.ts +61 -0
  23. package/dist/backends/agent/provider.d.ts.map +1 -0
  24. package/dist/backends/agent/provider.js +11 -0
  25. package/dist/backends/agent/provider.js.map +1 -0
  26. package/dist/server/index.d.ts +1 -1
  27. package/dist/server/index.d.ts.map +1 -1
  28. package/dist/server/index.js +1 -1
  29. package/dist/server/index.js.map +1 -1
  30. package/package.json +22 -2
package/README.md CHANGED
@@ -53,6 +53,9 @@ Each component can run in the browser, on a server, or in the cloud. Pick any fr
53
53
  N/A ☁️ Cloud Audio LLM N/A
54
54
  (GPT Audio, multimodal)
55
55
 
56
+ N/A 🤖 Agent SDK N/A
57
+ (OpenCode, Pi Agent)
58
+
56
59
  ```
57
60
 
58
61
  Want browser speech recognition + a cloud LLM + browser speech synthesis? Done. Want everything running locally on your server with native binaries? Also done. Same code structure, same events, different backends.
@@ -61,6 +64,7 @@ Want browser speech recognition + a cloud LLM + browser speech synthesis? Done.
61
64
 
62
65
  - **Streaming** — responses stream token-by-token to TTS
63
66
  - **Function calling** — tools work across all LLM backends (cloud, native, transformers)
67
+ - **Agent SDK support** — wrap coding agents (OpenCode, Pi Agent) as voice-controlled backends
64
68
  - **Conversation history** — automatic context management
65
69
  - **Hybrid configs** — mix browser and server components freely
66
70
 
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Agent Backend - Agent SDK support
3
+ * Wraps coding agent SDKs (OpenCode, Pi Agent, Pi Coding Agent, etc.) as LLM backends.
4
+ *
5
+ * The agent handles tool execution internally — the voice pipeline
6
+ * only receives text responses and tool activity notifications.
7
+ */
8
+ export { AgentLLM } from './llm';
9
+ export type { AgentProvider, AgentSession, AgentStreamEvent } from './provider';
10
+ export { OpenCodeAgentProvider } from './opencode-provider';
11
+ export type { OpenCodeAgentProviderConfig, OpenCodeClient } from './opencode-provider';
12
+ export { PiAgentProvider } from './pi-agent-provider';
13
+ export type { PiAgentProviderConfig, PiAgent } from './pi-agent-provider';
14
+ export { PiCodingAgentProvider } from './pi-coding-agent-provider';
15
+ export type { PiCodingAgentProviderConfig, PiCodingAgentSession } from './pi-coding-agent-provider';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/backends/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGhF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EAAE,2BAA2B,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEvF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Agent Backend - Agent SDK support
3
+ * Wraps coding agent SDKs (OpenCode, Pi Agent, Pi Coding Agent, etc.) as LLM backends.
4
+ *
5
+ * The agent handles tool execution internally — the voice pipeline
6
+ * only receives text responses and tool activity notifications.
7
+ */
8
+ // Core
9
+ export { AgentLLM } from './llm';
10
+ // Providers
11
+ export { OpenCodeAgentProvider } from './opencode-provider';
12
+ export { PiAgentProvider } from './pi-agent-provider';
13
+ export { PiCodingAgentProvider } from './pi-coding-agent-provider';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/backends/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO;AACP,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjC,YAAY;AACZ,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Agent LLM Pipeline
3
+ * Wraps agent SDKs (OpenCode, Pi Agent, etc.) as an LLMPipeline backend.
4
+ *
5
+ * Unlike CloudLLM which makes raw API calls and lets the voice pipeline handle
6
+ * tool execution, AgentLLM delegates to an agent SDK that manages its own
7
+ * tool execution loop internally. From the voice pipeline's perspective,
8
+ * this backend always returns finishReason: 'stop' — the tool loop is
9
+ * handled entirely within the agent.
10
+ *
11
+ * Tool activity events are forwarded via onToolCall callbacks so the UI
12
+ * can display "Reading file...", "Writing code...", etc.
13
+ */
14
+ import type { LLMPipeline, ProgressCallback, Message, LLMGenerateOptions, LLMGenerateResult } from '../../types';
15
+ import type { AgentProvider } from './provider';
16
+ export declare class AgentLLM implements LLMPipeline {
17
+ private provider;
18
+ private session;
19
+ private ready;
20
+ constructor(provider: AgentProvider);
21
+ initialize(_onProgress?: ProgressCallback): Promise<void>;
22
+ /**
23
+ * Agent backends handle tools internally — the voice pipeline
24
+ * should not pass tool definitions or expect tool_calls back.
25
+ */
26
+ supportsTools(): boolean;
27
+ generate(messages: Message[], options?: LLMGenerateOptions): Promise<LLMGenerateResult>;
28
+ isReady(): boolean;
29
+ /**
30
+ * Destroy the current session and release resources.
31
+ * A new session will be created on the next generate() call.
32
+ */
33
+ destroySession(): Promise<void>;
34
+ /**
35
+ * Extract the latest user message from the conversation history.
36
+ * We walk backwards to find the most recent 'user' role message.
37
+ */
38
+ private extractLatestUserMessage;
39
+ }
40
+ //# sourceMappingURL=llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../../src/backends/agent/llm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,YAAY,CAAC;AAE9D,qBAAa,QAAS,YAAW,WAAW;IAC1C,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,KAAK,CAAS;gBAEV,QAAQ,EAAE,aAAa;IAI7B,UAAU,CAAC,WAAW,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D;;;OAGG;IACH,aAAa,IAAI,OAAO;IAIlB,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA6D7F,OAAO,IAAI,OAAO;IAIlB;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;CAQjC"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Agent LLM Pipeline
3
+ * Wraps agent SDKs (OpenCode, Pi Agent, etc.) as an LLMPipeline backend.
4
+ *
5
+ * Unlike CloudLLM which makes raw API calls and lets the voice pipeline handle
6
+ * tool execution, AgentLLM delegates to an agent SDK that manages its own
7
+ * tool execution loop internally. From the voice pipeline's perspective,
8
+ * this backend always returns finishReason: 'stop' — the tool loop is
9
+ * handled entirely within the agent.
10
+ *
11
+ * Tool activity events are forwarded via onToolCall callbacks so the UI
12
+ * can display "Reading file...", "Writing code...", etc.
13
+ */
14
+ export class AgentLLM {
15
+ provider;
16
+ session = null;
17
+ ready = false;
18
+ constructor(provider) {
19
+ this.provider = provider;
20
+ }
21
+ async initialize(_onProgress) {
22
+ console.log('Initializing Agent LLM...');
23
+ this.ready = true;
24
+ console.log('Agent LLM ready (session will be created on first message).');
25
+ }
26
+ /**
27
+ * Agent backends handle tools internally — the voice pipeline
28
+ * should not pass tool definitions or expect tool_calls back.
29
+ */
30
+ supportsTools() {
31
+ return false;
32
+ }
33
+ async generate(messages, options) {
34
+ if (!this.ready) {
35
+ throw new Error('Agent LLM pipeline not initialized');
36
+ }
37
+ // Lazily create the agent session on first generate() call
38
+ if (!this.session) {
39
+ console.log('Creating agent session...');
40
+ this.session = await this.provider.createSession();
41
+ console.log('Agent session created.');
42
+ }
43
+ // Extract the latest user message from the conversation history.
44
+ // The agent SDK maintains its own history, so we only need the new message.
45
+ const latestUserMessage = this.extractLatestUserMessage(messages);
46
+ if (!latestUserMessage) {
47
+ return { content: '', finishReason: 'stop' };
48
+ }
49
+ // Stream the response from the agent
50
+ let fullContent = '';
51
+ for await (const event of this.session.sendMessage(latestUserMessage)) {
52
+ switch (event.type) {
53
+ case 'text_delta':
54
+ if (event.content) {
55
+ fullContent += event.content;
56
+ options?.onToken?.(event.content);
57
+ }
58
+ break;
59
+ case 'tool_call_start':
60
+ if (event.toolCall) {
61
+ options?.onToolCall?.({
62
+ id: event.toolCall.id,
63
+ name: event.toolCall.name,
64
+ arguments: event.toolCall.arguments ?? {},
65
+ });
66
+ }
67
+ break;
68
+ case 'tool_call_end':
69
+ // Tool results are informational only — the agent already handled them.
70
+ break;
71
+ case 'error':
72
+ throw new Error(`Agent error: ${event.error ?? 'Unknown error'}`);
73
+ case 'done':
74
+ break;
75
+ }
76
+ }
77
+ // Always return 'stop' — the agent handles its own tool loop.
78
+ // The voice pipeline's tool loop will exit on the first iteration.
79
+ return {
80
+ content: fullContent,
81
+ finishReason: 'stop',
82
+ };
83
+ }
84
+ isReady() {
85
+ return this.ready;
86
+ }
87
+ /**
88
+ * Destroy the current session and release resources.
89
+ * A new session will be created on the next generate() call.
90
+ */
91
+ async destroySession() {
92
+ if (this.session) {
93
+ await this.session.destroy();
94
+ this.session = null;
95
+ }
96
+ }
97
+ /**
98
+ * Extract the latest user message from the conversation history.
99
+ * We walk backwards to find the most recent 'user' role message.
100
+ */
101
+ extractLatestUserMessage(messages) {
102
+ for (let i = messages.length - 1; i >= 0; i--) {
103
+ if (messages[i].role === 'user') {
104
+ return messages[i].content;
105
+ }
106
+ }
107
+ return null;
108
+ }
109
+ }
110
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../../src/backends/agent/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * OpenCode Agent Provider
3
+ * Wraps an OpenCode SDK session as an AgentProvider.
4
+ *
5
+ * The user creates the OpenCode client externally and passes in
6
+ * the session API. This provider handles creating sessions and
7
+ * mapping SSE events to AgentStreamEvents.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { createOpencode } from '@opencode-ai/sdk';
12
+ *
13
+ * const opencode = await createOpencode({ ... });
14
+ *
15
+ * const pipeline = createVoicePipeline({
16
+ * create: () => ({
17
+ * stt: new CloudSTT({ ... }),
18
+ * llm: new AgentLLM(new OpenCodeAgentProvider({
19
+ * client: opencode.client,
20
+ * })),
21
+ * tts: null,
22
+ * systemPrompt: 'You are a coding assistant.',
23
+ * }),
24
+ * });
25
+ * ```
26
+ */
27
+ import type { AgentProvider, AgentSession } from './provider';
28
+ /**
29
+ * Configuration for the OpenCode agent provider.
30
+ */
31
+ export interface OpenCodeAgentProviderConfig {
32
+ /**
33
+ * The OpenCode SDK client instance.
34
+ * Created externally via createOpencode() or createOpencodeClient().
35
+ */
36
+ client: OpenCodeClient;
37
+ /**
38
+ * Model override (e.g., { providerID: 'anthropic', modelID: 'claude-sonnet-4-20250514' }).
39
+ * If omitted, uses the server's default model.
40
+ */
41
+ model?: {
42
+ providerID: string;
43
+ modelID: string;
44
+ };
45
+ }
46
+ /**
47
+ * OpenCode Agent Provider
48
+ * Wraps an externally-created OpenCode client.
49
+ */
50
+ export declare class OpenCodeAgentProvider implements AgentProvider {
51
+ private config;
52
+ constructor(config: OpenCodeAgentProviderConfig);
53
+ createSession(): Promise<AgentSession>;
54
+ }
55
+ /**
56
+ * Minimal type definitions for the OpenCode SDK client.
57
+ * These match the SDK's API surface without requiring the SDK at build time.
58
+ * The user passes in the real SDK client which satisfies this interface.
59
+ */
60
+ interface OpenCodePromptBody {
61
+ parts: Array<{
62
+ type: string;
63
+ text: string;
64
+ }>;
65
+ model?: {
66
+ providerID: string;
67
+ modelID: string;
68
+ };
69
+ }
70
+ export interface OpenCodeClient {
71
+ session: {
72
+ create(opts: {
73
+ body: Record<string, unknown>;
74
+ }): Promise<any>;
75
+ prompt(opts: {
76
+ path: {
77
+ id: string;
78
+ };
79
+ body: OpenCodePromptBody;
80
+ }): Promise<any>;
81
+ delete(opts: {
82
+ path: {
83
+ id: string;
84
+ };
85
+ }): Promise<any>;
86
+ };
87
+ event: {
88
+ subscribe(): Promise<{
89
+ stream: AsyncIterable<any>;
90
+ }>;
91
+ };
92
+ }
93
+ export {};
94
+ //# sourceMappingURL=opencode-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-provider.d.ts","sourceRoot":"","sources":["../../../src/backends/agent/opencode-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAoB,MAAM,YAAY,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,MAAM,EAAE,cAAc,CAAC;IACvB;;;OAGG;IACH,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IACzD,OAAO,CAAC,MAAM,CAA8B;gBAEhC,MAAM,EAAE,2BAA2B;IAIzC,aAAa,IAAI,OAAO,CAAC,YAAY,CAAC;CAY7C;AAoID;;;;GAIG;AAGH,UAAU,kBAAkB;IAC1B,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE;QACP,MAAM,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC;YAAC,IAAI,EAAE,kBAAkB,CAAA;SAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;KACtD,CAAC;IACF,KAAK,EAAE;QACL,SAAS,IAAI,OAAO,CAAC;YAAE,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,CAAA;SAAE,CAAC,CAAC;KACtD,CAAC;CACH"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * OpenCode Agent Provider
3
+ * Wraps an OpenCode SDK session as an AgentProvider.
4
+ *
5
+ * The user creates the OpenCode client externally and passes in
6
+ * the session API. This provider handles creating sessions and
7
+ * mapping SSE events to AgentStreamEvents.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { createOpencode } from '@opencode-ai/sdk';
12
+ *
13
+ * const opencode = await createOpencode({ ... });
14
+ *
15
+ * const pipeline = createVoicePipeline({
16
+ * create: () => ({
17
+ * stt: new CloudSTT({ ... }),
18
+ * llm: new AgentLLM(new OpenCodeAgentProvider({
19
+ * client: opencode.client,
20
+ * })),
21
+ * tts: null,
22
+ * systemPrompt: 'You are a coding assistant.',
23
+ * }),
24
+ * });
25
+ * ```
26
+ */
27
+ /**
28
+ * OpenCode Agent Provider
29
+ * Wraps an externally-created OpenCode client.
30
+ */
31
+ export class OpenCodeAgentProvider {
32
+ config;
33
+ constructor(config) {
34
+ this.config = config;
35
+ }
36
+ async createSession() {
37
+ const client = this.config.client;
38
+ // Create a new session on the OpenCode server
39
+ const session = await client.session.create({ body: {} });
40
+ const sessionId = session.id ?? session.data?.id;
41
+ if (!sessionId) {
42
+ throw new Error('OpenCode: Failed to create session — no session ID returned');
43
+ }
44
+ return new OpenCodeAgentSession(client, sessionId, this.config.model);
45
+ }
46
+ }
47
+ /**
48
+ * Active OpenCode agent session.
49
+ * Manages the SSE event subscription and prompt sending.
50
+ */
51
+ class OpenCodeAgentSession {
52
+ client;
53
+ sessionId;
54
+ model;
55
+ constructor(client, sessionId, model) {
56
+ this.client = client;
57
+ this.sessionId = sessionId;
58
+ this.model = model;
59
+ }
60
+ async *sendMessage(text) {
61
+ // Subscribe to SSE events before sending the prompt.
62
+ // This ensures we capture all events including the first ones.
63
+ const events = await this.client.event.subscribe();
64
+ // Build prompt body
65
+ const promptBody = {
66
+ parts: [{ type: 'text', text }],
67
+ };
68
+ if (this.model) {
69
+ promptBody.model = this.model;
70
+ }
71
+ // Send the prompt (don't await — we process events as they stream)
72
+ const promptPromise = this.client.session.prompt({
73
+ path: { id: this.sessionId },
74
+ body: promptBody,
75
+ });
76
+ // Track text we've already emitted to compute deltas.
77
+ // OpenCode message.part.updated events contain the full accumulated text,
78
+ // so we diff against what we've sent to produce incremental deltas.
79
+ let emittedTextLength = 0;
80
+ let done = false;
81
+ try {
82
+ for await (const event of events.stream) {
83
+ // Filter events for our session
84
+ const props = event.properties ?? event;
85
+ const eventSessionId = props.sessionID ?? props.session_id;
86
+ if (eventSessionId !== this.sessionId) {
87
+ continue;
88
+ }
89
+ const eventType = event.type ?? event.event ?? '';
90
+ if (eventType === 'message.part.updated') {
91
+ const part = props.part ?? props;
92
+ const partType = part?.type ?? '';
93
+ if (partType === 'text') {
94
+ // Text delta — OpenCode sends cumulative text, so compute the delta
95
+ const fullText = part.text ?? part.content ?? '';
96
+ if (fullText.length > emittedTextLength) {
97
+ const delta = fullText.slice(emittedTextLength);
98
+ emittedTextLength = fullText.length;
99
+ yield { type: 'text_delta', content: delta };
100
+ }
101
+ }
102
+ else if (partType === 'tool-invocation' || partType === 'tool_use') {
103
+ const toolInvocation = part.toolInvocation ?? part;
104
+ const state = toolInvocation.state ?? '';
105
+ const toolName = toolInvocation.toolName ?? part.name ?? 'unknown';
106
+ const toolCallId = toolInvocation.toolCallId ?? part.id ?? '';
107
+ if (state === 'calling' || state === 'partial-call') {
108
+ yield {
109
+ type: 'tool_call_start',
110
+ toolCall: {
111
+ id: toolCallId,
112
+ name: toolName,
113
+ arguments: toolInvocation.args ?? {},
114
+ },
115
+ };
116
+ }
117
+ else if (state === 'result') {
118
+ yield {
119
+ type: 'tool_call_end',
120
+ toolCall: {
121
+ id: toolCallId,
122
+ name: toolName,
123
+ result: toolInvocation.result,
124
+ },
125
+ };
126
+ }
127
+ }
128
+ }
129
+ else if (eventType === 'session.error') {
130
+ yield {
131
+ type: 'error',
132
+ error: props.error ?? props.message ?? 'Unknown OpenCode error',
133
+ };
134
+ done = true;
135
+ break;
136
+ }
137
+ else if (eventType === 'session.idle') {
138
+ // Reset text tracking for next message in this session
139
+ emittedTextLength = 0;
140
+ done = true;
141
+ yield { type: 'done' };
142
+ break;
143
+ }
144
+ }
145
+ }
146
+ finally {
147
+ if (!done) {
148
+ yield { type: 'done' };
149
+ }
150
+ // Wait for the prompt to resolve to catch any errors
151
+ try {
152
+ await promptPromise;
153
+ }
154
+ catch (err) {
155
+ console.warn('OpenCode prompt error:', err);
156
+ }
157
+ }
158
+ }
159
+ async destroy() {
160
+ try {
161
+ await this.client.session.delete({ path: { id: this.sessionId } });
162
+ }
163
+ catch {
164
+ // Session may already be cleaned up
165
+ }
166
+ }
167
+ }
168
+ /* eslint-enable @typescript-eslint/no-explicit-any */
169
+ //# sourceMappingURL=opencode-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-provider.js","sourceRoot":"","sources":["../../../src/backends/agent/opencode-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Pi Agent Provider
3
+ * Wraps a Pi Agent instance (@mariozechner/pi-agent-core) as an AgentProvider.
4
+ *
5
+ * The user creates the Agent externally with their own model, tools, and config.
6
+ * This provider wraps it and maps its event stream to AgentStreamEvents.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { Agent } from '@mariozechner/pi-agent-core';
11
+ * import { getModel } from '@mariozechner/pi-ai';
12
+ * import { codingTools } from '@mariozechner/pi-coding-agent';
13
+ *
14
+ * const agent = new Agent({
15
+ * initialState: {
16
+ * systemPrompt: 'You are a coding assistant.',
17
+ * model: getModel('anthropic', 'claude-sonnet-4-20250514'),
18
+ * thinkingLevel: 'medium',
19
+ * tools: codingTools,
20
+ * },
21
+ * });
22
+ *
23
+ * const pipeline = createVoicePipeline({
24
+ * create: () => ({
25
+ * stt: new CloudSTT({ ... }),
26
+ * llm: new AgentLLM(new PiAgentProvider({ agent })),
27
+ * tts: null,
28
+ * systemPrompt: 'You are a coding assistant.',
29
+ * }),
30
+ * });
31
+ * ```
32
+ */
33
+ import type { AgentProvider, AgentSession } from './provider';
34
+ /**
35
+ * Configuration for the Pi Agent provider.
36
+ */
37
+ export interface PiAgentProviderConfig {
38
+ /**
39
+ * A pre-created Pi Agent instance.
40
+ * Created externally with your own model, tools, and configuration.
41
+ */
42
+ agent: PiAgent;
43
+ }
44
+ /**
45
+ * Pi Agent Provider
46
+ * Wraps an externally-created Pi Agent instance.
47
+ */
48
+ export declare class PiAgentProvider implements AgentProvider {
49
+ private agent;
50
+ constructor(config: PiAgentProviderConfig);
51
+ createSession(): Promise<AgentSession>;
52
+ }
53
+ /**
54
+ * Minimal type definitions for the Pi Agent SDK.
55
+ * These match the SDK's API surface without requiring the SDK at build time.
56
+ * The user passes in the real Agent instance which satisfies this interface.
57
+ */
58
+ interface PiAgentEvent {
59
+ type: string;
60
+ assistantMessageEvent?: {
61
+ type: string;
62
+ delta?: string;
63
+ };
64
+ toolCallId?: string;
65
+ toolName?: string;
66
+ args?: Record<string, unknown>;
67
+ result?: any;
68
+ isError?: boolean;
69
+ }
70
+ export interface PiAgent {
71
+ prompt(text: string | any, images?: any[]): Promise<void>;
72
+ subscribe(listener: (event: PiAgentEvent) => void): () => void;
73
+ abort(): void;
74
+ }
75
+ export {};
76
+ //# sourceMappingURL=pi-agent-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-agent-provider.d.ts","sourceRoot":"","sources":["../../../src/backends/agent/pi-agent-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAoB,MAAM,YAAY,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,aAAa;IACnD,OAAO,CAAC,KAAK,CAAU;gBAEX,MAAM,EAAE,qBAAqB;IAInC,aAAa,IAAI,OAAO,CAAC,YAAY,CAAC;CAG7C;AA+GD;;;;GAIG;AAGH,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IAEb,qBAAqB,CAAC,EAAE;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAEF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC/D,KAAK,IAAI,IAAI,CAAC;CACf"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Pi Agent Provider
3
+ * Wraps a Pi Agent instance (@mariozechner/pi-agent-core) as an AgentProvider.
4
+ *
5
+ * The user creates the Agent externally with their own model, tools, and config.
6
+ * This provider wraps it and maps its event stream to AgentStreamEvents.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { Agent } from '@mariozechner/pi-agent-core';
11
+ * import { getModel } from '@mariozechner/pi-ai';
12
+ * import { codingTools } from '@mariozechner/pi-coding-agent';
13
+ *
14
+ * const agent = new Agent({
15
+ * initialState: {
16
+ * systemPrompt: 'You are a coding assistant.',
17
+ * model: getModel('anthropic', 'claude-sonnet-4-20250514'),
18
+ * thinkingLevel: 'medium',
19
+ * tools: codingTools,
20
+ * },
21
+ * });
22
+ *
23
+ * const pipeline = createVoicePipeline({
24
+ * create: () => ({
25
+ * stt: new CloudSTT({ ... }),
26
+ * llm: new AgentLLM(new PiAgentProvider({ agent })),
27
+ * tts: null,
28
+ * systemPrompt: 'You are a coding assistant.',
29
+ * }),
30
+ * });
31
+ * ```
32
+ */
33
+ /**
34
+ * Pi Agent Provider
35
+ * Wraps an externally-created Pi Agent instance.
36
+ */
37
+ export class PiAgentProvider {
38
+ agent;
39
+ constructor(config) {
40
+ this.agent = config.agent;
41
+ }
42
+ async createSession() {
43
+ return new PiAgentSession(this.agent);
44
+ }
45
+ }
46
+ /**
47
+ * Active Pi Agent session.
48
+ * Wraps a Pi Agent instance and maps its event stream to AgentStreamEvents.
49
+ */
50
+ class PiAgentSession {
51
+ agent;
52
+ constructor(agent) {
53
+ this.agent = agent;
54
+ }
55
+ async *sendMessage(text) {
56
+ // Use a queue to bridge the callback-based event system to an async iterable.
57
+ // The agent emits events via subscribe(), and we yield them from the generator.
58
+ const eventQueue = [];
59
+ let resolve = null;
60
+ let done = false;
61
+ const waitForEvent = () => new Promise((r) => {
62
+ if (eventQueue.length > 0) {
63
+ r();
64
+ }
65
+ else {
66
+ resolve = r;
67
+ }
68
+ });
69
+ const pushEvent = (event) => {
70
+ eventQueue.push(event);
71
+ if (resolve) {
72
+ const r = resolve;
73
+ resolve = null;
74
+ r();
75
+ }
76
+ };
77
+ // Subscribe to agent events
78
+ const unsubscribe = this.agent.subscribe((event) => {
79
+ const eventType = event.type;
80
+ if (eventType === 'message_update') {
81
+ // Streaming text delta from assistant
82
+ const assistantEvent = event.assistantMessageEvent;
83
+ if (assistantEvent?.type === 'text_delta' && assistantEvent.delta) {
84
+ pushEvent({
85
+ type: 'text_delta',
86
+ content: assistantEvent.delta,
87
+ });
88
+ }
89
+ }
90
+ else if (eventType === 'tool_execution_start') {
91
+ pushEvent({
92
+ type: 'tool_call_start',
93
+ toolCall: {
94
+ id: event.toolCallId ?? '',
95
+ name: event.toolName ?? 'unknown',
96
+ arguments: event.args ?? {},
97
+ },
98
+ });
99
+ }
100
+ else if (eventType === 'tool_execution_end') {
101
+ pushEvent({
102
+ type: 'tool_call_end',
103
+ toolCall: {
104
+ id: event.toolCallId ?? '',
105
+ name: event.toolName ?? 'unknown',
106
+ result: event.result,
107
+ isError: event.isError,
108
+ },
109
+ });
110
+ }
111
+ else if (eventType === 'agent_end') {
112
+ pushEvent({ type: 'done' });
113
+ done = true;
114
+ }
115
+ });
116
+ try {
117
+ // Start the agent prompt (runs asynchronously, events come via subscribe)
118
+ const promptPromise = this.agent.prompt(text).catch((err) => {
119
+ pushEvent({
120
+ type: 'error',
121
+ error: err.message ?? 'Pi Agent error',
122
+ });
123
+ done = true;
124
+ });
125
+ // Yield events as they arrive
126
+ while (!done) {
127
+ await waitForEvent();
128
+ while (eventQueue.length > 0) {
129
+ const event = eventQueue.shift();
130
+ yield event;
131
+ if (event.type === 'done' || event.type === 'error') {
132
+ done = true;
133
+ break;
134
+ }
135
+ }
136
+ }
137
+ // Wait for prompt to fully complete
138
+ await promptPromise;
139
+ }
140
+ finally {
141
+ unsubscribe();
142
+ }
143
+ }
144
+ async destroy() {
145
+ this.agent.abort();
146
+ }
147
+ }
148
+ /* eslint-enable @typescript-eslint/no-explicit-any */
149
+ //# sourceMappingURL=pi-agent-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-agent-provider.js","sourceRoot":"","sources":["../../../src/backends/agent/pi-agent-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Pi Coding Agent Provider
3
+ * Wraps a Pi Coding Agent session (@mariozechner/pi-coding-agent) as an AgentProvider.
4
+ *
5
+ * This is the higher-level wrapper compared to PiAgentProvider. The Pi Coding Agent
6
+ * adds session management, auto-compaction, retries, skill expansion, prompt templates,
7
+ * and built-in coding tools (read, write, edit, bash, grep, find, ls) on top of the
8
+ * raw Pi Agent runtime.
9
+ *
10
+ * The user creates the session externally via createAgentSession() and passes it in.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import {
15
+ * createAgentSession,
16
+ * SessionManager,
17
+ * AuthStorage,
18
+ * ModelRegistry,
19
+ * } from '@mariozechner/pi-coding-agent';
20
+ *
21
+ * const authStorage = new AuthStorage();
22
+ * const { session } = await createAgentSession({
23
+ * sessionManager: SessionManager.inMemory(),
24
+ * authStorage,
25
+ * modelRegistry: new ModelRegistry(authStorage),
26
+ * });
27
+ *
28
+ * const pipeline = createVoicePipeline({
29
+ * create: () => ({
30
+ * stt: new CloudSTT({ ... }),
31
+ * llm: new AgentLLM(new PiCodingAgentProvider({ session })),
32
+ * tts: null,
33
+ * systemPrompt: 'You are a coding assistant.',
34
+ * }),
35
+ * });
36
+ * ```
37
+ */
38
+ import type { AgentProvider, AgentSession as VoiceAgentSession } from './provider';
39
+ /**
40
+ * Configuration for the Pi Coding Agent provider.
41
+ */
42
+ export interface PiCodingAgentProviderConfig {
43
+ /**
44
+ * A pre-created Pi Coding Agent session.
45
+ * Created externally via createAgentSession() from @mariozechner/pi-coding-agent.
46
+ */
47
+ session: PiCodingAgentSession;
48
+ }
49
+ /**
50
+ * Pi Coding Agent Provider
51
+ * Wraps an externally-created Pi Coding Agent session.
52
+ */
53
+ export declare class PiCodingAgentProvider implements AgentProvider {
54
+ private session;
55
+ constructor(config: PiCodingAgentProviderConfig);
56
+ createSession(): Promise<VoiceAgentSession>;
57
+ }
58
+ /**
59
+ * Minimal type definitions for the Pi Coding Agent session.
60
+ * These match the AgentSession API surface from @mariozechner/pi-coding-agent
61
+ * without requiring the SDK at build time.
62
+ */
63
+ interface PiAgentSessionEvent {
64
+ type: string;
65
+ assistantMessageEvent?: {
66
+ type: string;
67
+ delta?: string;
68
+ };
69
+ toolCallId?: string;
70
+ toolName?: string;
71
+ args?: Record<string, unknown>;
72
+ result?: any;
73
+ isError?: boolean;
74
+ messages?: any[];
75
+ }
76
+ export interface PiCodingAgentSession {
77
+ /** Send a prompt to the agent (handles skills, templates, validation, etc.) */
78
+ prompt(text: string, options?: any): Promise<void>;
79
+ /** Subscribe to session events. Returns unsubscribe function. */
80
+ subscribe(listener: (event: PiAgentSessionEvent) => void): () => void;
81
+ /** Clean up the session */
82
+ dispose(): void;
83
+ /** The underlying Agent instance */
84
+ agent: any;
85
+ }
86
+ export {};
87
+ //# sourceMappingURL=pi-coding-agent-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-coding-agent-provider.d.ts","sourceRoot":"","sources":["../../../src/backends/agent/pi-coding-agent-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,IAAI,iBAAiB,EAAoB,MAAM,YAAY,CAAC;AAErG;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAED;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IACzD,OAAO,CAAC,OAAO,CAAuB;gBAE1B,MAAM,EAAE,2BAA2B;IAIzC,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAGlD;AAiHD;;;;GAIG;AAGH,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IAEb,qBAAqB,CAAC,EAAE;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAEF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,iEAAiE;IACjE,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACtE,2BAA2B;IAC3B,OAAO,IAAI,IAAI,CAAC;IAChB,oCAAoC;IACpC,KAAK,EAAE,GAAG,CAAC;CACZ"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Pi Coding Agent Provider
3
+ * Wraps a Pi Coding Agent session (@mariozechner/pi-coding-agent) as an AgentProvider.
4
+ *
5
+ * This is the higher-level wrapper compared to PiAgentProvider. The Pi Coding Agent
6
+ * adds session management, auto-compaction, retries, skill expansion, prompt templates,
7
+ * and built-in coding tools (read, write, edit, bash, grep, find, ls) on top of the
8
+ * raw Pi Agent runtime.
9
+ *
10
+ * The user creates the session externally via createAgentSession() and passes it in.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import {
15
+ * createAgentSession,
16
+ * SessionManager,
17
+ * AuthStorage,
18
+ * ModelRegistry,
19
+ * } from '@mariozechner/pi-coding-agent';
20
+ *
21
+ * const authStorage = new AuthStorage();
22
+ * const { session } = await createAgentSession({
23
+ * sessionManager: SessionManager.inMemory(),
24
+ * authStorage,
25
+ * modelRegistry: new ModelRegistry(authStorage),
26
+ * });
27
+ *
28
+ * const pipeline = createVoicePipeline({
29
+ * create: () => ({
30
+ * stt: new CloudSTT({ ... }),
31
+ * llm: new AgentLLM(new PiCodingAgentProvider({ session })),
32
+ * tts: null,
33
+ * systemPrompt: 'You are a coding assistant.',
34
+ * }),
35
+ * });
36
+ * ```
37
+ */
38
+ /**
39
+ * Pi Coding Agent Provider
40
+ * Wraps an externally-created Pi Coding Agent session.
41
+ */
42
+ export class PiCodingAgentProvider {
43
+ session;
44
+ constructor(config) {
45
+ this.session = config.session;
46
+ }
47
+ async createSession() {
48
+ return new PiCodingAgentSessionAdapter(this.session);
49
+ }
50
+ }
51
+ /**
52
+ * Adapts a Pi Coding Agent session to the VoiceAgentSession interface.
53
+ * Maps AgentSessionEvents to AgentStreamEvents.
54
+ */
55
+ class PiCodingAgentSessionAdapter {
56
+ session;
57
+ constructor(session) {
58
+ this.session = session;
59
+ }
60
+ async *sendMessage(text) {
61
+ // Use a queue to bridge the callback-based event system to an async iterable.
62
+ const eventQueue = [];
63
+ let resolve = null;
64
+ let done = false;
65
+ const waitForEvent = () => new Promise((r) => {
66
+ if (eventQueue.length > 0) {
67
+ r();
68
+ }
69
+ else {
70
+ resolve = r;
71
+ }
72
+ });
73
+ const pushEvent = (event) => {
74
+ eventQueue.push(event);
75
+ if (resolve) {
76
+ const r = resolve;
77
+ resolve = null;
78
+ r();
79
+ }
80
+ };
81
+ // Subscribe to session events.
82
+ // AgentSessionEvent extends AgentEvent, so we get all the core events
83
+ // plus session-level events (auto_compaction, auto_retry, etc.)
84
+ const unsubscribe = this.session.subscribe((event) => {
85
+ const eventType = event.type;
86
+ if (eventType === 'message_update') {
87
+ const assistantEvent = event.assistantMessageEvent;
88
+ if (assistantEvent?.type === 'text_delta' && assistantEvent.delta) {
89
+ pushEvent({
90
+ type: 'text_delta',
91
+ content: assistantEvent.delta,
92
+ });
93
+ }
94
+ }
95
+ else if (eventType === 'tool_execution_start') {
96
+ pushEvent({
97
+ type: 'tool_call_start',
98
+ toolCall: {
99
+ id: event.toolCallId ?? '',
100
+ name: event.toolName ?? 'unknown',
101
+ arguments: event.args ?? {},
102
+ },
103
+ });
104
+ }
105
+ else if (eventType === 'tool_execution_end') {
106
+ pushEvent({
107
+ type: 'tool_call_end',
108
+ toolCall: {
109
+ id: event.toolCallId ?? '',
110
+ name: event.toolName ?? 'unknown',
111
+ result: event.result,
112
+ isError: event.isError,
113
+ },
114
+ });
115
+ }
116
+ else if (eventType === 'agent_end') {
117
+ pushEvent({ type: 'done' });
118
+ done = true;
119
+ }
120
+ // We silently ignore session-level events like auto_compaction_start/end,
121
+ // auto_retry_start/end — the session handles them internally.
122
+ });
123
+ try {
124
+ // Use session.prompt() which handles skill expansion, prompt templates,
125
+ // validation, auto-compaction, retries, etc.
126
+ const promptPromise = this.session.prompt(text).catch((err) => {
127
+ pushEvent({
128
+ type: 'error',
129
+ error: err.message ?? 'Pi Coding Agent error',
130
+ });
131
+ done = true;
132
+ });
133
+ // Yield events as they arrive
134
+ while (!done) {
135
+ await waitForEvent();
136
+ while (eventQueue.length > 0) {
137
+ const event = eventQueue.shift();
138
+ yield event;
139
+ if (event.type === 'done' || event.type === 'error') {
140
+ done = true;
141
+ break;
142
+ }
143
+ }
144
+ }
145
+ await promptPromise;
146
+ }
147
+ finally {
148
+ unsubscribe();
149
+ }
150
+ }
151
+ async destroy() {
152
+ this.session.dispose();
153
+ }
154
+ }
155
+ /* eslint-enable @typescript-eslint/no-explicit-any */
156
+ //# sourceMappingURL=pi-coding-agent-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-coding-agent-provider.js","sourceRoot":"","sources":["../../../src/backends/agent/pi-coding-agent-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Agent Provider Interface
3
+ * Abstracts different agent SDKs (OpenCode, Pi Agent, etc.) behind a common interface.
4
+ *
5
+ * Agent SDKs manage their own tool execution loop internally.
6
+ * The provider streams events back so the voice pipeline can:
7
+ * - Stream text tokens to the client in real-time
8
+ * - Show tool activity in the UI (for feedback, not execution)
9
+ */
10
+ /**
11
+ * Streaming event from an agent session.
12
+ * These events are emitted as the agent processes a message,
13
+ * including tool calls that the agent executes internally.
14
+ */
15
+ export interface AgentStreamEvent {
16
+ type: 'text_delta' | 'tool_call_start' | 'tool_call_end' | 'error' | 'done';
17
+ /** Text content delta (for 'text_delta' events) */
18
+ content?: string;
19
+ /** Tool call information (for 'tool_call_start' and 'tool_call_end' events) */
20
+ toolCall?: {
21
+ id: string;
22
+ name: string;
23
+ arguments?: Record<string, unknown>;
24
+ result?: unknown;
25
+ isError?: boolean;
26
+ };
27
+ /** Error message (for 'error' events) */
28
+ error?: string;
29
+ }
30
+ /**
31
+ * An active agent session.
32
+ * Wraps the underlying SDK's session/agent instance.
33
+ * The session maintains its own conversation history internally.
34
+ */
35
+ export interface AgentSession {
36
+ /**
37
+ * Send a message to the agent and stream back events.
38
+ * The agent handles tool execution internally — the caller
39
+ * only receives text deltas and tool activity notifications.
40
+ *
41
+ * @param text - User message text
42
+ * @returns Async iterable of stream events
43
+ */
44
+ sendMessage(text: string): AsyncIterable<AgentStreamEvent>;
45
+ /**
46
+ * Clean up the session and release resources.
47
+ */
48
+ destroy(): Promise<void>;
49
+ }
50
+ /**
51
+ * Provider that creates agent sessions.
52
+ * Each provider wraps a specific agent SDK.
53
+ */
54
+ export interface AgentProvider {
55
+ /**
56
+ * Create a new agent session.
57
+ * The session manages its own conversation history, tool execution, etc.
58
+ */
59
+ createSession(): Promise<AgentSession>;
60
+ }
61
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/backends/agent/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,GAAG,iBAAiB,GAAG,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC;IAE5E,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE;QACT,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IAEF,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAE3D;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;CACxC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Agent Provider Interface
3
+ * Abstracts different agent SDKs (OpenCode, Pi Agent, etc.) behind a common interface.
4
+ *
5
+ * Agent SDKs manage their own tool execution loop internally.
6
+ * The provider streams events back so the voice pipeline can:
7
+ * - Stream text tokens to the client in real-time
8
+ * - Show tool activity in the UI (for feedback, not execution)
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/backends/agent/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -26,7 +26,7 @@
26
26
  */
27
27
  export { createPipelineHandler, PipelineHandler, PipelineSession } from './handler';
28
28
  export type { PipelineHandlerConfig } from './handler';
29
- export { float32ToBase64, base64ToFloat32, type ClientMessage, type ServerMessage, type AudioMessage, type EndAudioMessage, type ClearHistoryMessage, type TranscriptMessage, type ResponseChunkMessage, type AudioResponseMessage, type CompleteMessage, type ErrorMessage, } from '../client/protocol';
29
+ export { float32ToBase64, base64ToFloat32, generateId, type IdPrefix, type ClientEnvelope, type ServerEnvelope, type ClientMessage, type ServerMessage, type SessionInitMessage, type AudioMessage, type EndAudioMessage, type ClearHistoryMessage, type TextMessage, type TranscriptMessage, type ResponseChunkMessage, type AudioResponseMessage, type ToolCallMessage, type ToolResultMessage, type CompleteMessage, type ErrorMessage, } from '../client/protocol';
30
30
  export { float32ToBase64Node, base64ToFloat32Node } from './encoding';
31
31
  export type { Message } from '../types';
32
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACpF,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAGvD,OAAO,EACL,eAAe,EACf,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGtE,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACpF,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAGvD,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGtE,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
@@ -26,7 +26,7 @@
26
26
  */
27
27
  export { createPipelineHandler, PipelineHandler, PipelineSession } from './handler';
28
28
  // Re-export protocol types for server use
29
- export { float32ToBase64, base64ToFloat32, } from '../client/protocol';
29
+ export { float32ToBase64, base64ToFloat32, generateId, } from '../client/protocol';
30
30
  // Server-side encoding utilities (use Buffer for efficiency in Node.js)
31
31
  export { float32ToBase64Node, base64ToFloat32Node } from './encoding';
32
32
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGpF,0CAA0C;AAC1C,OAAO,EACL,eAAe,EACf,eAAe,GAWhB,MAAM,oBAAoB,CAAC;AAE5B,wEAAwE;AACxE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGpF,0CAA0C;AAC1C,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,GAkBX,MAAM,oBAAoB,CAAC;AAE5B,wEAAwE;AACxE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modular-voice-agent-sdk",
3
- "version": "2.4.0",
3
+ "version": "2.5.1",
4
4
  "description": "Modular isomorphic STT → LLM → TTS pipeline library for AI voice agents and voice assistants",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,6 +26,10 @@
26
26
  "./server": {
27
27
  "import": "./dist/server/index.js",
28
28
  "types": "./dist/server/index.d.ts"
29
+ },
30
+ "./agent": {
31
+ "import": "./dist/backends/agent/index.js",
32
+ "types": "./dist/backends/agent/index.d.ts"
29
33
  }
30
34
  },
31
35
  "bin": {
@@ -51,11 +55,27 @@
51
55
  "ulid": "^3.0.2"
52
56
  },
53
57
  "peerDependencies": {
54
- "ws": "^8.0.0"
58
+ "ws": "^8.0.0",
59
+ "@opencode-ai/sdk": "*",
60
+ "@mariozechner/pi-agent-core": "*",
61
+ "@mariozechner/pi-ai": "*",
62
+ "@mariozechner/pi-coding-agent": "*"
55
63
  },
56
64
  "peerDependenciesMeta": {
57
65
  "ws": {
58
66
  "optional": true
67
+ },
68
+ "@opencode-ai/sdk": {
69
+ "optional": true
70
+ },
71
+ "@mariozechner/pi-agent-core": {
72
+ "optional": true
73
+ },
74
+ "@mariozechner/pi-ai": {
75
+ "optional": true
76
+ },
77
+ "@mariozechner/pi-coding-agent": {
78
+ "optional": true
59
79
  }
60
80
  },
61
81
  "devDependencies": {