@ziggs-ai/agent-sdk 0.1.12 → 0.2.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 (218) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +41 -2
  3. package/dist/AgentHost.d.ts +201 -0
  4. package/dist/AgentHost.js +652 -0
  5. package/dist/adapters/AnthropicAdapter.d.ts +39 -0
  6. package/dist/adapters/AnthropicAdapter.js +200 -0
  7. package/dist/adapters/McpAdapter.d.ts +199 -0
  8. package/dist/adapters/McpAdapter.js +468 -0
  9. package/dist/adapters/OpenAIAdapter.d.ts +26 -0
  10. package/dist/adapters/OpenAIAdapter.js +158 -0
  11. package/dist/adapters/index.js +2 -0
  12. package/dist/agent/Agent.d.ts +78 -0
  13. package/dist/agent/Agent.js +58 -0
  14. package/dist/agent/ClaudeSdkAgent.d.ts +38 -0
  15. package/dist/agent/ClaudeSdkAgent.js +322 -0
  16. package/dist/agent/claudeCognition.d.ts +67 -0
  17. package/dist/agent/claudeCognition.js +103 -0
  18. package/dist/agent/claudeSdkProtocol.d.ts +11 -0
  19. package/dist/agent/claudeSdkTools.d.ts +19 -0
  20. package/dist/agent/claudeSdkTools.js +57 -0
  21. package/dist/agent/hostedAgentConnection.d.ts +15 -0
  22. package/dist/agent/hostedAgentConnection.js +29 -0
  23. package/dist/agent/toolManagerToSdkMcp.d.ts +12 -0
  24. package/dist/agent/toolManagerToSdkMcp.js +123 -0
  25. package/dist/brain/index.d.ts +50 -0
  26. package/dist/brain/index.js +45 -0
  27. package/dist/cognition/validateContext.d.ts +11 -0
  28. package/dist/cognition/validateContext.js +117 -0
  29. package/dist/context/applyEffects.d.ts +2 -0
  30. package/dist/context/applyEffects.js +89 -0
  31. package/dist/context/batch.d.ts +2 -0
  32. package/dist/context/batch.js +18 -0
  33. package/dist/context/classifyEnvelope.d.ts +1 -0
  34. package/dist/context/classifyEnvelope.js +58 -0
  35. package/dist/context/routingLabels.d.ts +4 -0
  36. package/dist/context/routingLabels.js +48 -0
  37. package/dist/defineAgent.d.ts +14 -0
  38. package/dist/defineAgent.js +68 -0
  39. package/dist/formatters/AgreementFormatter.d.ts +18 -0
  40. package/dist/formatters/AgreementFormatter.js +130 -0
  41. package/dist/formatters/HistoryFormatter.d.ts +26 -0
  42. package/dist/formatters/HistoryFormatter.js +173 -0
  43. package/dist/formatters/index.js +2 -0
  44. package/{src/index.ts → dist/index.d.ts} +7 -53
  45. package/dist/index.js +66 -0
  46. package/dist/ingress/normalizeIncoming.d.ts +65 -0
  47. package/dist/ingress/normalizeIncoming.js +88 -0
  48. package/dist/memory/MemoryStore.d.ts +55 -0
  49. package/dist/memory/MemoryStore.js +78 -0
  50. package/dist/pricing/fleetDefaults.d.ts +46 -0
  51. package/dist/pricing/fleetDefaults.js +168 -0
  52. package/dist/pricing/fleetEvalFree.d.ts +7 -0
  53. package/dist/pricing/fleetEvalFree.js +24 -0
  54. package/dist/pricing/fleetFreeTierA.gen.d.ts +6 -0
  55. package/{src/pricing/fleetFreeTierA.gen.ts → dist/pricing/fleetFreeTierA.gen.js} +5 -6
  56. package/dist/pricing/fleetTierByAgentId.gen.d.ts +7 -0
  57. package/dist/pricing/fleetTierByAgentId.gen.js +768 -0
  58. package/dist/runtime/AgentMachine.d.ts +143 -0
  59. package/dist/runtime/AgentMachine.js +400 -0
  60. package/dist/runtime/PromptBuilder.d.ts +96 -0
  61. package/dist/runtime/PromptBuilder.js +439 -0
  62. package/{src/runtime/bootstrapCtx.ts → dist/runtime/bootstrapCtx.d.ts} +1 -22
  63. package/dist/runtime/bootstrapCtx.js +37 -0
  64. package/dist/runtime/buildOutcome.d.ts +68 -0
  65. package/dist/runtime/buildOutcome.js +464 -0
  66. package/dist/runtime/defaults.d.ts +54 -0
  67. package/dist/runtime/defaults.js +47 -0
  68. package/dist/runtime/deriveRespondsToProposals.d.ts +9 -0
  69. package/dist/runtime/deriveRespondsToProposals.js +38 -0
  70. package/dist/runtime/kickoff.d.ts +15 -0
  71. package/dist/runtime/kickoff.js +112 -0
  72. package/dist/runtime/runMechanical.d.ts +25 -0
  73. package/dist/runtime/runMechanical.js +74 -0
  74. package/dist/runtime/runTurn.d.ts +63 -0
  75. package/dist/runtime/runTurn.js +800 -0
  76. package/dist/runtime/validateWorkflow.d.ts +17 -0
  77. package/dist/runtime/validateWorkflow.js +209 -0
  78. package/dist/server/ConnectionPool.d.ts +68 -0
  79. package/dist/server/ConnectionPool.js +166 -0
  80. package/dist/server/EventQueue.d.ts +33 -0
  81. package/dist/server/EventQueue.js +98 -0
  82. package/dist/server/InboxCatchUp.d.ts +24 -0
  83. package/dist/server/InboxCatchUp.js +214 -0
  84. package/dist/server/OutboxBuffer.d.ts +33 -0
  85. package/dist/server/OutboxBuffer.js +68 -0
  86. package/dist/server/SeenMessages.d.ts +13 -0
  87. package/dist/server/SeenMessages.js +31 -0
  88. package/dist/server/StateTimers.d.ts +34 -0
  89. package/dist/server/StateTimers.js +70 -0
  90. package/dist/server/ZiggsEffectHandler.d.ts +79 -0
  91. package/dist/server/ZiggsEffectHandler.js +319 -0
  92. package/dist/server/agreements/AgreementService.d.ts +50 -0
  93. package/dist/server/agreements/AgreementService.js +85 -0
  94. package/dist/server/createHealthServer.d.ts +7 -0
  95. package/dist/server/createHealthServer.js +75 -0
  96. package/dist/server/proactive/ProactiveTrigger.d.ts +33 -0
  97. package/dist/server/proactive/ProactiveTrigger.js +71 -0
  98. package/dist/server/runLauncher.d.ts +28 -0
  99. package/dist/server/runLauncher.js +93 -0
  100. package/dist/server/tasks/TaskService.d.ts +25 -0
  101. package/dist/server/tasks/TaskService.js +103 -0
  102. package/dist/server/tasks/index.js +1 -0
  103. package/dist/server/telemetryIngest.d.ts +24 -0
  104. package/dist/server/telemetryIngest.js +62 -0
  105. package/dist/server/tools/index.d.ts +24 -0
  106. package/{src/server/tools/index.ts → dist/server/tools/index.js} +4 -24
  107. package/dist/server/tools/tier1/protocolRunner.d.ts +39 -0
  108. package/dist/server/tools/tier1/protocolRunner.js +288 -0
  109. package/dist/server/tools/tier1/protocolTools.d.ts +12 -0
  110. package/dist/server/tools/tier1/protocolTools.js +37 -0
  111. package/dist/server/tools/tier2/connectionTools.d.ts +4 -0
  112. package/dist/server/tools/tier2/connectionTools.js +63 -0
  113. package/dist/server/tools/tier2/contextTools.d.ts +4 -0
  114. package/dist/server/tools/tier2/contextTools.js +46 -0
  115. package/dist/server/tools/tier2/discoveryTools.d.ts +4 -0
  116. package/dist/server/tools/tier2/discoveryTools.js +25 -0
  117. package/dist/server/tools/tier2/marketplaceTools.d.ts +3 -0
  118. package/dist/server/tools/tier2/marketplaceTools.js +22 -0
  119. package/dist/server/tools/tier2/paymentTools.d.ts +12 -0
  120. package/dist/server/tools/tier2/paymentTools.js +165 -0
  121. package/dist/server/ziggsconnect/ZiggsConnectClient.d.ts +35 -0
  122. package/dist/server/ziggsconnect/ZiggsConnectClient.js +95 -0
  123. package/dist/server/ziggscontext/ZiggsContextClient.d.ts +53 -0
  124. package/dist/server/ziggscontext/ZiggsContextClient.js +124 -0
  125. package/dist/server/ziggspay/ZiggsPayClient.d.ts +82 -0
  126. package/dist/server/ziggspay/ZiggsPayClient.js +203 -0
  127. package/dist/shared/ids.d.ts +1 -0
  128. package/dist/shared/ids.js +3 -0
  129. package/dist/shared/runtimeLog.d.ts +18 -0
  130. package/dist/shared/runtimeLog.js +68 -0
  131. package/dist/shared/types.d.ts +22 -0
  132. package/dist/shared/types.js +23 -0
  133. package/dist/tasks/protocolRegistry.d.ts +16 -0
  134. package/dist/tasks/protocolRegistry.js +20 -0
  135. package/dist/tools/ToolManager.d.ts +12 -0
  136. package/dist/tools/ToolManager.js +74 -0
  137. package/dist/tools/ToolProvider.d.ts +6 -0
  138. package/dist/tools/ToolProvider.js +21 -0
  139. package/dist/tools/defineTool.d.ts +27 -0
  140. package/dist/tools/defineTool.js +62 -0
  141. package/{src/tools/index.ts → dist/tools/index.d.ts} +0 -1
  142. package/dist/tools/index.js +6 -0
  143. package/dist/tools/recordReport.d.ts +41 -0
  144. package/dist/tools/recordReport.js +30 -0
  145. package/dist/types.d.ts +466 -0
  146. package/dist/types.js +7 -0
  147. package/dist/utils/jsonExtractor.d.ts +2 -0
  148. package/dist/utils/jsonExtractor.js +111 -0
  149. package/package.json +14 -6
  150. package/src/AgentHost.ts +0 -814
  151. package/src/adapters/AnthropicAdapter.ts +0 -238
  152. package/src/adapters/McpAdapter.ts +0 -678
  153. package/src/adapters/OpenAIAdapter.ts +0 -194
  154. package/src/agent/Agent.ts +0 -112
  155. package/src/agent/ClaudeSdkAgent.ts +0 -401
  156. package/src/agent/claudeCognition.ts +0 -139
  157. package/src/agent/claudeSdkTools.ts +0 -81
  158. package/src/agent/hostedAgentConnection.ts +0 -41
  159. package/src/agent/toolManagerToSdkMcp.ts +0 -136
  160. package/src/cognition/validateContext.ts +0 -95
  161. package/src/context/applyEffects.ts +0 -80
  162. package/src/context/batch.ts +0 -19
  163. package/src/context/classifyEnvelope.ts +0 -38
  164. package/src/context/routingLabels.ts +0 -46
  165. package/src/defineAgent.ts +0 -77
  166. package/src/formatters/AgreementFormatter.ts +0 -111
  167. package/src/formatters/HistoryFormatter.ts +0 -172
  168. package/src/ingress/normalizeIncoming.ts +0 -162
  169. package/src/memory/MemoryStore.ts +0 -104
  170. package/src/pricing/fleetDefaults.ts +0 -225
  171. package/src/pricing/fleetEvalFree.ts +0 -24
  172. package/src/pricing/fleetTierByAgentId.gen.ts +0 -775
  173. package/src/runtime/AgentMachine.ts +0 -484
  174. package/src/runtime/PromptBuilder.ts +0 -522
  175. package/src/runtime/buildOutcome.ts +0 -563
  176. package/src/runtime/defaults.ts +0 -86
  177. package/src/runtime/deriveRespondsToProposals.ts +0 -35
  178. package/src/runtime/kickoff.ts +0 -117
  179. package/src/runtime/runMechanical.ts +0 -106
  180. package/src/runtime/runTurn.ts +0 -870
  181. package/src/runtime/validateWorkflow.ts +0 -221
  182. package/src/server/ConnectionPool.ts +0 -206
  183. package/src/server/EventQueue.ts +0 -133
  184. package/src/server/InboxCatchUp.ts +0 -291
  185. package/src/server/OutboxBuffer.ts +0 -90
  186. package/src/server/SeenMessages.ts +0 -27
  187. package/src/server/StateTimers.ts +0 -85
  188. package/src/server/ZiggsEffectHandler.ts +0 -427
  189. package/src/server/agreements/AgreementService.ts +0 -118
  190. package/src/server/createHealthServer.ts +0 -85
  191. package/src/server/proactive/ProactiveTrigger.ts +0 -83
  192. package/src/server/runLauncher.ts +0 -146
  193. package/src/server/tasks/TaskService.ts +0 -111
  194. package/src/server/telemetryIngest.ts +0 -91
  195. package/src/server/tools/tier1/protocolRunner.ts +0 -353
  196. package/src/server/tools/tier1/protocolTools.ts +0 -114
  197. package/src/server/tools/tier2/connectionTools.ts +0 -75
  198. package/src/server/tools/tier2/contextTools.ts +0 -63
  199. package/src/server/tools/tier2/discoveryTools.ts +0 -34
  200. package/src/server/tools/tier2/marketplaceTools.ts +0 -27
  201. package/src/server/tools/tier2/paymentTools.ts +0 -170
  202. package/src/server/ziggsconnect/ZiggsConnectClient.ts +0 -126
  203. package/src/server/ziggscontext/ZiggsContextClient.ts +0 -129
  204. package/src/server/ziggspay/ZiggsPayClient.ts +0 -193
  205. package/src/shared/ids.ts +0 -3
  206. package/src/shared/runtimeLog.ts +0 -72
  207. package/src/shared/types.ts +0 -29
  208. package/src/tasks/protocolRegistry.ts +0 -25
  209. package/src/tools/ToolManager.ts +0 -95
  210. package/src/tools/ToolProvider.ts +0 -19
  211. package/src/tools/defineTool.ts +0 -90
  212. package/src/tools/recordReport.ts +0 -82
  213. package/src/types.ts +0 -483
  214. package/src/utils/jsonExtractor.ts +0 -100
  215. /package/{src/adapters/index.ts → dist/adapters/index.d.ts} +0 -0
  216. /package/{src/agent/claudeSdkProtocol.ts → dist/agent/claudeSdkProtocol.js} +0 -0
  217. /package/{src/formatters/index.ts → dist/formatters/index.d.ts} +0 -0
  218. /package/{src/server/tasks/index.ts → dist/server/tasks/index.d.ts} +0 -0
