@ziggs-ai/agent-sdk 0.1.11 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) 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/claudeSdkProtocol.js +27 -0
  20. package/dist/agent/claudeSdkTools.d.ts +19 -0
  21. package/dist/agent/claudeSdkTools.js +57 -0
  22. package/dist/agent/hostedAgentConnection.d.ts +15 -0
  23. package/dist/agent/hostedAgentConnection.js +29 -0
  24. package/dist/agent/toolManagerToSdkMcp.d.ts +12 -0
  25. package/dist/agent/toolManagerToSdkMcp.js +123 -0
  26. package/dist/brain/index.d.ts +50 -0
  27. package/dist/brain/index.js +45 -0
  28. package/dist/cognition/validateContext.d.ts +11 -0
  29. package/dist/cognition/validateContext.js +117 -0
  30. package/dist/context/applyEffects.d.ts +2 -0
  31. package/dist/context/applyEffects.js +89 -0
  32. package/dist/context/batch.d.ts +2 -0
  33. package/dist/context/batch.js +18 -0
  34. package/dist/context/classifyEnvelope.d.ts +1 -0
  35. package/dist/context/classifyEnvelope.js +58 -0
  36. package/dist/context/routingLabels.d.ts +4 -0
  37. package/dist/context/routingLabels.js +48 -0
  38. package/dist/defineAgent.d.ts +14 -0
  39. package/dist/defineAgent.js +68 -0
  40. package/dist/formatters/AgreementFormatter.d.ts +18 -0
  41. package/dist/formatters/AgreementFormatter.js +130 -0
  42. package/dist/formatters/HistoryFormatter.d.ts +26 -0
  43. package/dist/formatters/HistoryFormatter.js +173 -0
  44. package/dist/formatters/index.js +2 -0
  45. package/{src/index.ts → dist/index.d.ts} +13 -53
  46. package/dist/index.js +66 -0
  47. package/dist/ingress/normalizeIncoming.d.ts +65 -0
  48. package/dist/ingress/normalizeIncoming.js +88 -0
  49. package/dist/memory/MemoryStore.d.ts +55 -0
  50. package/dist/memory/MemoryStore.js +78 -0
  51. package/dist/pricing/fleetDefaults.d.ts +46 -0
  52. package/dist/pricing/fleetDefaults.js +168 -0
  53. package/dist/pricing/fleetEvalFree.d.ts +7 -0
  54. package/dist/pricing/fleetEvalFree.js +24 -0
  55. package/dist/pricing/fleetFreeTierA.gen.d.ts +6 -0
  56. package/{src/pricing/fleetFreeTierA.gen.ts → dist/pricing/fleetFreeTierA.gen.js} +5 -6
  57. package/dist/pricing/fleetTierByAgentId.gen.d.ts +7 -0
  58. package/dist/pricing/fleetTierByAgentId.gen.js +768 -0
  59. package/dist/runtime/AgentMachine.d.ts +143 -0
  60. package/dist/runtime/AgentMachine.js +400 -0
  61. package/dist/runtime/PromptBuilder.d.ts +96 -0
  62. package/dist/runtime/PromptBuilder.js +439 -0
  63. package/dist/runtime/bootstrapCtx.d.ts +18 -0
  64. package/dist/runtime/bootstrapCtx.js +37 -0
  65. package/dist/runtime/buildOutcome.d.ts +68 -0
  66. package/dist/runtime/buildOutcome.js +464 -0
  67. package/dist/runtime/defaults.d.ts +54 -0
  68. package/dist/runtime/defaults.js +47 -0
  69. package/dist/runtime/deriveRespondsToProposals.d.ts +9 -0
  70. package/dist/runtime/deriveRespondsToProposals.js +38 -0
  71. package/dist/runtime/kickoff.d.ts +15 -0
  72. package/dist/runtime/kickoff.js +112 -0
  73. package/dist/runtime/runMechanical.d.ts +25 -0
  74. package/dist/runtime/runMechanical.js +74 -0
  75. package/dist/runtime/runTurn.d.ts +63 -0
  76. package/dist/runtime/runTurn.js +800 -0
  77. package/dist/runtime/validateWorkflow.d.ts +17 -0
  78. package/dist/runtime/validateWorkflow.js +209 -0
  79. package/dist/server/ConnectionPool.d.ts +68 -0
  80. package/dist/server/ConnectionPool.js +166 -0
  81. package/dist/server/EventQueue.d.ts +33 -0
  82. package/dist/server/EventQueue.js +98 -0
  83. package/dist/server/InboxCatchUp.d.ts +24 -0
  84. package/dist/server/InboxCatchUp.js +213 -0
  85. package/dist/server/OutboxBuffer.d.ts +33 -0
  86. package/dist/server/OutboxBuffer.js +68 -0
  87. package/dist/server/SeenMessages.d.ts +13 -0
  88. package/dist/server/SeenMessages.js +31 -0
  89. package/dist/server/StateTimers.d.ts +34 -0
  90. package/dist/server/StateTimers.js +70 -0
  91. package/dist/server/ZiggsEffectHandler.d.ts +79 -0
  92. package/dist/server/ZiggsEffectHandler.js +319 -0
  93. package/dist/server/agreements/AgreementService.d.ts +50 -0
  94. package/dist/server/agreements/AgreementService.js +85 -0
  95. package/dist/server/createHealthServer.d.ts +7 -0
  96. package/dist/server/createHealthServer.js +75 -0
  97. package/dist/server/proactive/ProactiveTrigger.d.ts +33 -0
  98. package/dist/server/proactive/ProactiveTrigger.js +71 -0
  99. package/dist/server/runLauncher.d.ts +28 -0
  100. package/dist/server/runLauncher.js +93 -0
  101. package/dist/server/tasks/TaskService.d.ts +25 -0
  102. package/dist/server/tasks/TaskService.js +103 -0
  103. package/dist/server/tasks/index.js +1 -0
  104. package/dist/server/telemetryIngest.d.ts +24 -0
  105. package/dist/server/telemetryIngest.js +62 -0
  106. package/dist/server/tools/index.d.ts +24 -0
  107. package/{src/server/tools/index.ts → dist/server/tools/index.js} +4 -24
  108. package/dist/server/tools/tier1/protocolRunner.d.ts +39 -0
  109. package/dist/server/tools/tier1/protocolRunner.js +288 -0
  110. package/dist/server/tools/tier1/protocolTools.d.ts +12 -0
  111. package/dist/server/tools/tier1/protocolTools.js +37 -0
  112. package/dist/server/tools/tier2/connectionTools.d.ts +4 -0
  113. package/dist/server/tools/tier2/connectionTools.js +63 -0
  114. package/dist/server/tools/tier2/contextTools.d.ts +4 -0
  115. package/dist/server/tools/tier2/contextTools.js +46 -0
  116. package/dist/server/tools/tier2/discoveryTools.d.ts +4 -0
  117. package/dist/server/tools/tier2/discoveryTools.js +25 -0
  118. package/dist/server/tools/tier2/marketplaceTools.d.ts +3 -0
  119. package/dist/server/tools/tier2/marketplaceTools.js +22 -0
  120. package/dist/server/tools/tier2/paymentTools.d.ts +12 -0
  121. package/dist/server/tools/tier2/paymentTools.js +165 -0
  122. package/dist/server/ziggsconnect/ZiggsConnectClient.d.ts +35 -0
  123. package/dist/server/ziggsconnect/ZiggsConnectClient.js +95 -0
  124. package/dist/server/ziggscontext/ZiggsContextClient.d.ts +48 -0
  125. package/dist/server/ziggscontext/ZiggsContextClient.js +90 -0
  126. package/dist/server/ziggspay/ZiggsPayClient.d.ts +82 -0
  127. package/dist/server/ziggspay/ZiggsPayClient.js +188 -0
  128. package/dist/shared/ids.d.ts +1 -0
  129. package/dist/shared/ids.js +3 -0
  130. package/dist/shared/runtimeLog.d.ts +18 -0
  131. package/dist/shared/runtimeLog.js +68 -0
  132. package/dist/shared/types.d.ts +22 -0
  133. package/dist/shared/types.js +23 -0
  134. package/dist/tasks/protocolRegistry.d.ts +16 -0
  135. package/dist/tasks/protocolRegistry.js +20 -0
  136. package/dist/tools/ToolManager.d.ts +12 -0
  137. package/dist/tools/ToolManager.js +74 -0
  138. package/dist/tools/ToolProvider.d.ts +6 -0
  139. package/dist/tools/ToolProvider.js +21 -0
  140. package/dist/tools/defineTool.d.ts +27 -0
  141. package/dist/tools/defineTool.js +62 -0
  142. package/{src/tools/index.ts → dist/tools/index.d.ts} +0 -1
  143. package/dist/tools/index.js +6 -0
  144. package/dist/tools/recordReport.d.ts +41 -0
  145. package/dist/tools/recordReport.js +30 -0
  146. package/dist/types.d.ts +466 -0
  147. package/dist/types.js +7 -0
  148. package/dist/utils/jsonExtractor.d.ts +2 -0
  149. package/dist/utils/jsonExtractor.js +111 -0
  150. package/package.json +17 -7
  151. package/src/AgentHost.ts +0 -545
  152. package/src/adapters/AnthropicAdapter.ts +0 -206
  153. package/src/adapters/McpAdapter.ts +0 -348
  154. package/src/adapters/OpenAIAdapter.ts +0 -187
  155. package/src/agent/Agent.ts +0 -104
  156. package/src/cognition/validateContext.ts +0 -95
  157. package/src/context/applyEffects.ts +0 -80
  158. package/src/context/batch.ts +0 -19
  159. package/src/context/classifyEnvelope.ts +0 -38
  160. package/src/context/routingLabels.ts +0 -46
  161. package/src/defineAgent.ts +0 -70
  162. package/src/formatters/AgreementFormatter.ts +0 -111
  163. package/src/formatters/HistoryFormatter.ts +0 -172
  164. package/src/ingress/normalizeIncoming.ts +0 -162
  165. package/src/memory/MemoryStore.ts +0 -104
  166. package/src/pricing/fleetDefaults.ts +0 -225
  167. package/src/pricing/fleetEvalFree.ts +0 -24
  168. package/src/pricing/fleetTierByAgentId.gen.ts +0 -775
  169. package/src/runtime/AgentMachine.ts +0 -402
  170. package/src/runtime/PromptBuilder.ts +0 -485
  171. package/src/runtime/buildOutcome.ts +0 -563
  172. package/src/runtime/defaults.ts +0 -75
  173. package/src/runtime/kickoff.ts +0 -117
  174. package/src/runtime/runTurn.ts +0 -813
  175. package/src/runtime/validateWorkflow.ts +0 -202
  176. package/src/server/ConnectionPool.ts +0 -206
  177. package/src/server/EventQueue.ts +0 -133
  178. package/src/server/InboxCatchUp.ts +0 -254
  179. package/src/server/OutboxBuffer.ts +0 -90
  180. package/src/server/SeenMessages.ts +0 -27
  181. package/src/server/StateTimers.ts +0 -85
  182. package/src/server/ZiggsEffectHandler.ts +0 -418
  183. package/src/server/agreements/AgreementService.ts +0 -118
  184. package/src/server/createHealthServer.ts +0 -85
  185. package/src/server/proactive/ProactiveTrigger.ts +0 -83
  186. package/src/server/runLauncher.ts +0 -146
  187. package/src/server/tasks/TaskService.ts +0 -110
  188. package/src/server/telemetryIngest.ts +0 -91
  189. package/src/server/tools/tier1/protocolRunner.ts +0 -144
  190. package/src/server/tools/tier1/protocolTools.ts +0 -99
  191. package/src/server/tools/tier2/connectionTools.ts +0 -75
  192. package/src/server/tools/tier2/contextTools.ts +0 -63
  193. package/src/server/tools/tier2/discoveryTools.ts +0 -34
  194. package/src/server/tools/tier2/marketplaceTools.ts +0 -27
  195. package/src/server/tools/tier2/paymentTools.ts +0 -170
  196. package/src/server/ziggsconnect/ZiggsConnectClient.ts +0 -126
  197. package/src/server/ziggscontext/ZiggsContextClient.ts +0 -129
  198. package/src/server/ziggspay/ZiggsPayClient.ts +0 -193
  199. package/src/shared/ids.ts +0 -3
  200. package/src/shared/runtimeLog.ts +0 -72
  201. package/src/shared/types.ts +0 -29
  202. package/src/tasks/protocolRegistry.ts +0 -25
  203. package/src/tools/ToolManager.ts +0 -95
  204. package/src/tools/ToolProvider.ts +0 -19
  205. package/src/tools/defineTool.ts +0 -90
  206. package/src/tools/recordReport.ts +0 -82
  207. package/src/types.ts +0 -456
  208. package/src/utils/jsonExtractor.ts +0 -100
  209. /package/{src/adapters/index.ts → dist/adapters/index.d.ts} +0 -0
  210. /package/{src/formatters/index.ts → dist/formatters/index.d.ts} +0 -0
  211. /package/{src/server/tasks/index.ts → dist/server/tasks/index.d.ts} +0 -0
