connectonion 0.0.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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +362 -0
  3. package/dist/connect.d.ts +35 -0
  4. package/dist/connect.d.ts.map +1 -0
  5. package/dist/connect.js +149 -0
  6. package/dist/console.d.ts +30 -0
  7. package/dist/console.d.ts.map +1 -0
  8. package/dist/console.js +124 -0
  9. package/dist/core/agent.d.ts +233 -0
  10. package/dist/core/agent.d.ts.map +1 -0
  11. package/dist/core/agent.js +500 -0
  12. package/dist/examples/comprehensive-test.js +314 -0
  13. package/dist/examples/simple-test.js +80 -0
  14. package/dist/history/index.d.ts +42 -0
  15. package/dist/history/index.d.ts.map +1 -0
  16. package/dist/history/index.js +140 -0
  17. package/dist/index.d.ts +20 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +53 -0
  20. package/dist/llm/anthropic.d.ts +23 -0
  21. package/dist/llm/anthropic.d.ts.map +1 -0
  22. package/dist/llm/anthropic.js +139 -0
  23. package/dist/llm/gemini.d.ts +20 -0
  24. package/dist/llm/gemini.d.ts.map +1 -0
  25. package/dist/llm/gemini.js +136 -0
  26. package/dist/llm/index.d.ts +18 -0
  27. package/dist/llm/index.d.ts.map +1 -0
  28. package/dist/llm/index.js +76 -0
  29. package/dist/llm/llm-do.d.ts +8 -0
  30. package/dist/llm/llm-do.d.ts.map +1 -0
  31. package/dist/llm/llm-do.js +25 -0
  32. package/dist/llm/noop.d.ts +16 -0
  33. package/dist/llm/noop.d.ts.map +1 -0
  34. package/dist/llm/noop.js +23 -0
  35. package/dist/llm/openai.d.ts +21 -0
  36. package/dist/llm/openai.d.ts.map +1 -0
  37. package/dist/llm/openai.js +131 -0
  38. package/dist/src/core/agent.js +368 -0
  39. package/dist/src/history/index.js +140 -0
  40. package/dist/src/index.js +34 -0
  41. package/dist/src/llm/index.js +22 -0
  42. package/dist/src/llm/openai.js +78 -0
  43. package/dist/src/tools/tool-utils.js +348 -0
  44. package/dist/src/types.js +8 -0
  45. package/dist/tools/email.d.ts +13 -0
  46. package/dist/tools/email.d.ts.map +1 -0
  47. package/dist/tools/email.js +98 -0
  48. package/dist/tools/replay.d.ts +19 -0
  49. package/dist/tools/replay.d.ts.map +1 -0
  50. package/dist/tools/replay.js +62 -0
  51. package/dist/tools/tool-executor.d.ts +58 -0
  52. package/dist/tools/tool-executor.d.ts.map +1 -0
  53. package/dist/tools/tool-executor.js +100 -0
  54. package/dist/tools/tool-utils.d.ts +133 -0
  55. package/dist/tools/tool-utils.d.ts.map +1 -0
  56. package/dist/tools/tool-utils.js +380 -0
  57. package/dist/tools/xray.d.ts +58 -0
  58. package/dist/tools/xray.d.ts.map +1 -0
  59. package/dist/tools/xray.js +110 -0
  60. package/dist/trust/index.d.ts +26 -0
  61. package/dist/trust/index.d.ts.map +1 -0
  62. package/dist/trust/index.js +47 -0
  63. package/dist/trust/tools.d.ts +4 -0
  64. package/dist/trust/tools.d.ts.map +1 -0
  65. package/dist/trust/tools.js +71 -0
  66. package/dist/types.d.ts +141 -0
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +10 -0
  69. package/package.json +63 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ConnectOnion Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,362 @@