@@ -0,0 +1,39 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import type { LlmMessage, LlmResponse, LlmToolSchema } from '../types.js';
3
+ interface AdapterOptions {
4
+ key?: string;
5
+ model?: string;
6
+ }
7
+ /**
8
+ * Anthropic adapter satisfying the same LlmAdapter contract as OpenAIAdapter:
9
+ * OpenAI-wire-shaped LlmMessage[] in, { content, tool_calls, usage } out.
10
+ * Selected by AgentHost when the configured model id starts with "claude".
11
+ */
12
+ export declare class AnthropicAdapter {
13
+ private client;
14
+ model: string;
15
+ constructor({ key, model }: AdapterOptions);
16
+ chat(prompt: string, tools?: LlmToolSchema[], _temperature?: number, systemHints?: LlmMessage[], options?: Record<string, unknown>): Promise<LlmResponse>;
17
+ chatMessages(messages: LlmMessage[], tools?: LlmToolSchema[], _options?: Record<string, unknown>): Promise<LlmResponse>;
18
+ chatMessagesStream(messages: LlmMessage[], onChunk: (text: string) => void): Promise<{
19
+ text: string;
20
+ usage: {
21
+ prompt_tokens: number;
22
+ completion_tokens: number;
23
+ total_tokens: number;
24
+ } | undefined;
25
+ }>;
26
+ }
27
+ /**
28
+ * Convert the runtime's tool list into Anthropic's `tools` param.
29
+ *
30
+ * The declared `LlmToolSchema` type (`{ type, function }`) is a lie at runtime:
31
+ * `runTurn` launders `ToolDefinition[]` (shape `{ schema: { function } }`)
32
+ * through an `as unknown as LlmToolSchema[]` cast before it reaches any adapter.
33
+ * OpenAIAdapter already reads `t.schema.function || t.schema`; this must do the
34
+ * same, or every claude-backed agent whose state exposes ≥1 tool crashes on
35
+ * `t.function` being undefined ("Cannot read properties of undefined (reading
36
+ * 'name')"). Both shapes are accepted so raw wire-shaped tools also work.
37
+ */
38
+ export declare function toAnthropicTools(tools?: LlmToolSchema[]): Anthropic.Tool[] | undefined;
39
+ export {};
@@ -0,0 +1,200 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { runtimeLog } from '../shared/runtimeLog.js';
3
+ // Claude 4.7+ models reject sampling params (temperature/top_p/top_k) with a
4
+ // 400 and run without thinking when the `thinking` param is omitted. We omit
5
+ // both on purpose: the SDK's LlmMessage history cannot round-trip thinking
6
+ // blocks through the tool loop, so thinking must stay off.
7
+ const MAX_COMPLETION_TOKENS = 16000;
8
+ /**
9
+ * Anthropic adapter satisfying the same LlmAdapter contract as OpenAIAdapter:
10
+ * OpenAI-wire-shaped LlmMessage[] in, { content, tool_calls, usage } out.
11
+ * Selected by AgentHost when the configured model id starts with "claude".
12
+ */
13
+ export class AnthropicAdapter {
14
+ client;
15
+ model;
16
+ constructor({ key, model = 'claude-opus-4-8' }) {
17
+ this.client = new Anthropic({ apiKey: key });
18
+ this.model = model;
19
+ }
20
+ async chat(prompt, tools = [], _temperature = 0, systemHints = [], options = {}) {
21
+ const messages = [
22
+ { role: 'system', content: 'Respond with valid JSON.' },
23
+ ...systemHints,
24
+ { role: 'user', content: prompt },
25
+ ];
26
+ return this.chatMessages(messages, tools, options);
27
+ }
28
+ async chatMessages(messages, tools = [], _options = {}) {
29
+ const { system, anthropicMessages } = translateMessages(messages);
30
+ const anthropicTools = toAnthropicTools(tools);
31
+ try {
32
+ const res = await this.client.messages.create({
33
+ model: this.model,
34
+ max_tokens: MAX_COMPLETION_TOKENS,
35
+ ...(system ? { system } : {}),
36
+ messages: anthropicMessages,
37
+ ...(anthropicTools ? { tools: anthropicTools } : {}),
38
+ });
39
+ if (res.stop_reason === 'refusal') {
40
+ throw new Error(`LLM refused the request (stop_reason=refusal)`);
41
+ }
42
+ const content = res.content
43
+ .filter((b) => b.type === 'text')
44
+ .map(b => b.text)
45
+ .join('')
46
+ .trim() || null;
47
+ const toolCalls = (() => {
48
+ const uses = res.content.filter((b) => b.type === 'tool_use');
49
+ if (!uses.length)
50
+ return null;
51
+ return uses.map(u => ({
52
+ id: u.id,
53
+ function: { name: u.name, arguments: JSON.stringify(u.input ?? {}) },
54
+ }));
55
+ })();
56
+ if (!content && !toolCalls && res.stop_reason === 'max_tokens') {
57
+ throw new Error(`LLM returned no usable output — completion token budget exhausted before any content (stop_reason=max_tokens)`);
58
+ }
59
+ return {
60
+ content: content ?? undefined,
61
+ tool_calls: toolCalls ?? undefined,
62
+ usage: res.usage
63
+ ? {
64
+ prompt_tokens: res.usage.input_tokens,
65
+ completion_tokens: res.usage.output_tokens,
66
+ total_tokens: res.usage.input_tokens + res.usage.output_tokens,
67
+ }
68
+ : undefined,
69
+ };
70
+ }
71
+ catch (error) {
72
+ const err = error;
73
+ runtimeLog.error('AnthropicAdapter', `LLM API call failed: ${err.message}`, {
74
+ model: this.model,
75
+ error: err.message,
76
+ status: err.status ?? 'unknown',
77
+ });
78
+ throw error;
79
+ }
80
+ }
81
+ async chatMessagesStream(messages, onChunk) {
82
+ const { system, anthropicMessages } = translateMessages(messages);
83
+ const stream = this.client.messages.stream({
84
+ model: this.model,
85
+ max_tokens: MAX_COMPLETION_TOKENS,
86
+ ...(system ? { system } : {}),
87
+ messages: anthropicMessages,
88
+ });
89
+ let text = '';
90
+ stream.on('text', (delta) => {
91
+ text += delta;
92
+ onChunk(delta);
93
+ });
94
+ const final = await stream.finalMessage();
95
+ const u = final.usage;
96
+ // Fold cache read/creation into prompt tokens so the streamed reply is not
97
+ // undercounted (cache traffic was the bulk of the ZIG-759 drain).
98
+ const usage = u
99
+ ? {
100
+ prompt_tokens: (u.input_tokens ?? 0) + (u.cache_read_input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0),
101
+ completion_tokens: u.output_tokens ?? 0,
102
+ total_tokens: (u.input_tokens ?? 0) + (u.cache_read_input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0) + (u.output_tokens ?? 0),
103
+ }
104
+ : undefined;
105
+ return { text, usage };
106
+ }
107
+ }
108
+ /**
109
+ * Convert the runtime's tool list into Anthropic's `tools` param.
110
+ *
111
+ * The declared `LlmToolSchema` type (`{ type, function }`) is a lie at runtime:
112
+ * `runTurn` launders `ToolDefinition[]` (shape `{ schema: { function } }`)
113
+ * through an `as unknown as LlmToolSchema[]` cast before it reaches any adapter.
114
+ * OpenAIAdapter already reads `t.schema.function || t.schema`; this must do the
115
+ * same, or every claude-backed agent whose state exposes ≥1 tool crashes on
116
+ * `t.function` being undefined ("Cannot read properties of undefined (reading
117
+ * 'name')"). Both shapes are accepted so raw wire-shaped tools also work.
118
+ */
119
+ export function toAnthropicTools(tools = []) {
120
+ if (!tools.length)
121
+ return undefined;
122
+ return tools.map(t => {
123
+ const td = t;
124
+ const fn = (td.schema?.function ?? td.function ?? {});
125
+ return {
126
+ name: fn['name'],
127
+ description: fn['description'] ?? '',
128
+ input_schema: (fn['parameters'] ?? { type: 'object' }),
129
+ };
130
+ });
131
+ }
132
+ /**
133
+ * OpenAI-wire-shaped LlmMessage[] → Anthropic { system, messages }.
134
+ * - system messages concatenate into the top-level system param
135
+ * - assistant tool_calls become tool_use blocks (arguments JSON-parsed)
136
+ * - role:"tool" results become user-turn tool_result blocks
137
+ * Consecutive same-role turns are merged (Anthropic requires alternation to
138
+ * start with user; the API tolerates consecutive same-role, but tool_result
139
+ * blocks must open the user turn that answers a tool_use turn).
140
+ */
141
+ function translateMessages(messages) {
142
+ const systemParts = [];
143
+ const out = [];
144
+ for (const m of messages) {
145
+ if (m.role === 'system') {
146
+ if (m.content)
147
+ systemParts.push(m.content);
148
+ continue;
149
+ }
150
+ if (m.role === 'tool') {
151
+ const block = {
152
+ type: 'tool_result',
153
+ tool_use_id: m.tool_call_id ?? '',
154
+ content: m.content ?? '',
155
+ };
156
+ const last = out[out.length - 1];
157
+ if (last && last.role === 'user' && Array.isArray(last.content)) {
158
+ last.content.push(block);
159
+ }
160
+ else {
161
+ out.push({ role: 'user', content: [block] });
162
+ }
163
+ continue;
164
+ }
165
+ if (m.role === 'assistant' && m.tool_calls?.length) {
166
+ const blocks = [];
167
+ if (m.content)
168
+ blocks.push({ type: 'text', text: m.content });
169
+ for (const tc of m.tool_calls) {
170
+ blocks.push({
171
+ type: 'tool_use',
172
+ id: tc.id,
173
+ name: tc.function.name,
174
+ input: safeParseJson(tc.function.arguments),
175
+ });
176
+ }
177
+ out.push({ role: 'assistant', content: blocks });
178
+ continue;
179
+ }
180
+ out.push({ role: m.role, content: m.content ?? '' });
181
+ }
182
+ if (!out.length || out[0].role !== 'user') {
183
+ out.unshift({ role: 'user', content: '(session start)' });
184
+ }
185
+ return {
186
+ system: systemParts.length ? systemParts.join('\n\n') : undefined,
187
+ anthropicMessages: out,
188
+ };
189
+ }
190
+ function safeParseJson(s) {
191
+ try {
192
+ const v = JSON.parse(s);
193
+ return typeof v === 'object' && v !== null ? v : {};
194
+ }
195
+ catch {
196
+ // Malformed arguments string from a prior turn's history: replaying it as
197
+ // an empty input beats crashing the whole turn on someone else's output.
198
+ return {};
199
+ }
200
+ }
@@ -0,0 +1,199 @@
1
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
2
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
+ import { AgentHost, type AgentHostOptions } from '../AgentHost.js';
4
+ import type { ToolDefinition } from '../tools/defineTool.js';
5
+ import type { Workflow } from '../types.js';
6
+ export type McpTransportConfig = {
7
+ type: 'stdio';
8
+ command: string;
9
+ args?: string[];
10
+ env?: Record<string, string>;
11
+ } | {
12
+ type: 'http';
13
+ url: string;
14
+ /**
15
+ * Optional static request headers — e.g. a fixed API key the server is
16
+ * keyed by. Sent on every request to the server. Values are used as-is;
17
+ * `$VAR` interpolation (if any) is the caller's job, mirroring how the
18
+ * stdio path leaves `env` interpolation to the caller.
19
+ */
20
+ headers?: Record<string, string>;
21
+ } | {
22
+ /**
23
+ * Brokered connection through the Ziggs MCP gateway: the agent speaks
24
+ * StreamableHTTP to `/connections/:id/mcp` and Ziggs injects the
25
+ * connection owner's OAuth token upstream. The agent never holds the
26
+ * token; every tools/call is checked against the grant's caveats.
27
+ */
28
+ type: 'ziggs';
29
+ /** Connection id (`con_…`) of the user's MCP server connection. */
30
+ connectionId: string;
31
+ /** ConnectionGrant id (`cgr_…`) issued to this agent. */
32
+ grantId: string;
33
+ /** Operator key — defaults to ZIGGS_OPERATOR_KEY. */
34
+ operatorKey?: string;
35
+ /** Ziggs backend base URL — defaults to BACKEND_URL / ZIGGS_BACKEND_URL. */
36
+ baseUrl?: string;
37
+ /** Agent to impersonate (X-Agent-Id) — defaults to the host agentId. */
38
+ agentId?: string;
39
+ } | {
40
+ /**
41
+ * Per-user brokered connection (ZIG-771): the agent holds NO
42
+ * connectionId/grantId. It speaks StreamableHTTP to
43
+ * `/connections/mcp/relay` and asserts the invoking end-user via
44
+ * `x-on-behalf-of-user`; the gateway resolves that user's own connection
45
+ * + grant and injects their token. One MCP client is created per invoking
46
+ * user so each keeps an isolated upstream session. Tool schemas cannot be
47
+ * discovered at boot (there is no connection yet) — pass `toolSchema`.
48
+ */
49
+ type: 'ziggs-per-user';
50
+ /** Operator key — defaults to ZIGGS_OPERATOR_KEY. */
51
+ operatorKey?: string;
52
+ /** Ziggs backend base URL — defaults to BACKEND_URL / ZIGGS_BACKEND_URL. */
53
+ baseUrl?: string;
54
+ /** Agent to impersonate (X-Agent-Id) — defaults to the host agentId. */
55
+ agentId?: string;
56
+ /**
57
+ * The MCP server URL this agent fronts. Not used for gateway calls (the
58
+ * gateway derives the server from the resolved connection), but needed to
59
+ * open a connection request when the invoking user hasn't connected yet
60
+ * (ZIG-771). Without it, a NO_USER_CONNECTION surfaces as an error rather
61
+ * than an auto-created consent prompt.
62
+ */
63
+ serverUrl?: string;
64
+ };
65
+ /**
66
+ * Typed failure from the Ziggs MCP gateway (ZIG-702). `code` is the stable
67
+ * machine-readable reason — e.g. `GRANT_REVOKED`, `GRANT_EXPIRED`,
68
+ * `GRANT_HOLDER_MISMATCH`, `GRANT_CONNECTION_MISMATCH` — so agent code can
69
+ * branch ("revoked → tell the user and stop retrying" vs "network blip →
70
+ * retry") instead of parsing transport-error prose.
71
+ */
72
+ export declare class ZiggsGatewayError extends Error {
73
+ readonly code: string;
74
+ readonly status: number;
75
+ constructor(code: string, message: string, status: number);
76
+ }
77
+ /**
78
+ * Wrap fetch so structured gateway denials (401/403 with a `code` body)
79
+ * surface as ZiggsGatewayError instead of a generic transport failure.
80
+ */
81
+ export declare function wrapGatewayFetch(baseFetch?: typeof fetch): typeof fetch;
82
+ /** Resolve the gateway URL + auth headers for a `type: 'ziggs'` transport. */
83
+ export declare function resolveZiggsGatewayTarget(config: Extract<McpTransportConfig, {
84
+ type: 'ziggs';
85
+ }>, defaults?: {
86
+ agentId?: string;
87
+ }): {
88
+ url: URL;
89
+ headers: Record<string, string>;
90
+ };
91
+ /**
92
+ * Resolve the per-user gateway URL + headers (ZIG-771). No connectionId/grantId —
93
+ * the gateway resolves the invoking user's own connection + grant from
94
+ * `x-on-behalf-of-user` + the impersonated agent.
95
+ */
96
+ export declare function resolvePerUserGatewayTarget(config: Extract<McpTransportConfig, {
97
+ type: 'ziggs-per-user';
98
+ }>, agentId: string, userId: string, onBehalfOfAgreementId?: string): {
99
+ url: URL;
100
+ headers: Record<string, string>;
101
+ };
102
+ export interface CreateMcpAgentOptions extends Omit<AgentHostOptions, 'tools' | 'workflow' | 'states' | 'initial'> {
103
+ /** MCP server connection — stdio (local process) or HTTP (remote). */
104
+ transport: McpTransportConfig;
105
+ /** Additional Ziggs tools to register alongside the MCP-derived ones. */
106
+ extraTools?: ToolDefinition[];
107
+ /** Override the default single-state thinking workflow. */
108
+ workflow?: Workflow;
109
+ /**
110
+ * Max tools to bind to the LLM per turn. LLM providers cap the `tools` array
111
+ * (OpenAI: 128); an MCP server exposing more (e.g. PostHog: 146) makes every
112
+ * turn fail with `400 ... array too long`. When the server's tool count
113
+ * exceeds this budget the list is truncated (and logged). Defaults to 128.
114
+ * See ZIG-759; Phase 2 will replace truncation with query-aware selection.
115
+ */
116
+ maxTools?: number;
117
+ /**
118
+ * Restrict the bound tool set to only tools whose name matches one of these
119
+ * case-insensitive substrings, applied BEFORE the maxTools cap. Lets a large
120
+ * MCP server (e.g. PostHog's 146 tools) be narrowed to the handful this agent
121
+ * actually needs — cutting per-turn cost and stopping the model from thrashing
122
+ * across (or never binding) the tool it should call. Empty/undefined = bind
123
+ * all (unchanged behavior). ZIG-759 Phase 2 = name-based selection.
124
+ */
125
+ allowedTools?: string[];
126
+ /**
127
+ * Pre-discovered MCP tool schemas. REQUIRED for `type: 'ziggs-per-user'`
128
+ * (ZIG-771) — there is no boot connection to call `tools/list` on, so the
129
+ * schema is baked at provision time and passed here. Ignored for the other
130
+ * transports, which discover tools live at boot.
131
+ */
132
+ toolSchema?: Array<{
133
+ name: string;
134
+ description?: string;
135
+ inputSchema?: Record<string, unknown>;
136
+ }>;
137
+ }
138
+ /**
139
+ * How many MCP tools may be bound to the LLM, given the provider cap and the
140
+ * number of extra (non-MCP) tools the agent also carries. Always >= 1 so a
141
+ * pathological config still binds something rather than nothing. ZIG-759.
142
+ */
143
+ export declare function mcpToolBudget(maxTools: number, extraToolCount: number): number;
144
+ export interface McpAgentHandle {
145
+ host: AgentHost;
146
+ /** Disconnect the MCP client (call on shutdown alongside host.disconnect()). */
147
+ closeMcp: () => Promise<void>;
148
+ /** Names of MCP tools that were mapped to Ziggs tools on startup. */
149
+ toolNames: string[];
150
+ }
151
+ export declare function buildTransport(config: McpTransportConfig, defaults?: {
152
+ agentId?: string;
153
+ }): StdioClientTransport | StreamableHTTPClientTransport;
154
+ /**
155
+ * Max chars for a single tool description bound to the LLM. Verbose MCP servers
156
+ * embed whole manuals in their descriptions (PostHog's `execute-sql` alone is
157
+ * ~30K chars of HogQL docs; its 146 tools total ~54K tokens of descriptions) and
158
+ * that full block rides every turn. Keep the lead — what the tool does + how to
159
+ * call it — and drop the embedded reference; agents fetch detail via dedicated
160
+ * schema/help tools at call time. Tunable; big enough to preserve real guidance.
161
+ * ZIG-759.
162
+ */
163
+ export declare const MAX_TOOL_DESC_CHARS = 2000;
164
+ /** Truncate one description at a sentence/newline boundary near the cap. */
165
+ export declare function trimDescription(desc: string | undefined): string | undefined;
166
+ /**
167
+ * Wraps any MCP server as a Ziggs AgentHost.
168
+ *
169
+ * 1. Opens a connection to the MCP server (stdio, HTTP, or the Ziggs gateway).
170
+ * 2. Calls tools/list and maps each tool to a Ziggs ToolDefinition.
171
+ * 3. Returns an AgentHost pre-loaded with those tools, ready to connectAsync().
172
+ *
173
+ * Usage (local stdio server):
174
+ * const { host, closeMcp } = await createMcpAgent({
175
+ * transport: { type: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-github'] },
176
+ * agentId: 'my-github-agent',
177
+ * name: 'GitHub Agent',
178
+ * description: 'Wraps the GitHub MCP server',
179
+ * });
180
+ * await host.connectAsync();
181
+ *
182
+ * Usage (OAuth-protected remote server, brokered through Ziggs — the user
183
+ * connected the server and issued this agent a grant; the agent never sees
184
+ * the user's token):
185
+ * const { host, closeMcp } = await createMcpAgent({
186
+ * transport: { type: 'ziggs', connectionId: 'con_abc', grantId: 'cgr_xyz' },
187
+ * agentId: 'my-notion-agent',
188
+ * name: 'Notion Agent',
189
+ * description: 'Works in the owner\'s Notion via their MCP connection',
190
+ * });
191
+ * await host.connectAsync();
192
+ *
193
+ * process.on('SIGTERM', async () => {
194
+ * host.disconnect();
195
+ * await host.drain();
196
+ * await closeMcp();
197
+ * });
198
+ */
199
+ export declare function createMcpAgent(options: CreateMcpAgentOptions): Promise<McpAgentHandle>;