@@ -1,187 +0,0 @@
1
- import OpenAI from 'openai';
2
- import type { ToolDefinition } from '../tools/defineTool.js';
3
- import { runtimeLog } from '../shared/runtimeLog.js';
4
-
5
- interface ChatResult {
6
- content: string | null;
7
- tool_calls: OpenAI.Chat.ChatCompletionMessageToolCall[] | null;
8
- message: OpenAI.Chat.ChatCompletionMessage;
9
- usage: OpenAI.CompletionUsage | undefined;
10
- }
11
-
12
- interface AdapterOptions {
13
- key?: string;
14
- model?: string;
15
- }
16
-
17
- /** OpenAI completion-token cap varies by model family (e.g. gpt-4o-mini max 16384). */
18
- export function maxCompletionTokensForModel(model: string): number {
19
- const m = model.toLowerCase();
20
- if (m.includes('gpt-4o')) return 16384;
21
- return 25000;
22
- }
23
-
24
- export class OpenAIAdapter {
25
- private client: OpenAI;
26
- model: string;
27
-
28
- constructor({ key, model = 'gpt-5.4' }: AdapterOptions) {
29
- this.client = new OpenAI({ apiKey: key });
30
- this.model = model;
31
- }
32
-
33
- async chat(
34
- prompt: string,
35
- tools: ToolDefinition[] = [],
36
- temperature = 0.2,
37
- systemHints: OpenAI.Chat.ChatCompletionMessageParam[] = [],
38
- options: Record<string, unknown> = {},
39
- ): Promise<ChatResult> {
40
- const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [
41
- { role: 'system', content: 'Respond with valid JSON.' },
42
- ...systemHints,
43
- { role: 'user', content: prompt },
44
- ];
45
- return this.chatMessages(messages, tools, { ...options, temperature });
46
- }
47
-
48
- async chatMessages(
49
- messages: OpenAI.Chat.ChatCompletionMessageParam[],
50
- tools: ToolDefinition[] = [],
51
- options: Record<string, unknown> = {},
52
- ): Promise<ChatResult> {
53
- const openAITools: OpenAI.Chat.ChatCompletionTool[] | undefined = tools.length > 0
54
- ? tools.map(t => {
55
- const fn = (t.schema.function || t.schema) as Record<string, unknown>;
56
- const tAny = t as unknown as Record<string, unknown>;
57
- const usageWhen = tAny['usage']
58
- ? ` Use when: ${(tAny['usage'] as Record<string, unknown>)['when']}`
59
- : '';
60
- return {
61
- type: 'function' as const,
62
- function: {
63
- name: fn['name'] as string,
64
- description: ((fn['description'] as string) || '') + usageWhen,
65
- parameters: fn['parameters'] as Record<string, unknown>,
66
- },
67
- };
68
- })
69
- : undefined;
70
-
71
- try {
72
- const { usage: _u, response_format: _explicitResponseFormat, ...restOptions } = options as Record<string, unknown>;
73
- const responseFormat = openAITools
74
- ? undefined
75
- : ((_explicitResponseFormat as OpenAI.ResponseFormatJSONObject) ?? { type: 'json_object' });
76
-
77
- // OpenAI 400s response_format:{type:'json_object'} unless the word "json"
78
- // appears somewhere in the messages. Callers are expected to mention it
79
- // in their system prompt, but that's an implicit cross-file contract —
80
- // guarantee it here instead of trusting every call site to remember.
81
- let finalMessages = messages;
82
- if (
83
- responseFormat?.type === 'json_object' &&
84
- !messages.some(m => {
85
- const c = typeof m.content === 'string' ? m.content : JSON.stringify(m.content ?? '');
86
- return /json/i.test(c);
87
- })
88
- ) {
89
- finalMessages = [...messages, { role: 'system', content: 'Respond with valid JSON.' }];
90
- }
91
-
92
- // Verbose LLM request/response logging — enabled for debugging.
93
- // Comment out again to reduce log noise.
94
- const divider = '─'.repeat(80);
95
- console.log(`\n${divider}`);
96
- console.log(`📤 LLM REQUEST → ${this.model} (${finalMessages.length} msg${finalMessages.length === 1 ? '' : 's'})`);
97
- console.log(divider);
98
- for (const m of finalMessages) {
99
- const content = typeof m.content === 'string' ? m.content : JSON.stringify(m.content);
100
- const len = content?.length ?? 0;
101
- console.log(`\n[${m.role.toUpperCase()}] ${len} chars`);
102
- console.log(content ?? '');
103
- }
104
- console.log(`${divider}\n`);
105
- const res = await this.client.chat.completions.create({
106
- model: this.model,
107
- messages: finalMessages,
108
- stream: false,
109
- // Reasoning models (gpt-5.x/o-series) need a high cap for hidden
110
- // reasoning tokens; gpt-4o family is capped lower by the API.
111
- max_completion_tokens: maxCompletionTokensForModel(this.model),
112
- response_format: responseFormat,
113
- ...(openAITools && { tools: openAITools }),
114
- ...restOptions,
115
- } as OpenAI.Chat.ChatCompletionCreateParamsNonStreaming);
116
-
117
- const msg = res.choices[0].message;
118
- const finishReason = res.choices[0].finish_reason;
119
- const content = msg.content?.trim() ?? null;
120
- const toolCalls = msg.tool_calls?.length ? msg.tool_calls : null;
121
- // Verbose LLM response logging — enabled for debugging.
122
- // Comment out again to reduce log noise.
123
- console.log(`\n${divider}`);
124
- console.log(`📥 LLM RESPONSE ← ${this.model} finish=${finishReason}`);
125
- console.log(divider);
126
- if (content) {
127
- console.log(`\n[CONTENT] ${content.length} chars`);
128
- console.log(content);
129
- }
130
- if (toolCalls) {
131
- console.log(`\n[TOOL CALLS] ${toolCalls.length}`);
132
- for (const tc of toolCalls) {
133
- console.log(` → ${tc.function.name}(${tc.function.arguments})`);
134
- }
135
- }
136
- if (!content && !toolCalls) console.log('\n(no content, no tool calls)');
137
- if (res.usage) {
138
- const u = res.usage as OpenAI.CompletionUsage & { completion_tokens_details?: { reasoning_tokens?: number } };
139
- console.log(`\n[USAGE] prompt=${u.prompt_tokens} completion=${u.completion_tokens}${u.completion_tokens_details?.reasoning_tokens != null ? ` (reasoning=${u.completion_tokens_details.reasoning_tokens})` : ''} total=${u.total_tokens}`);
140
- }
141
- console.log(`${divider}\n`);
142
- if (!content && !toolCalls && finishReason === 'length') {
143
- const u = res.usage as (OpenAI.CompletionUsage & { completion_tokens_details?: { reasoning_tokens?: number } }) | undefined;
144
- throw new Error(
145
- `LLM returned no usable output — completion token budget exhausted before any content ` +
146
- `(finish_reason=length, reasoning_tokens=${u?.completion_tokens_details?.reasoning_tokens ?? 'unknown'})`,
147
- );
148
- }
149
- return {
150
- content,
151
- tool_calls: toolCalls,
152
- message: msg,
153
- usage: res.usage,
154
- };
155
- } catch (error) {
156
- const err = error as Error & { status?: number; code?: string };
157
- runtimeLog.error('OpenAIAdapter', `LLM API call failed: ${err.message}`, {
158
- model: this.model,
159
- error: err.message,
160
- status: err.status || 'unknown',
161
- code: err.code || 'unknown',
162
- });
163
- throw error;
164
- }
165
- }
166
-
167
- async chatMessagesStream(
168
- messages: OpenAI.Chat.ChatCompletionMessageParam[],
169
- onChunk: (text: string) => void,
170
- ): Promise<string> {
171
- const stream = await this.client.chat.completions.create({
172
- model: this.model,
173
- messages,
174
- stream: true,
175
- max_completion_tokens: maxCompletionTokensForModel(this.model),
176
- });
177
- let text = '';
178
- for await (const chunk of stream) {
179
- const delta = chunk.choices[0]?.delta?.content;
180
- if (delta) {
181
- text += delta;
182
- onChunk(delta);
183
- }
184
- }
185
- return text;
186
- }
187
- }
@@ -1,104 +0,0 @@
1
- import type { Ctx, Identity, Workflow, EffectHandler } from '../types.js';
2
- import { AgentMachine, type TransitionEvent } from '../runtime/AgentMachine.js';
3
- import { runTurn } from '../runtime/runTurn.js';
4
- import { PromptBuilder } from '../runtime/PromptBuilder.js';
5
- import type { MemoryStore } from '../memory/MemoryStore.js';
6
- import type { ToolManager } from '../tools/ToolManager.js';
7
- import type { RawEvent } from '../runtime/buildOutcome.js';
8
-
9
- export interface AgentOptions {
10
- workflow: Workflow;
11
- toolManager: ToolManager;
12
- promptBuilder?: PromptBuilder;
13
- }
14
-
15
- export interface TickInput {
16
- /** Wire event (already normalized: a `message` or `task_result`-style envelope). */
17
- event: unknown;
18
- /** Server-provided per-session state. Omit on the first tick — a fresh ctx is constructed. */
19
- ctx?: Ctx;
20
- /** Server-provided workflow state name. Omit on the first tick — defaults to `workflow.initial`. */
21
- state?: string;
22
- /** Who am I and what session am I running in. The Agent carries this through Ctx. */
23
- identity: Identity;
24
- /** The single side channel for I/O — LLM, context, tools, send, record. */
25
- eff: EffectHandler;
26
- /**
27
- * Agent-private long-term memory. Operator-provided (default
28
- * `InMemoryStore` when omitted by `AgentHost`). Key shape is the agent's
29
- * choice — `counterparty:<id>`, `agreement:<id>:notes`, etc.
30
- */
31
- memory?: MemoryStore;
32
- /** Optional tap for FSM transition events (ZIG-442). */
33
- transitionTap?: (event: TransitionEvent) => void;
34
- }
35
-
36
- export interface TickOutput {
37
- /** Updated ctx — Server persists this against the session. */
38
- ctx: Ctx;
39
- /** Workflow state name after the tick — Server persists this against the session. */
40
- state: string;
41
- /** Whether the machine settled at a parked state. */
42
- parked: boolean;
43
- /** True when a state-timeout outcome matched no transition this tick — the host must NOT re-arm. */
44
- stateTimeoutUnhandled: boolean;
45
- /** Accumulated LLM call count and token usage for this tick. */
46
- metrics: { llmCalls: number; tokens: { total: number; input: number; output: number } };
47
- }
48
-
49
- /**
50
- * Pure agent: workflow definition + cognition machinery. No I/O, no transport,
51
- * no services. The Agent's only side channel is the `eff` handler it receives
52
- * on each `tick`. Server-side state (sessions, lanes, queue, outbox) lives in
53
- * `AgentHost` — not here.
54
- *
55
- * The contract:
56
- *
57
- * `tick({ event, ctx, state, identity, eff })` →
58
- * `{ ctx, state, parked }`
59
- *
60
- * Reads top-to-bottom like a synchronous function. Every `await eff(...)`
61
- * inside the cognition core is a yield to the Server, which performs the
62
- * impure operation and resumes the Agent with the result.
63
- */
64
- export class Agent {
65
- workflow: Workflow;
66
- toolManager: ToolManager;
67
- promptBuilder: PromptBuilder;
68
-
69
- constructor({ workflow, toolManager, promptBuilder }: AgentOptions) {
70
- if (!workflow?.states) throw new Error('Agent: workflow with states is required');
71
- if (!toolManager) throw new Error('Agent: toolManager is required');
72
- this.workflow = workflow;
73
- this.toolManager = toolManager;
74
- this.promptBuilder = promptBuilder || new PromptBuilder();
75
- }
76
-
77
- async tick({ event, ctx, state, identity, eff, memory, transitionTap }: TickInput): Promise<TickOutput> {
78
- if (!identity?.sessionId) throw new Error('Agent.tick: identity.sessionId is required');
79
- if (!eff) throw new Error('Agent.tick: eff is required');
80
-
81
- const machine = new AgentMachine({
82
- workflow: this.workflow,
83
- executionCore: runTurn,
84
- eff,
85
- toolManager: this.toolManager,
86
- promptBuilder: this.promptBuilder,
87
- memory,
88
- input: { identity, ctx, state },
89
- transitionTap,
90
- });
91
-
92
- // `send` awaits the recursive _step until the machine settles at a
93
- // parked state (or stops). When it returns, we have the final state.
94
- await machine.send({ event: event as RawEvent | undefined, identity });
95
-
96
- return {
97
- ctx: machine.ctx,
98
- state: machine.state,
99
- parked: machine.isParked,
100
- stateTimeoutUnhandled: machine.stateTimeoutUnhandled,
101
- metrics: { llmCalls: machine.llmCalls, tokens: machine.tokens },
102
- };
103
- }
104
- }
@@ -1,95 +0,0 @@
1
- export class ContextWarning {
2
- constructor(public path: string, public message: string) {}
3
- toString(): string { return `[context] ${this.path}: ${this.message}`; }
4
- }
5
-
6
- type WarnFn = (path: string, msg: string) => void;
7
-
8
- export function validateContext(
9
- ctx: unknown,
10
- { logger }: { logger?: { warn: (msg: string) => void } } = {},
11
- ): ContextWarning[] {
12
- const warnings: ContextWarning[] = [];
13
- const warn: WarnFn = (path, msg) => warnings.push(new ContextWarning(path, msg));
14
-
15
- if (!ctx || typeof ctx !== 'object') {
16
- warn('context', 'missing or not an object');
17
- return warnings;
18
- }
19
-
20
- const c = ctx as Record<string, unknown>;
21
- validateAgreements(c['agreements'], warn);
22
- validateAgents(c['agents'], warn);
23
- validateHistory(c['history'], warn);
24
- validateUsers(c['users'], warn);
25
-
26
- if (logger && warnings.length > 0) {
27
- for (const w of warnings) logger.warn(w.toString());
28
- }
29
- return warnings;
30
- }
31
-
32
- function validateAgreements(agreements: unknown, warn: WarnFn): void {
33
- if (!Array.isArray(agreements)) return;
34
- for (let i = 0; i < agreements.length; i++) {
35
- const ag = agreements[i] as Record<string, unknown>;
36
- const path = `agreements[${i}]`;
37
- if (!ag || typeof ag !== 'object') { warn(path, 'not an object'); continue; }
38
- for (const key of ['agreementId', 'parties']) {
39
- if (ag[key] == null) warn(`${path}.${key}`, 'missing');
40
- }
41
- if (ag['parties'] && typeof ag['parties'] === 'object') {
42
- const parties = ag['parties'] as Record<string, unknown>;
43
- for (const key of ['creator', 'provider']) {
44
- if (!parties[key]) warn(`${path}.parties.${key}`, 'missing');
45
- }
46
- }
47
- if (ag['proposal'] && typeof ag['proposal'] === 'object') {
48
- if (!(ag['proposal'] as Record<string, unknown>)['status']) warn(`${path}.proposal.status`, 'missing');
49
- }
50
- if (ag['task'] && typeof ag['task'] === 'object') {
51
- const t = ag['task'] as Record<string, unknown>;
52
- if (!t['taskId']) warn(`${path}.task.taskId`, 'missing');
53
- if (!t['state']) warn(`${path}.task.state`, 'missing');
54
- }
55
- }
56
- }
57
-
58
- function validateAgents(agents: unknown, warn: WarnFn): void {
59
- if (!Array.isArray(agents)) return;
60
- let youCount = 0;
61
- for (let i = 0; i < agents.length; i++) {
62
- const agent = agents[i] as Record<string, unknown>;
63
- const path = `agents[${i}]`;
64
- if (!agent || typeof agent !== 'object') { warn(path, 'not an object'); continue; }
65
- if (!agent['agentId']) warn(`${path}.agentId`, 'missing');
66
- if (agent['isYou']) youCount++;
67
- }
68
- if (agents.length > 0 && youCount === 0) warn('agents', 'no agent has isYou=true — agent identity will be unknown');
69
- if (youCount > 1) warn('agents', `${youCount} agents have isYou=true — should be exactly 1`);
70
- }
71
-
72
- function validateHistory(history: unknown, warn: WarnFn): void {
73
- if (!Array.isArray(history)) return;
74
- for (let i = 0; i < history.length; i++) {
75
- const entry = history[i] as Record<string, unknown>;
76
- const path = `history[${i}]`;
77
- if (!entry || typeof entry !== 'object') { warn(path, 'not an object'); continue; }
78
- if (!entry['entryType'] && entry['entryType'] !== 0) warn(`${path}.entryType`, 'missing');
79
- if (entry['entryType'] === 'message' && !entry['sender']) warn(`${path}.sender`, 'missing for message entry');
80
- if (entry['entryType'] === 'task_history') {
81
- const svc = entry['service'] as Record<string, unknown> | undefined;
82
- if (!svc?.['task']) warn(`${path}.service.task`, 'missing for task_history entry');
83
- }
84
- }
85
- }
86
-
87
- function validateUsers(users: unknown, warn: WarnFn): void {
88
- if (!Array.isArray(users)) return;
89
- for (let i = 0; i < users.length; i++) {
90
- const user = users[i] as Record<string, unknown>;
91
- const path = `users[${i}]`;
92
- if (!user || typeof user !== 'object') { warn(path, 'not an object'); continue; }
93
- if (!user['userId']) warn(`${path}.userId`, 'missing');
94
- }
95
- }
@@ -1,80 +0,0 @@
1
- import { isProtocolToolName, mapProtocolToolToOperation } from '../tasks/protocolRegistry.js';
2
-
3
- function applyTaskOperationResultToContext(updates: Record<string, unknown>, operation: string | null, result: Record<string, unknown>): void {
4
- const r = result || {};
5
- const agreement = (r['agreement'] as Record<string, unknown>) ||
6
- (r['agreementId'] ? r : null);
7
- const task = (r['task'] as Record<string, unknown>) || (r['taskId'] ? r : null);
8
-
9
- if (operation === 'agreement-propose' || operation === 'agreement-subcontract') {
10
- // Agreement creation no longer spawns a task. The caller has made a
11
- // proposal that the proposedTo party still needs to approve.
12
- if (agreement) updates['proposal'] = r;
13
- }
14
- if (operation === 'task-spawn') {
15
- if (task) {
16
- updates['delegatedTask'] = r;
17
- if (task['taskId']) {
18
- if (!updates['_delegatedTaskIds']) updates['_delegatedTaskIds'] = [];
19
- (updates['_delegatedTaskIds'] as string[]).push(task['taskId'] as string);
20
- }
21
- }
22
- }
23
- if (operation === 'task-update') {
24
- const status = (task?.['state'] || r['state'] || r['status']) as string | undefined;
25
- if (status === 'completed') updates['taskCompleted'] = true;
26
- if (status === 'failed') updates['taskFailed'] = true;
27
- }
28
- if (operation === 'agreement-respond') updates['respondedProposal'] = r;
29
- }
30
-
31
- export const CONTEXT_RESET: Record<string, unknown> = Object.freeze({
32
- messageSent: false, activeWait: false, proposal: null, taskCompleted: false,
33
- taskFailed: false, subtaskResult: null, subtaskFailed: false, toolResults: null,
34
- lastError: null, lastAction: null, lastActionResult: null, approval: false,
35
- rejection: false, taskAssignment: null, incomingMessage: false,
36
- respondedProposal: null, searchCompleted: false, boardResults: null, taskPublished: false,
37
- });
38
-
39
- export function buildContextUpdates(actionName: string, emittedEvents: unknown[]): Record<string, unknown> {
40
- const updates: Record<string, unknown> = { ...CONTEXT_RESET, lastAction: actionName };
41
- if (!Array.isArray(emittedEvents)) return updates;
42
- const toolResults: unknown[] = [];
43
-
44
- for (const ev of emittedEvents) {
45
- if (!ev || typeof ev !== 'object') continue;
46
- const events = Array.isArray(ev) ? ev : [ev];
47
- for (const e of events) {
48
- const event = e as Record<string, unknown>;
49
- switch (event['type']) {
50
- case 'tool_result':
51
- toolResults.push({ tool: event['tool'], result: event['result'] });
52
- updates['lastActionResult'] = event;
53
- if (isProtocolToolName(event['tool'] as string)) {
54
- applyTaskOperationResultToContext(updates, mapProtocolToolToOperation(event['tool'] as string), (event['result'] as Record<string, unknown>) || {});
55
- }
56
- break;
57
- case 'tool_error':
58
- toolResults.push({ tool: event['tool'], error: event['error'] });
59
- updates['lastActionResult'] = event;
60
- updates['lastError'] = event['error'];
61
- break;
62
- case 'message_sent':
63
- updates['messageSent'] = true; updates['lastActionResult'] = event; break;
64
- case 'message_duplicate_skipped':
65
- updates['messageSent'] = true; break;
66
- case 'waited':
67
- updates['activeWait'] = true; break;
68
- case 'task_result': {
69
- updates['lastActionResult'] = event;
70
- applyTaskOperationResultToContext(updates, (event['operation'] as string) || null, (event['result'] as Record<string, unknown>) || {});
71
- break;
72
- }
73
- case 'task_error':
74
- updates['lastError'] = event['error']; updates['lastActionResult'] = event; break;
75
- }
76
- }
77
- }
78
- if (toolResults.length > 0) updates['toolResults'] = toolResults;
79
- return updates;
80
- }
@@ -1,19 +0,0 @@
1
- import { isBroadcastTarget } from '@ziggs-ai/api-client';
2
-
3
- export function getBatchEvents(rawEvent: unknown): unknown[] {
4
- if (!rawEvent) return [];
5
- const e = rawEvent as Record<string, unknown>;
6
- if (e['type'] === 'batch' && Array.isArray(e['events'])) return e['events'] as unknown[];
7
- return [rawEvent];
8
- }
9
-
10
- export function isTaskResultRelevantToAgent(result: Record<string, unknown>, ownAgentId: string | null): boolean {
11
- if (!ownAgentId) return true;
12
- const parties = (result['agreement'] as Record<string, unknown> | undefined)?.['parties'] as Record<string, unknown> | undefined ?? {};
13
- return !!(
14
- result['creatorIsYou'] || result['providerIsYou'] || result['payerIsYou'] || result['proposedToIsYou'] ||
15
- parties['creator'] === ownAgentId || parties['provider'] === ownAgentId ||
16
- parties['payer'] === ownAgentId || parties['proposedTo'] === ownAgentId ||
17
- isBroadcastTarget(parties['proposedTo'] as string | undefined)
18
- );
19
- }
@@ -1,38 +0,0 @@
1
- import { CONTEXT_RESET } from './applyEffects.js';
2
- import { getBatchEvents, isTaskResultRelevantToAgent } from './batch.js';
3
-
4
- function isTaskAssignment(result: Record<string, unknown>, ownAgentId: string | null): boolean {
5
- const parties = (result['agreement'] as Record<string, unknown> | undefined)?.['parties'] as Record<string, unknown> | undefined ?? {};
6
- const isProvider = result['providerIsYou'] || parties['provider'] === ownAgentId;
7
- return !!(isProvider && (result['state'] === 'active' || result['state'] === 'in-progress'));
8
- }
9
-
10
- export function classifyIncomingEvent(rawEvent: unknown, ownAgentId: string | null): Record<string, unknown> {
11
- const flags: Record<string, unknown> = { ...CONTEXT_RESET };
12
- if (!rawEvent) return flags;
13
-
14
- for (const ev of getBatchEvents(rawEvent)) {
15
- if (!ev) continue;
16
- const e = ev as Record<string, unknown>;
17
- if (e['type'] !== 'task_result') { flags['incomingMessage'] = true; continue; }
18
-
19
- const result = (e['result'] as Record<string, unknown>) || {};
20
- if (ownAgentId && !isTaskResultRelevantToAgent(result, ownAgentId) && e['receiverId'] !== ownAgentId) continue;
21
-
22
- const state = result['state'] as string | undefined;
23
- const ag = result['agreement'] as Record<string, unknown> | undefined;
24
- const parties = (ag?.['parties'] as Record<string, unknown>) || {};
25
- const proposalStatus = (ag?.['proposal'] as Record<string, unknown> | undefined)?.['status'];
26
-
27
- if (state === 'active' && proposalStatus === 'approved' && ownAgentId && parties['creator'] === ownAgentId) {
28
- flags['approval'] = true; flags['taskAssignment'] = result; continue;
29
- }
30
- if (isTaskAssignment(result, ownAgentId)) { flags['taskAssignment'] = result; flags['approval'] = true; continue; }
31
- if (proposalStatus === 'approved' || (state === 'active' && proposalStatus === 'pending')) { flags['approval'] = true; flags['taskAssignment'] = result; continue; }
32
- if (proposalStatus === 'rejected' || state === 'cancelled') { flags['rejection'] = true; continue; }
33
- if (state === 'completed') { flags['subtaskResult'] = result; continue; }
34
- if (state === 'failed') { flags['subtaskResult'] = result; flags['subtaskFailed'] = true; continue; }
35
- flags['subtaskResult'] = result;
36
- }
37
- return flags;
38
- }
@@ -1,46 +0,0 @@
1
- import { isProtocolToolName } from '../tasks/protocolRegistry.js';
2
- import { getBatchEvents, isTaskResultRelevantToAgent } from './batch.js';
3
-
4
- export function unwrapBatchEvent(event: unknown): unknown {
5
- const e = event as Record<string, unknown> | null | undefined;
6
- if (e?.['type'] === 'batch' && Array.isArray(e['events']) && e['events'][0]) return e['events'][0];
7
- return event;
8
- }
9
-
10
- export function classifyWorkflowEvent(event: unknown, ownAgentId: string | null = null): string {
11
- const events = getBatchEvents(event);
12
- if (events.length === 0) return 'message';
13
-
14
- let sawTaskResult = false, sawOwnTaskResult = false;
15
-
16
- for (const ev of events) {
17
- const e = ev as Record<string, unknown> | null | undefined;
18
- if (e?.['type'] !== 'task_result') continue;
19
- sawTaskResult = true;
20
- const result = (e['result'] as Record<string, unknown>) || {};
21
- if (!isTaskResultRelevantToAgent(result, ownAgentId)) continue;
22
- sawOwnTaskResult = true;
23
- const state = result['state'] as string | undefined;
24
- const ag = result['agreement'] as Record<string, unknown> | undefined;
25
- const parties = (ag?.['parties'] as Record<string, unknown>) || {};
26
- const proposalStatus = ag?.['proposal'] ? (ag['proposal'] as Record<string, unknown>)['status'] : undefined;
27
- const isProvider = result['providerIsYou'] || parties['provider'] === ownAgentId;
28
- if (isProvider && (state === 'active' || state === 'in-progress')) return 'task_assignment';
29
- if (proposalStatus === 'approved' || (state === 'active' && proposalStatus === 'pending')) return 'task_approved';
30
- if (proposalStatus === 'rejected' || state === 'cancelled') return 'task_rejected';
31
- }
32
- if (sawOwnTaskResult || sawTaskResult) return 'task_update';
33
- return 'message';
34
- }
35
-
36
- export function findTaskResult(output: Record<string, unknown> | null | undefined): unknown {
37
- const events = (output?.['emittedEvents'] as unknown[]) ?? [];
38
- return events.find(e => {
39
- const ev = e as Record<string, unknown>;
40
- return ev['type'] === 'task_result' || (ev['type'] === 'tool_result' && isProtocolToolName(ev['tool'] as string));
41
- }) ?? null;
42
- }
43
-
44
- export function findIncomingTaskResult(incomingEvent: unknown): unknown {
45
- return getBatchEvents(incomingEvent).find(e => (e as Record<string, unknown>)?.['type'] === 'task_result') ?? null;
46
- }
@@ -1,70 +0,0 @@
1
- import type { AgentConfig, DefineAgentInput, Workflow } from './types.js';
2
- import { validateWorkflow } from './runtime/validateWorkflow.js';
3
- import { injectKickoffDefault } from './runtime/kickoff.js';
4
- import { runtimeLog } from './shared/runtimeLog.js';
5
-
6
- /**
7
- * Validates the workflow synchronously, resolves merged tools and model, and
8
- * returns a frozen AgentConfig. Never mutates the input. `wait` defaults remain
9
- * the author's visible spread of `thinkingDefaults`. ONE default is injected (as
10
- * new objects): the agreement-kickoff state `kickingOff` plus a last-position
11
- * transition into it, appended to every state that does not already handle a
12
- * proposer-side proposal-resolved/approve outcome (runtime/kickoff.ts). The
13
- * state name 'kickingOff' is reserved; defining it throws.
14
- *
15
- * Validation throws WorkflowValidationError on hard problems and logs warnings
16
- * on soft ones (e.g. missing wait fallthrough).
17
- */
18
- export function defineAgent(input: DefineAgentInput): AgentConfig {
19
- if (!input?.agentId) throw new Error('[defineAgent] agentId is required');
20
- if (!input?.description) throw new Error('[defineAgent] description is required');
21
- if (!input?.states) throw new Error('[defineAgent] states is required');
22
- if (!input?.initial) throw new Error('[defineAgent] initial state is required');
23
-
24
- // Agreement-kickoff default (see runtime/kickoff.ts): injected BEFORE
25
- // validation so the injected state/transitions are validated too.
26
- const workflow: Workflow = injectKickoffDefault({
27
- id: input.agentId,
28
- description: input.description,
29
- initial: input.initial,
30
- states: input.states,
31
- });
32
-
33
- const { warnings } = validateWorkflow(workflow);
34
- for (const w of warnings) runtimeLog.warn('defineAgent', w);
35
-
36
- const tools = [
37
- ...(Array.isArray(input.tools) ? input.tools : []),
38
- ...(Array.isArray(input.services?.tools) ? input.services!.tools! : []),
39
- ];
40
-
41
- const model =
42
- input.services?.llm?.model ||
43
- process.env.LLM_MODEL ||
44
- process.env.OPENAI_MODEL ||
45
- 'gpt-5.4';
46
-
47
- // Strip the structural fields we already consumed; pass through everything
48
- // else (operatorKey, taskTools, custom keys consumed by AgentHost).
49
- const {
50
- agentId, description, specialization, services: _services, initial: _initial,
51
- states: _states, tools: _tools, operatorKey, taskTools, ...rest
52
- } = input;
53
-
54
- const config: AgentConfig = {
55
- openaiKey: process.env.OPENAI_API_KEY,
56
- anthropicKey: process.env.ANTHROPIC_API_KEY,
57
- ...(operatorKey ? { operatorKey } : {}),
58
- agentId,
59
- description,
60
- ...(specialization ? { specialization } : {}),
61
- tools,
62
- model,
63
- workflow,
64
- ...(input.services ? { services: input.services } : {}),
65
- ...(taskTools !== undefined ? { taskTools } : {}),
66
- ...rest,
67
- };
68
-
69
- return Object.freeze(config) as AgentConfig;
70
- }