1
+ # 🚀 ConnectOnion TypeScript SDK
2
+
3
+ > **Build AI agents that actually DO things** - Zero boilerplate, maximum power
4
+
5
+ [![npm version](https://img.shields.io/npm/v/connectonion.svg)](https://www.npmjs.com/package/connectonion)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## ✨ What is ConnectOnion?
10
+
11
+ ConnectOnion is a TypeScript SDK that makes building AI agents ridiculously simple. Your functions become tools. Your classes become toolsets. Your agents just work.
12
+
13
+ ```typescript
14
+ // This is all you need for a working AI agent
15
+ import { Agent } from 'connectonion';
16
+
17
+ function calculateTip(bill: number, percentage: number): number {
18
+ return bill * (percentage / 100);
19
+ }
20
+
21
+ const agent = new Agent({
22
+ name: 'assistant',
23
+ tools: [calculateTip] // Your function is now an AI tool!
24
+ });
25
+
26
+ const response = await agent.input('What\'s a 20% tip on $85?');
27
+ // "A 20% tip on $85 would be $17.00"
28
+ ```
29
+
30
+ **That's it.** No schemas. No configurations. No boilerplate.
31
+
32
+ ## 🆕 Python-Parity Highlights
33
+
34
+ - Default LLM: Anthropic Claude Sonnet 3.5 (`claude-3-5-sonnet-20241022`)
35
+ - LLM factory: routes `claude-*`, `gpt-*`/`o*`, `gemini-*`, and `co/*` (OpenOnion)
36
+ - Structured output: `llm.structuredComplete(messages, schema)` returns validated JSON
37
+ - Multi‑turn: agent now keeps conversation state until `resetConversation()`
38
+ - Console logging: progress printed and logged to `./.co/logs/{name}.log` by default
39
+ - Env override: set `CONNECTONION_LOG` to choose a custom log file
40
+
41
+ ## 🎯 Why CO?
42
+
43
+ ### 🧠 **Smart by Default**
44
+ - Agents automatically understand when and how to use tools
45
+ - Built-in conversation memory and context management
46
+ - Parallel tool execution for maximum efficiency
47
+
48
+ ### 🛠️ **Any Function is a Tool**
49
+ ```typescript
50
+ // These all become tools automatically
51
+ function sendEmail(to: string, subject: string) { }
52
+ async function fetchWeather(city: string) { }
53
+ const calculate = (x: number, y: number) => x + y;
54
+
55
+ // Even class methods!
56
+ class Database {
57
+ query(sql: string) { }
58
+ insert(table: string, data: any) { }
59
+ }
60
+ ```
61
+
62
+ ### 📝 **TypeScript Superpowers**
63
+ - Full type safety and IntelliSense support
64
+ - Compile-time parameter validation
65
+ - Auto-completion for all APIs
66
+ - JSDoc comments become tool descriptions
67
+
68
+ ### 💾 **Session & Trace**
69
+ Agents keep an in-memory session (messages + tool execution trace). Inspect it with `agent.getSession()` and reset with `agent.resetConversation()`.
70
+
71
+ ## 🚀 Quick Start (60 seconds)
72
+
73
+ ### 1. Install
74
+ ```bash
75
+ npm install connectonion
76
+ # or
77
+ yarn add connectonion
78
+ # or
79
+ pnpm add connectonion
80
+ ```
81
+
82
+ ### 2. Set API Key
83
+ ```bash
84
+ export OPENAI_API_KEY=sk-...
85
+ # or use .env file
86
+
87
+ # Anthropic (default)
88
+ export ANTHROPIC_API_KEY=sk-ant-...
89
+
90
+ # Gemini (optional)
91
+ export GEMINI_API_KEY=sk-gem-... # or GOOGLE_API_KEY
92
+
93
+ # OpenOnion managed keys (optional, for co/* models)
94
+ export OPENONION_API_KEY=oo-...
95
+ export OPENONION_BASE_URL=https://oo.openonion.ai/v1
96
+ # Dev mode: uses http://localhost:8000/v1
97
+ export OPENONION_DEV=1
98
+
99
+ # Console log override (otherwise ./.co/logs/{name}.log)
100
+ export CONNECTONION_LOG=./my-agent.log
101
+ ```
102
+
103
+ ### 3. Create Your First Agent
104
+ ```typescript
105
+ import { Agent } from 'connectonion';
106
+
107
+ // Define what your agent can do
108
+ function searchWeb(query: string): string {
109
+ // Your search logic here
110
+ return `Results for ${query}...`;
111
+ }
112
+
113
+ function sendMessage(to: string, message: string): string {
114
+ // Your messaging logic here
115
+ return `Message sent to ${to}`;
116
+ }
117
+
118
+ // Create the agent
119
+ const agent = new Agent({
120
+ name: 'personal-assistant',
121
+ tools: [searchWeb, sendMessage],
122
+ systemPrompt: 'You are a helpful personal assistant.'
123
+ });
124
+
125
+ // Use it!
126
+ const response = await agent.input(
127
+ 'Search for TypeScript tutorials and send the link to John'
128
+ );
129
+ ```
130
+
131
+ ## 🎨 Real-World Examples
132
+
133
+ ### Example 1: Customer Service Bot
134
+ ```typescript
135
+ class CustomerService {
136
+ // Each method becomes a tool automatically
137
+ async lookupOrder(orderId: string): Promise<Order> {
138
+ return await db.orders.findOne({ id: orderId });
139
+ }
140
+
141
+ async processRefund(orderId: string, reason: string): Promise<RefundResult> {
142
+ const order = await this.lookupOrder(orderId);
143
+ return await payments.refund(order, reason);
144
+ }
145
+
146
+ async sendEmail(to: string, subject: string, body: string): Promise<void> {
147
+ await emailService.send({ to, subject, body });
148
+ }
149
+ }
150
+
151
+ // Create an agent with all methods as tools
152
+ const agent = new Agent({
153
+ name: 'customer-service',
154
+ tools: [new CustomerService()], // All methods become tools!
155
+ systemPrompt: 'You are a helpful customer service representative.'
156
+ });
157
+
158
+ // Handle customer requests naturally
159
+ const response = await agent.input(
160
+ 'Order #12345 arrived damaged, I want a refund'
161
+ );
162
+ // Agent will: lookup order → process refund → send confirmation email
163
+ ```
164
+
165
+ ### Example 2: Data Analysis Agent
166
+ ```typescript
167
+ import { Agent } from 'connectonion';
168
+ import * as fs from 'fs';
169
+ import * as csv from 'csv-parse';
170
+
171
+ // Tools for data analysis
172
+ function readCSV(filepath: string): any[] {
173
+ const data = fs.readFileSync(filepath, 'utf-8');
174
+ return csv.parse(data, { columns: true });
175
+ }
176
+
177
+ function analyzeData(data: any[], column: string): Statistics {
178
+ // Statistical analysis logic
179
+ return {
180
+ mean: calculateMean(data, column),
181
+ median: calculateMedian(data, column),
182
+ stdDev: calculateStdDev(data, column)
183
+ };
184
+ }
185
+
186
+ function createChart(data: any[], type: string): string {
187
+ // Chart generation logic
188
+ return `chart_${Date.now()}.png`;
189
+ }
190
+
191
+ // Create the analyst
192
+ const analyst = new Agent({
193
+ name: 'data-analyst',
194
+ tools: [readCSV, analyzeData, createChart],
195
+ model: 'gpt-4', // Use GPT-4 for complex analysis
196
+ systemPrompt: 'You are an expert data analyst. Provide insights and visualizations.'
197
+ });
198
+
199
+ // Analyze data with natural language
200
+ const report = await analyst.input(
201
+ 'Analyze sales.csv, focus on Q4 performance, and create a bar chart'
202
+ );
203
+ ```
204
+
205
+ ### Example 3: DevOps Automation
206
+ ```typescript
207
+ class DevOpsTools {
208
+ async deployToProduction(service: string, version: string) {
209
+ // Kubernetes deployment logic
210
+ return `Deployed ${service}:${version} to production`;
211
+ }
212
+
213
+ async checkSystemHealth(service: string) {
214
+ // Health check logic
215
+ return { status: 'healthy', uptime: '99.9%' };
216
+ }
217
+
218
+ async rollback(service: string) {
219
+ // Rollback logic
220
+ return `Rolled back ${service} to previous version`;
221
+ }
222
+
223
+ async queryLogs(service: string, timeRange: string, filter?: string) {
224
+ // Log querying logic
225
+ return [`[ERROR] Connection timeout`, `[WARN] High memory usage`];
226
+ }
227
+ }
228
+
229
+ const devops = new Agent({
230
+ name: 'devops-assistant',
231
+ tools: [new DevOpsTools()],
232
+ maxIterations: 20, // Complex operations might need more iterations
233
+ systemPrompt: 'You are a DevOps expert. Be cautious with production changes.'
234
+ });
235
+
236
+ // Natural language DevOps
237
+ await devops.input(
238
+ 'Check if api-service is healthy, if not check logs and consider rollback'
239
+ );
240
+ ```
241
+
242
+ ## 🔧 Advanced Features
243
+
244
+ ### Dynamic Tool Management
245
+ ```typescript
246
+ // Add tools at runtime
247
+ agent.addTool(newFunction);
248
+
249
+ // Remove tools
250
+ agent.removeTool('oldToolName');
251
+
252
+ // List available tools
253
+ const tools = agent.getTools();
254
+ console.log(tools.map(t => `${t.name}: ${t.description}`));
255
+ ```
256
+
257
+ ### Custom LLM Providers
258
+ ```typescript
259
+ import { LLM, Agent } from 'connectonion';
260
+
261
+ class CustomLLM implements LLM {
262
+ async complete(messages, tools) {
263
+ // Your LLM implementation
264
+ return { content: '...', toolCalls: [], rawResponse: {} };
265
+ }
266
+ }
267
+
268
+ const agent = new Agent({
269
+ name: 'custom-agent',
270
+ llm: new CustomLLM()
271
+ });
272
+ ```
273
+
274
+ ### Session & Trace
275
+ ```typescript
276
+ const { messages, trace } = agent.getSession();
277
+ console.log(messages.length, trace.length);
278
+ agent.clearHistory(); // clear in-memory trace
279
+ ```
280
+
281
+ ### Override Iterations for Complex Tasks
282
+ ```typescript
283
+ // Simple task - use default
284
+ await agent.input('What is 2+2?');
285
+
286
+ // Complex multi-step task - allow more iterations
287
+ await agent.input(
288
+ 'Analyze all CSV files, generate reports, and email summaries',
289
+ 30 // Allow up to 30 iterations
290
+ );
291
+ ```
292
+
293
+ ## 📚 Documentation
294
+
295
+ - **[Getting Started Guide](docs/getting-started.md)** - Complete setup walkthrough
296
+ - **[API Reference](docs/api.md)** - Full API documentation
297
+ - **[Examples](docs/examples.md)** - More real-world examples
298
+ - **[Tool System](docs/tools.md)** - Deep dive into tools
299
+ - **[Troubleshooting](docs/troubleshooting.md)** - Common issues & solutions
300
+
301
+ ## 🏗️ Project Structure
302
+
303
+ ```
304
+ your-project/
305
+ ├── src/
306
+ │ ├── agents/ # Your agent definitions
307
+ │ ├── tools/ # Custom tool implementations
308
+ │ └── index.ts # Main entry point
309
+ ├── .env # API keys (never commit!)
310
+ ├── package.json
311
+ └── tsconfig.json
312
+ ```
313
+
314
+ ## 🤝 Contributing
315
+
316
+ We love contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
317
+
318
+ ### Development Setup
319
+ ```bash
320
+ # Clone the repo
321
+ git clone https://github.com/connectonion/connectonion-ts
322
+ cd connectonion-ts
323
+
324
+ # Install dependencies
325
+ npm install
326
+
327
+ # Run tests
328
+ npm test
329
+
330
+ # Build
331
+ npm run build
332
+ ```
333
+
334
+ ## 📄 License
335
+
336
+ MIT © [CO Team](https://github.com/connectonion)
337
+
338
+ ## 🔗 Links
339
+
340
+ - **[Python Version](https://github.com/connectonion/connectonion)** - Original Python SDK
341
+ - **[Discord Community](https://discord.gg/connectonion)** - Get help & share ideas
342
+ - **[Blog](https://connectonion.com/blog)** - Tutorials and updates
343
+
344
+ ## 🌟 Why TypeScript?
345
+
346
+ While our Python SDK is great, TypeScript offers unique advantages:
347
+
348
+ - **Type Safety**: Catch errors at compile time
349
+ - **IDE Support**: Unmatched IntelliSense and auto-completion
350
+ - **Modern Async**: Native async/await and Promise handling
351
+ - **NPM Ecosystem**: Access to millions of packages
352
+ - **Browser Ready**: Build agents that run in browsers (coming soon!)
353
+
354
+ ---
355
+
356
+ <p align="center">
357
+ Built with ❤️ by developers, for developers
358
+ </p>
359
+
360
+ <p align="center">
361
+ <a href="https://github.com/connectonion/connectonion-ts">⭐ Star us on GitHub</a>
362
+ </p>
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Connect to remote agents via the relay network.
3
+ *
4
+ * Mirrors Python SDK connect(): returns a RemoteAgent proxy with input().
5
+ */
6
+ type WebSocketLike = {
7
+ onopen: ((ev?: any) => any) | null;
8
+ onmessage: ((ev: {
9
+ data: any;
10
+ }) => any) | null;
11
+ onerror: ((ev: any) => any) | null;
12
+ onclose: ((ev: any) => any) | null;
13
+ send(data: any): void;
14
+ close(): void;
15
+ };
16
+ type WebSocketCtor = new (url: string) => WebSocketLike;
17
+ /** Proxy to a remote agent reachable via the relay */
18
+ export declare class RemoteAgent {
19
+ private address;
20
+ private relayUrl;
21
+ private WS;
22
+ constructor(address: string, relayUrl: string, wsCtor?: WebSocketCtor);
23
+ /** Send task to remote agent and await result */
24
+ input(prompt: string, timeoutMs?: number): Promise<string>;
25
+ toString(): string;
26
+ }
27
+ /**
28
+ * Connect to a remote agent.
29
+ *
30
+ * @param address Agent public key (0x...)
31
+ * @param relayUrl Relay announce URL (default production)
32
+ */
33
+ export declare function connect(address: string, relayUrl?: string, wsCtor?: WebSocketCtor): RemoteAgent;
34
+ export {};
35
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,KAAK,aAAa,GAAG;IACnB,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;QAAE,IAAI,EAAE,GAAG,CAAA;KAAE,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC;IAC/C,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC;IACnC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACtB,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAEF,KAAK,aAAa,GAAG,KAAK,GAAG,EAAE,MAAM,KAAK,aAAa,CAAC;AAmBxD,sDAAsD;AACtD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,EAAE,CAAgB;gBAEd,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa;IAMrE,iDAAiD;IAC3C,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAiF/D,QAAQ;CAIT;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAAqE,EAC/E,MAAM,CAAC,EAAE,aAAa,GACrB,WAAW,CAEb"}
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ /**
3
+ * Connect to remote agents via the relay network.
4
+ *
5
+ * Mirrors Python SDK connect(): returns a RemoteAgent proxy with input().
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.RemoteAgent = void 0;
12
+ exports.connect = connect;
13
+ const crypto_1 = __importDefault(require("crypto"));
14
+ function defaultWebSocketCtor() {
15
+ // Prefer global WebSocket (browser), else require('ws') in Node
16
+ const g = globalThis;
17
+ if (typeof g.WebSocket === 'function') {
18
+ return g.WebSocket;
19
+ }
20
+ try {
21
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
22
+ const WS = require('ws');
23
+ return WS;
24
+ }
25
+ catch {
26
+ throw new Error("No WebSocket implementation found. Install 'ws' (npm i ws) or provide a custom WebSocket factory.");
27
+ }
28
+ }
29
+ /** Proxy to a remote agent reachable via the relay */
30
+ class RemoteAgent {
31
+ constructor(address, relayUrl, wsCtor) {
32
+ this.address = address;
33
+ this.relayUrl = relayUrl;
34
+ this.WS = wsCtor || defaultWebSocketCtor();
35
+ }
36
+ /** Send task to remote agent and await result */
37
+ async input(prompt, timeoutMs = 30000) {
38
+ const inputId = crypto_1.default.randomUUID();
39
+ const relayInputUrl = this.relayUrl.replace('/ws/announce', '/ws/input');
40
+ const ws = new this.WS(relayInputUrl);
41
+ return await new Promise((resolve, reject) => {
42
+ let settled = false;
43
+ const timer = setTimeout(() => {
44
+ if (!settled) {
45
+ settled = true;
46
+ try {
47
+ ws.close();
48
+ }
49
+ catch { }
50
+ reject(new Error('Connection timed out'));
51
+ }
52
+ }, timeoutMs);
53
+ ws.onopen = () => {
54
+ // Send INPUT message
55
+ const msg = {
56
+ type: 'INPUT',
57
+ input_id: inputId,
58
+ to: this.address,
59
+ prompt,
60
+ };
61
+ try {
62
+ ws.send(JSON.stringify(msg));
63
+ }
64
+ catch (e) {
65
+ clearTimeout(timer);
66
+ if (!settled) {
67
+ settled = true;
68
+ try {
69
+ ws.close();
70
+ }
71
+ catch { }
72
+ reject(e);
73
+ }
74
+ }
75
+ };
76
+ ws.onmessage = (evt) => {
77
+ if (settled)
78
+ return;
79
+ try {
80
+ const raw = typeof evt.data === 'string' ? evt.data : evt.data?.toString?.() ?? '';
81
+ const data = JSON.parse(raw);
82
+ if (data?.type === 'OUTPUT' && data?.input_id === inputId) {
83
+ settled = true;
84
+ clearTimeout(timer);
85
+ try {
86
+ ws.close();
87
+ }
88
+ catch { }
89
+ resolve(data?.result ?? '');
90
+ }
91
+ else if (data?.type === 'ERROR') {
92
+ settled = true;
93
+ clearTimeout(timer);
94
+ try {
95
+ ws.close();
96
+ }
97
+ catch { }
98
+ reject(new Error(String(data?.error || 'Agent error')));
99
+ }
100
+ else {
101
+ // Ignore unrelated message; keep waiting
102
+ }
103
+ }
104
+ catch (e) {
105
+ settled = true;
106
+ clearTimeout(timer);
107
+ try {
108
+ ws.close();
109
+ }
110
+ catch { }
111
+ reject(e);
112
+ }
113
+ };
114
+ ws.onerror = (err) => {
115
+ if (settled)
116
+ return;
117
+ settled = true;
118
+ clearTimeout(timer);
119
+ try {
120
+ ws.close();
121
+ }
122
+ catch { }
123
+ reject(new Error(`WebSocket error: ${String(err?.message || err)}`));
124
+ };
125
+ ws.onclose = () => {
126
+ // If closed without settling, treat as error
127
+ if (!settled) {
128
+ settled = true;
129
+ clearTimeout(timer);
130
+ reject(new Error('Connection closed before response'));
131
+ }
132
+ };
133
+ });
134
+ }
135
+ toString() {
136
+ const short = this.address.length > 12 ? this.address.slice(0, 12) + '...' : this.address;
137
+ return `RemoteAgent(${short})`;
138
+ }
139
+ }
140
+ exports.RemoteAgent = RemoteAgent;
141
+ /**
142
+ * Connect to a remote agent.
143
+ *
144
+ * @param address Agent public key (0x...)
145
+ * @param relayUrl Relay announce URL (default production)
146
+ */
147
+ function connect(address, relayUrl = process.env.RELAY_URL || 'wss://oo.openonion.ai/ws/announce', wsCtor) {
148
+ return new RemoteAgent(address, relayUrl, wsCtor);
149
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @purpose Dual-output logging system (terminal + optional file) that mirrors Python SDK UX with colored terminal output and @xray tool tracing
3
+ * @llm-note
4
+ * Dependencies: imports from [node:fs, node:path] | imported by [src/core/agent.ts, src/tools/tool-executor.ts] | tested by agent tests
5
+ * Data flow: receives log messages/xray traces → formats with timestamps/colors → writes to stderr + optional file (.co/logs/{name}.log)
6
+ * State/Effects: writes to stderr via console.error | appends to logFile if configured | creates log directories with fs.mkdirSync
7
+ * Integration: exposes print(message), printXray(toolName, args, result, timing, context) | used by Agent for all output | ANSI color support via isTTY detection
8
+ */
9
+ export declare class Console {
10
+ private logPath?;
11
+ private colorEnabled;
12
+ constructor(logFile?: string);
13
+ private initLogFile;
14
+ print(message: string): void;
15
+ printXray(toolName: string, toolArgs: Record<string, any>, result: any, timingMs: number, context?: {
16
+ agent?: string;
17
+ iteration?: number;
18
+ userPrompt?: string;
19
+ }): void;
20
+ private toPlain;
21
+ private stylize;
22
+ private code;
23
+ private green;
24
+ private red;
25
+ private yellow;
26
+ private cyan;
27
+ private dim;
28
+ private bold;
29
+ }
30
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,qBAAa,OAAO;IAClB,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,YAAY,CAAU;gBAElB,OAAO,CAAC,EAAE,MAAM;IAM5B,OAAO,CAAC,WAAW;IASnB,KAAK,CAAC,OAAO,EAAE,MAAM;IAUrB,SAAS,CACP,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7B,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAgBvE,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,IAAI;CACb"}