beam-protocol-sdk 0.2.2 → 0.3.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.
@@ -0,0 +1,213 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ MAX_FRAME_SIZE,
4
+ REPLAY_WINDOW_MS,
5
+ canonicalizeFrame,
6
+ createIntentFrame,
7
+ createResultFrame,
8
+ signFrame,
9
+ validateIntentFrame,
10
+ validateResultFrame,
11
+ } from '../src/frames.js'
12
+ import { BeamIdentity } from '../src/identity.js'
13
+ import type { IntentFrame } from '../src/types.js'
14
+
15
+ describe('frames', () => {
16
+ const sender = BeamIdentity.generate({ agentName: 'alice', orgName: 'acme' })
17
+ const receiver = BeamIdentity.generate({ agentName: 'bob', orgName: 'acme' })
18
+
19
+ it('createIntentFrame() signs a valid intent frame', () => {
20
+ const frame = createIntentFrame(
21
+ {
22
+ intent: 'task.delegate',
23
+ from: sender.beamId,
24
+ to: receiver.beamId,
25
+ payload: { task: 'Review proposal', priority: 'high' },
26
+ },
27
+ sender,
28
+ )
29
+
30
+ expect(frame.signature).toBeTruthy()
31
+ expect(frame.v).toBe('1')
32
+ expect(frame.nonce).toMatch(/^[0-9a-f-]{36}$/)
33
+ expect(validateIntentFrame(frame, sender.publicKeyBase64)).toEqual({ valid: true })
34
+ })
35
+
36
+ it('signFrame() produces signatures that fail after tampering', () => {
37
+ const frame: IntentFrame = {
38
+ v: '1',
39
+ intent: 'agent.ping',
40
+ from: sender.beamId,
41
+ to: receiver.beamId,
42
+ payload: { message: 'hello' },
43
+ nonce: BeamIdentity.generateNonce(),
44
+ timestamp: new Date().toISOString(),
45
+ }
46
+
47
+ signFrame(frame, sender.export().privateKeyBase64)
48
+ expect(validateIntentFrame(frame, sender.publicKeyBase64)).toEqual({ valid: true })
49
+
50
+ frame.payload.message = 'tampered'
51
+ expect(validateIntentFrame(frame, sender.publicKeyBase64)).toEqual({
52
+ valid: false,
53
+ error: 'Signature verification failed',
54
+ })
55
+ })
56
+
57
+ it('createResultFrame() signs a valid result frame', () => {
58
+ const frame = createResultFrame(
59
+ {
60
+ nonce: BeamIdentity.generateNonce(),
61
+ success: true,
62
+ payload: { accepted: true, estimatedCompletion: 'soon' },
63
+ latency: 25,
64
+ },
65
+ receiver,
66
+ )
67
+
68
+ expect(frame.signature).toBeTruthy()
69
+ expect(validateResultFrame(frame, receiver.publicKeyBase64)).toEqual({ valid: true })
70
+ })
71
+
72
+ it('validateResultFrame() rejects tampered result frames', () => {
73
+ const frame = createResultFrame(
74
+ {
75
+ nonce: BeamIdentity.generateNonce(),
76
+ success: false,
77
+ error: 'Denied',
78
+ errorCode: 'ACCESS_DENIED',
79
+ },
80
+ receiver,
81
+ )
82
+
83
+ const tampered = { ...frame, error: 'Allowed now' }
84
+ expect(validateResultFrame(tampered, receiver.publicKeyBase64)).toEqual({
85
+ valid: false,
86
+ error: 'Signature verification failed',
87
+ })
88
+ })
89
+
90
+ it('validateIntentFrame() rejects missing or malformed fields', () => {
91
+ const validFrame = createIntentFrame(
92
+ {
93
+ intent: 'agent.introduce',
94
+ from: sender.beamId,
95
+ to: receiver.beamId,
96
+ payload: { question: 'Who are you?' },
97
+ },
98
+ sender,
99
+ )
100
+
101
+ const cases: Array<[string, unknown, string]> = [
102
+ ['non-object frame', null, 'Frame must be an object'],
103
+ ['wrong protocol version', { ...validFrame, v: '2' }, 'Invalid protocol version'],
104
+ ['missing intent', { ...validFrame, intent: '' }, 'Missing or empty intent'],
105
+ ['invalid sender id', { ...validFrame, from: 'Alice@acme.beam.directory' }, 'Invalid from Beam ID'],
106
+ ['invalid receiver id', { ...validFrame, to: 'bob@example.com' }, 'Invalid to Beam ID'],
107
+ ['missing nonce', { ...validFrame, nonce: '' }, 'Missing nonce'],
108
+ ['missing timestamp', { ...validFrame, timestamp: 123 }, 'Missing timestamp'],
109
+ ['non-object payload', { ...validFrame, payload: [] }, 'Payload must be an object'],
110
+ ['missing signature', { ...validFrame, signature: undefined }, 'Missing signature'],
111
+ ]
112
+
113
+ for (const [, frame, error] of cases) {
114
+ expect(validateIntentFrame(frame, sender.publicKeyBase64)).toEqual({ valid: false, error })
115
+ }
116
+ })
117
+
118
+ it('validateResultFrame() rejects missing required fields', () => {
119
+ const frame = createResultFrame(
120
+ {
121
+ nonce: BeamIdentity.generateNonce(),
122
+ success: true,
123
+ },
124
+ receiver,
125
+ )
126
+
127
+ expect(validateResultFrame({ ...frame, success: undefined }, receiver.publicKeyBase64)).toEqual({
128
+ valid: false,
129
+ error: 'Missing success boolean',
130
+ })
131
+ expect(validateResultFrame({ ...frame, nonce: '' }, receiver.publicKeyBase64)).toEqual({
132
+ valid: false,
133
+ error: 'Missing nonce',
134
+ })
135
+ expect(validateResultFrame({ ...frame, signature: undefined }, receiver.publicKeyBase64)).toEqual({
136
+ valid: false,
137
+ error: 'Missing signature',
138
+ })
139
+ })
140
+
141
+ it('enforces MAX_FRAME_SIZE for intent frames', () => {
142
+ const oversizedFrame = createIntentFrame(
143
+ {
144
+ intent: 'system.broadcast',
145
+ from: sender.beamId,
146
+ to: receiver.beamId,
147
+ payload: { message: 'x'.repeat(MAX_FRAME_SIZE) },
148
+ },
149
+ sender,
150
+ )
151
+
152
+ const result = validateIntentFrame(oversizedFrame, sender.publicKeyBase64)
153
+ expect(result.valid).toBe(false)
154
+ expect(result.error).toContain(`exceeds limit of ${MAX_FRAME_SIZE} bytes`)
155
+ })
156
+
157
+ it('enforces REPLAY_WINDOW_MS for old and future intent frames', () => {
158
+ const oldTimestamp = new Date(Date.now() - REPLAY_WINDOW_MS - 1_000).toISOString()
159
+ const futureTimestamp = new Date(Date.now() + REPLAY_WINDOW_MS + 1_000).toISOString()
160
+
161
+ const oldFrame = signFrame(
162
+ {
163
+ v: '1',
164
+ intent: 'agent.ping',
165
+ from: sender.beamId,
166
+ to: receiver.beamId,
167
+ payload: { message: 'old' },
168
+ nonce: BeamIdentity.generateNonce(),
169
+ timestamp: oldTimestamp,
170
+ },
171
+ sender.export().privateKeyBase64,
172
+ )
173
+ const futureFrame = signFrame(
174
+ {
175
+ v: '1',
176
+ intent: 'agent.ping',
177
+ from: sender.beamId,
178
+ to: receiver.beamId,
179
+ payload: { message: 'future' },
180
+ nonce: BeamIdentity.generateNonce(),
181
+ timestamp: futureTimestamp,
182
+ },
183
+ sender.export().privateKeyBase64,
184
+ )
185
+
186
+ expect(validateIntentFrame(oldFrame, sender.publicKeyBase64)).toEqual({
187
+ valid: false,
188
+ error: 'Frame timestamp outside replay window (±5 minutes)',
189
+ })
190
+ expect(validateIntentFrame(futureFrame, sender.publicKeyBase64)).toEqual({
191
+ valid: false,
192
+ error: 'Frame timestamp outside replay window (±5 minutes)',
193
+ })
194
+ })
195
+
196
+ it('canonicalizeFrame() is stable regardless of key order', () => {
197
+ const left = {
198
+ payload: { z: 1, a: { d: 4, b: 2 } },
199
+ nonce: '123',
200
+ success: true,
201
+ v: '1',
202
+ }
203
+ const right = {
204
+ v: '1',
205
+ success: true,
206
+ nonce: '123',
207
+ payload: { a: { b: 2, d: 4 }, z: 1 },
208
+ }
209
+
210
+ expect(canonicalizeFrame(left)).toBe(canonicalizeFrame(right))
211
+ expect(canonicalizeFrame(left)).toBe('{"nonce":"123","payload":{"a":{"b":2,"d":4},"z":1},"success":true,"v":"1"}')
212
+ })
213
+ })
@@ -0,0 +1,130 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { BeamIdentity } from '../src/identity.js'
3
+
4
+ describe('BeamIdentity', () => {
5
+ it('generate() creates valid beamId format', () => {
6
+ const identity = BeamIdentity.generate({ agentName: 'myagent', orgName: 'myorg' })
7
+ expect(identity.beamId).toBe('myagent@myorg.beam.directory')
8
+ expect(identity.publicKeyBase64).toBeTruthy()
9
+ expect(typeof identity.publicKeyBase64).toBe('string')
10
+ })
11
+
12
+ it('sign() + verify() round-trip works', () => {
13
+ const identity = BeamIdentity.generate({ agentName: 'alice', orgName: 'acme' })
14
+ const data = 'hello beam protocol'
15
+ const signature = identity.sign(data)
16
+ expect(typeof signature).toBe('string')
17
+ expect(signature.length).toBeGreaterThan(0)
18
+ const valid = BeamIdentity.verify(data, signature, identity.publicKeyBase64)
19
+ expect(valid).toBe(true)
20
+ })
21
+
22
+ it('verify() returns false for tampered data', () => {
23
+ const identity = BeamIdentity.generate({ agentName: 'alice', orgName: 'acme' })
24
+ const data = 'original message'
25
+ const signature = identity.sign(data)
26
+ const valid = BeamIdentity.verify('tampered message', signature, identity.publicKeyBase64)
27
+ expect(valid).toBe(false)
28
+ })
29
+
30
+ it('verify() returns false for tampered signature', () => {
31
+ const identity = BeamIdentity.generate({ agentName: 'alice', orgName: 'acme' })
32
+ const data = 'hello beam protocol'
33
+ const signature = identity.sign(data)
34
+ // Flip a character in the signature
35
+ const tampered = signature.slice(0, -4) + 'AAAA'
36
+ const valid = BeamIdentity.verify(data, tampered, identity.publicKeyBase64)
37
+ expect(valid).toBe(false)
38
+ })
39
+
40
+ it('verify() returns false for wrong public key', () => {
41
+ const identity1 = BeamIdentity.generate({ agentName: 'alice', orgName: 'acme' })
42
+ const identity2 = BeamIdentity.generate({ agentName: 'bob', orgName: 'acme' })
43
+ const data = 'hello beam protocol'
44
+ const signature = identity1.sign(data)
45
+ // Verify with wrong key
46
+ const valid = BeamIdentity.verify(data, signature, identity2.publicKeyBase64)
47
+ expect(valid).toBe(false)
48
+ })
49
+
50
+ it('export() + fromData() round-trip works', () => {
51
+ const original = BeamIdentity.generate({ agentName: 'testbot', orgName: 'testorg' })
52
+ const data = original.export()
53
+
54
+ expect(data.beamId).toBe('testbot@testorg.beam.directory')
55
+ expect(typeof data.publicKeyBase64).toBe('string')
56
+ expect(typeof data.privateKeyBase64).toBe('string')
57
+
58
+ const restored = BeamIdentity.fromData(data)
59
+ expect(restored.beamId).toBe(original.beamId)
60
+ expect(restored.publicKeyBase64).toBe(original.publicKeyBase64)
61
+
62
+ // Signing with restored key should verify against original public key
63
+ const message = 'test round trip'
64
+ const sig = restored.sign(message)
65
+ expect(BeamIdentity.verify(message, sig, original.publicKeyBase64)).toBe(true)
66
+ })
67
+
68
+ it('export() produces stable base64 keys', () => {
69
+ const identity = BeamIdentity.generate({ agentName: 'stable', orgName: 'org' })
70
+ const export1 = identity.export()
71
+ const export2 = identity.export()
72
+ expect(export1.publicKeyBase64).toBe(export2.publicKeyBase64)
73
+ expect(export1.privateKeyBase64).toBe(export2.privateKeyBase64)
74
+ })
75
+
76
+ describe('parseBeamId()', () => {
77
+ it('returns correct agent/org for valid beam ID', () => {
78
+ const result = BeamIdentity.parseBeamId('myagent@myorg.beam.directory')
79
+ expect(result).not.toBeNull()
80
+ expect(result!.agent).toBe('myagent')
81
+ expect(result!.org).toBe('myorg')
82
+ })
83
+
84
+ it('returns correct result for hyphenated names', () => {
85
+ const result = BeamIdentity.parseBeamId('my-agent@my-org.beam.directory')
86
+ expect(result).not.toBeNull()
87
+ expect(result!.agent).toBe('my-agent')
88
+ expect(result!.org).toBe('my-org')
89
+ })
90
+
91
+ it('returns correct result for underscore names', () => {
92
+ const result = BeamIdentity.parseBeamId('my_agent@my_org.beam.directory')
93
+ expect(result).not.toBeNull()
94
+ expect(result!.agent).toBe('my_agent')
95
+ expect(result!.org).toBe('my_org')
96
+ })
97
+
98
+ it('returns null for invalid format - missing @', () => {
99
+ expect(BeamIdentity.parseBeamId('myagentmyorg.beam.directory')).toBeNull()
100
+ })
101
+
102
+ it('returns null for invalid format - wrong suffix', () => {
103
+ expect(BeamIdentity.parseBeamId('myagent@myorg.beam.com')).toBeNull()
104
+ })
105
+
106
+ it('returns null for invalid format - uppercase letters', () => {
107
+ expect(BeamIdentity.parseBeamId('MyAgent@myorg.beam.directory')).toBeNull()
108
+ })
109
+
110
+ it('returns null for empty string', () => {
111
+ expect(BeamIdentity.parseBeamId('')).toBeNull()
112
+ })
113
+
114
+ it('returns null for partial match', () => {
115
+ expect(BeamIdentity.parseBeamId('agent@org.beam.directory.extra')).toBeNull()
116
+ })
117
+ })
118
+
119
+ it('generateNonce() returns a UUID v4 string', () => {
120
+ const nonce = BeamIdentity.generateNonce()
121
+ expect(typeof nonce).toBe('string')
122
+ // UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
123
+ expect(nonce).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/)
124
+ })
125
+
126
+ it('generateNonce() returns unique values', () => {
127
+ const nonces = new Set(Array.from({ length: 100 }, () => BeamIdentity.generateNonce()))
128
+ expect(nonces.size).toBe(100)
129
+ })
130
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "declaration": true,
11
+ "declarationMap": true,
12
+ "sourceMap": true,
13
+ "esModuleInterop": true,
14
+ "skipLibCheck": true,
15
+ "forceConsistentCasingInFileNames": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist", "tests"]
19
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config'
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: 'node',
6
+ globals: true
7
+ }
8
+ })
package/README.md DELETED
@@ -1,177 +0,0 @@
1
- # beam-protocol-sdk · TypeScript SDK
2
-
3
- > **SMTP for AI Agents** — TypeScript SDK for agent identity, registration, discovery and intent routing via the Beam Protocol.
4
-
5
- [![npm version](https://img.shields.io/npm/v/beam-protocol-sdk)](https://www.npmjs.com/package/beam-protocol-sdk)
6
- [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-orange.svg)](https://www.apache.org/licenses/LICENSE-2.0)
7
- [![Node ≥ 18](https://img.shields.io/badge/node-≥18-blue.svg)](https://nodejs.org)
8
-
9
- ---
10
-
11
- ## Installation
12
-
13
- ```bash
14
- npm install beam-protocol-sdk
15
- ```
16
-
17
- ## Quick Start
18
-
19
- ```typescript
20
- import { BeamIdentity, BeamClient } from 'beam-protocol-sdk'
21
-
22
- // 1. Generate a Beam identity (Ed25519 keypair)
23
- const identity = BeamIdentity.generate({
24
- agentName: 'myagent',
25
- orgName: 'myorg',
26
- })
27
- console.log(identity.beamId) // → myagent@myorg.beam.directory
28
-
29
- // 2. Connect to the directory
30
- const client = new BeamClient({
31
- identity: identity.export(),
32
- directoryUrl: 'wss://dir.beam.directory',
33
- })
34
- await client.connect()
35
-
36
- // 3. Send a structured intent
37
- const result = await client.send(
38
- 'other@org.beam.directory',
39
- 'payment.status_check',
40
- { invoiceId: 'INV-2847' }
41
- )
42
- console.log(result.payload)
43
- // → { status: 'paid', amount: 2185.00, date: '2026-03-05' }
44
-
45
- // 4. Or just talk in natural language
46
- const reply = await client.talk(
47
- 'clara@coppen.beam.directory',
48
- 'Was weißt du über Christopher Schnorrenberg?'
49
- )
50
- console.log(reply) // Clara uses her real tools to answer
51
- ```
52
-
53
- ## Concepts
54
-
55
- ### Beam ID
56
-
57
- Every agent gets a globally unique **Beam ID**:
58
-
59
- ```
60
- agent@org.beam.directory
61
- ```
62
-
63
- Like email, but for AI agents. Backed by an Ed25519 keypair for cryptographic verification.
64
-
65
- ### Intent Frames
66
-
67
- Structured JSON messages with built-in security:
68
-
69
- ```typescript
70
- import { createIntentFrame, signFrame } from 'beam-protocol-sdk'
71
-
72
- const frame = createIntentFrame({
73
- from: 'jarvis@coppen.beam.directory',
74
- to: 'fischer@coppen.beam.directory',
75
- intent: 'escalation.request',
76
- payload: { caseId: 'CASE-0042', priority: 'high' },
77
- })
78
-
79
- const signed = signFrame(frame, identity.privateKey)
80
- // → Ed25519 signature, nonce, replay protection included
81
- ```
82
-
83
- ### Directory
84
-
85
- Discover agents by org, capability, or connection status:
86
-
87
- ```typescript
88
- import { BeamDirectory } from 'beam-protocol-sdk'
89
-
90
- const directory = new BeamDirectory({
91
- baseUrl: 'https://api.beam.directory',
92
- })
93
-
94
- // Look up a specific agent
95
- const agent = await directory.lookup('clara@coppen.beam.directory')
96
-
97
- // Search by org
98
- const agents = await directory.search({ org: 'coppen', limit: 10 })
99
- ```
100
-
101
- ### Threads
102
-
103
- Multi-turn conversations between agents:
104
-
105
- ```typescript
106
- const thread = client.thread('clara@coppen.beam.directory')
107
-
108
- const r1 = await thread.send('query.customer', { name: 'Chris' })
109
- // Clara responds with customer data
110
-
111
- const r2 = await thread.send('query.deals', { customerId: r1.payload.id })
112
- // Follow-up in the same conversation context
113
- ```
114
-
115
- ## API Reference
116
-
117
- ### `BeamIdentity`
118
-
119
- | Method | Description |
120
- |---|---|
121
- | `BeamIdentity.generate(config)` | Create a new identity with Ed25519 keypair |
122
- | `identity.beamId` | The agent's Beam ID string |
123
- | `identity.export()` | Serialize for storage/transport |
124
- | `BeamIdentity.fromExport(data)` | Restore from serialized data |
125
-
126
- ### `BeamClient`
127
-
128
- | Method | Description |
129
- |---|---|
130
- | `new BeamClient(config)` | Create client with identity + directory URL |
131
- | `client.connect()` | Connect to directory via WebSocket |
132
- | `client.send(to, intent, payload)` | Send a structured intent frame |
133
- | `client.talk(to, message)` | Natural language message (no schema needed) |
134
- | `client.thread(to)` | Start a multi-turn conversation |
135
- | `client.disconnect()` | Graceful disconnect |
136
-
137
- ### `BeamDirectory`
138
-
139
- | Method | Description |
140
- |---|---|
141
- | `directory.lookup(beamId)` | Find a specific agent |
142
- | `directory.search(query)` | Search agents by org/capability |
143
- | `directory.register(name, capabilities)` | Register agent in directory |
144
-
145
- ### Frame Utilities
146
-
147
- | Function | Description |
148
- |---|---|
149
- | `createIntentFrame(opts)` | Build a new intent frame |
150
- | `createResultFrame(opts)` | Build a result response frame |
151
- | `signFrame(frame, privateKey)` | Ed25519-sign a frame |
152
- | `validateIntentFrame(frame)` | Validate structure + replay protection |
153
- | `MAX_FRAME_SIZE` | 1024 bytes max per frame |
154
- | `REPLAY_WINDOW_MS` | 5 minute replay window |
155
-
156
- ## Security
157
-
158
- - **Ed25519 signatures** on every frame
159
- - **Nonce-based replay protection** (5 min window)
160
- - **Deny-by-default ACL** — agents must be explicitly authorized
161
- - **Schema validation** at the directory level
162
- - **Rate limiting** — 60 intents/min per agent
163
-
164
- ## Examples
165
-
166
- See [`examples/`](https://github.com/Beam-directory/beam-protocol/tree/main/examples) in the main repo.
167
-
168
- ## Links
169
-
170
- - 🌐 [beam.directory](https://beam.directory)
171
- - 📄 [RFC 0001](https://github.com/Beam-directory/beam-protocol/blob/main/spec/RFC-0001.md)
172
- - 📖 [Full Documentation](https://github.com/Beam-directory/beam-protocol/tree/main/docs)
173
- - 🐍 [Python SDK](https://pypi.org/project/beam-directory/)
174
-
175
- ## License
176
-
177
- Apache-2.0
package/dist/client.d.ts DELETED
@@ -1,96 +0,0 @@
1
- import { BeamDirectory } from './directory.js';
2
- import type { BeamClientConfig, BeamIdString, IntentFrame, ResultFrame, AgentRecord } from './types.js';
3
- type IntentHandler = (frame: IntentFrame, respond: (options: {
4
- success: boolean;
5
- payload?: Record<string, unknown>;
6
- error?: string;
7
- errorCode?: string;
8
- latency?: number;
9
- }) => ResultFrame) => void | Promise<void>;
10
- export declare class BeamClient {
11
- private readonly _identity;
12
- private readonly _directory;
13
- private readonly _directoryUrl;
14
- private _ws;
15
- private _wsConnected;
16
- private readonly _pendingResults;
17
- private readonly _intentHandlers;
18
- constructor(config: BeamClientConfig);
19
- get beamId(): BeamIdString;
20
- get directory(): BeamDirectory;
21
- register(displayName: string, capabilities: string[]): Promise<AgentRecord>;
22
- connect(): Promise<void>;
23
- private _handleMessage;
24
- send(to: BeamIdString, intent: string, payload?: Record<string, unknown>, timeoutMs?: number): Promise<ResultFrame>;
25
- private _sendViaWebSocket;
26
- private _sendViaHttp;
27
- on(intent: string, handler: IntentHandler): this;
28
- /**
29
- * Send a natural language message to another agent.
30
- * The receiving agent uses its LLM to interpret and respond.
31
- *
32
- * @example
33
- * const reply = await client.talk(
34
- * 'clara@coppen.beam.directory',
35
- * 'Was weißt du über Chris Schnorrenberg?'
36
- * )
37
- * console.log(reply.message) // Natural language response
38
- * console.log(reply.structured) // Optional structured data
39
- */
40
- /**
41
- * Start a multi-turn conversation thread.
42
- * Returns a Thread object with a `say()` method for follow-ups.
43
- */
44
- thread(to: BeamIdString, options?: {
45
- language?: string;
46
- timeoutMs?: number;
47
- }): BeamThread;
48
- talk(to: BeamIdString, message: string, options?: {
49
- context?: Record<string, unknown>;
50
- language?: string;
51
- timeoutMs?: number;
52
- threadId?: string;
53
- }): Promise<{
54
- message: string;
55
- structured?: Record<string, unknown>;
56
- threadId?: string;
57
- raw: ResultFrame;
58
- }>;
59
- /**
60
- * Register a natural language handler.
61
- * Convenience wrapper that listens for conversation.message intents.
62
- *
63
- * @example
64
- * client.onTalk(async (message, from, respond) => {
65
- * const answer = await myLLM.generate(message)
66
- * respond(answer)
67
- * })
68
- */
69
- onTalk(handler: (message: string, from: BeamIdString, respond: (reply: string, structured?: Record<string, unknown>) => void, frame: IntentFrame) => void | Promise<void>): this;
70
- disconnect(): void;
71
- }
72
- /**
73
- * A multi-turn conversation thread between two agents.
74
- *
75
- * @example
76
- * const chat = client.thread('clara@coppen.beam.directory')
77
- * const r1 = await chat.say('Was weißt du über Chris?')
78
- * const r2 = await chat.say('Und seine Pipeline?') // keeps context
79
- */
80
- export declare class BeamThread {
81
- readonly threadId: string;
82
- private readonly _client;
83
- private readonly _to;
84
- private readonly _language?;
85
- private readonly _timeoutMs;
86
- constructor(client: BeamClient, to: BeamIdString, options?: {
87
- language?: string;
88
- timeoutMs?: number;
89
- });
90
- say(message: string, context?: Record<string, unknown>): Promise<{
91
- message: string;
92
- structured?: Record<string, unknown>;
93
- }>;
94
- }
95
- export {};
96
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}