@provenonce/sdk 0.10.1 → 0.11.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.
- package/README.md +38 -38
- package/dist/index.d.mts +35 -23
- package/dist/index.d.ts +35 -23
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,13 +54,13 @@ const agent = new BeatAgent({
|
|
|
54
54
|
|
|
55
55
|
await agent.init(); // Birth in Beat time
|
|
56
56
|
|
|
57
|
-
// Purchase a SIGIL (cryptographic identity)
|
|
58
|
-
const sigil = await agent.purchaseSigil({
|
|
59
|
-
identity_class: 'autonomous',
|
|
60
|
-
principal: 'my-agent',
|
|
61
|
-
tier: 'ind',
|
|
62
|
-
payment_tx: 'solana-tx-signature...',
|
|
63
|
-
});
|
|
57
|
+
// Purchase a SIGIL (cryptographic identity)
|
|
58
|
+
const sigil = await agent.purchaseSigil({
|
|
59
|
+
identity_class: 'autonomous',
|
|
60
|
+
principal: 'my-agent',
|
|
61
|
+
tier: 'ind',
|
|
62
|
+
payment_tx: 'solana-tx-signature...',
|
|
63
|
+
});
|
|
64
64
|
|
|
65
65
|
// Start heartbeating (paid liveness proofs)
|
|
66
66
|
agent.startHeartbeat();
|
|
@@ -78,18 +78,18 @@ agent.stopHeartbeat();
|
|
|
78
78
|
|
|
79
79
|
## API
|
|
80
80
|
|
|
81
|
-
### `BeatAgent`
|
|
82
|
-
|
|
83
|
-
| Method | Description |
|
|
84
|
-
|--------|-------------|
|
|
85
|
-
| `init()` | Initialize the agent's Beat chain (birth in Logical Time) |
|
|
86
|
-
| `purchaseSigil(opts)` | Purchase a SIGIL identity (required for heartbeating) |
|
|
87
|
-
| `updateMetadata(fields)` | Update mutable SIGIL metadata fields |
|
|
88
|
-
| `heartbeat(paymentTx?, globalAnchor?)` | Submit a paid heartbeat and receive a signed lineage proof |
|
|
89
|
-
| `startHeartbeat()` | Start autonomous heartbeat loop |
|
|
90
|
-
| `stopHeartbeat()` | Stop heartbeat |
|
|
91
|
-
| `getPassport()` | Get latest lineage proof (Passport) |
|
|
92
|
-
| `reissueProof(paymentTx?)` | Reissue proof without extending lineage |
|
|
81
|
+
### `BeatAgent`
|
|
82
|
+
|
|
83
|
+
| Method | Description |
|
|
84
|
+
|--------|-------------|
|
|
85
|
+
| `init()` | Initialize the agent's Beat chain (birth in Logical Time) |
|
|
86
|
+
| `purchaseSigil(opts)` | Purchase a SIGIL identity (required for heartbeating) |
|
|
87
|
+
| `updateMetadata(fields)` | Update mutable SIGIL metadata fields |
|
|
88
|
+
| `heartbeat(paymentTx?, globalAnchor?)` | Submit a paid heartbeat and receive a signed lineage proof |
|
|
89
|
+
| `startHeartbeat()` | Start autonomous heartbeat loop |
|
|
90
|
+
| `stopHeartbeat()` | Stop heartbeat |
|
|
91
|
+
| `getPassport()` | Get latest lineage proof (Passport) |
|
|
92
|
+
| `reissueProof(paymentTx?)` | Reissue proof without extending lineage |
|
|
93
93
|
| `requestSpawn(name?)` | Spawn a child agent (requires accumulated beats) |
|
|
94
94
|
| `getStatus()` | Get full beat status from registry |
|
|
95
95
|
| `getLocalState()` | Get local state (no network call) |
|
|
@@ -124,7 +124,7 @@ Returns `RegistrationResult` with `hash`, `api_key`, `secret`, `wallet?`.
|
|
|
124
124
|
|
|
125
125
|
**Note:** Agent names should only contain `[a-zA-Z0-9_\-. ]`. Other characters are stripped by the server before signature verification.
|
|
126
126
|
|
|
127
|
-
### Phase 2 Types
|
|
127
|
+
### Phase 2 Types
|
|
128
128
|
|
|
129
129
|
```typescript
|
|
130
130
|
import type { Passport, LineageProof, IdentityClass, SigilResult, HeartbeatResult } from '@provenonce/sdk';
|
|
@@ -133,20 +133,20 @@ import type { Passport, LineageProof, IdentityClass, SigilResult, HeartbeatResul
|
|
|
133
133
|
// Contains: agent_hash, agent_public_key, identity_class, lineage_chain_hash,
|
|
134
134
|
// provenonce_signature, issued_at, valid_until, etc.
|
|
135
135
|
|
|
136
|
-
// IdentityClass = 'narrow_task' | 'autonomous' | 'orchestrator'
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### `purchaseSigil(opts)` required fields
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
await agent.purchaseSigil({
|
|
143
|
-
identity_class: 'narrow_task' | 'autonomous' | 'orchestrator',
|
|
144
|
-
principal: 'my-agent',
|
|
145
|
-
tier: 'sov' | 'org' | 'ind' | 'eph' | 'sbx',
|
|
146
|
-
payment_tx: 'solana-tx-signature...', // or 'devnet-skip' on devnet
|
|
147
|
-
name: 'optional-display-name'
|
|
148
|
-
});
|
|
149
|
-
```
|
|
136
|
+
// IdentityClass = 'narrow_task' | 'autonomous' | 'orchestrator'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `purchaseSigil(opts)` required fields
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
await agent.purchaseSigil({
|
|
143
|
+
identity_class: 'narrow_task' | 'autonomous' | 'orchestrator',
|
|
144
|
+
principal: 'my-agent',
|
|
145
|
+
tier: 'sov' | 'org' | 'ind' | 'eph' | 'sbx',
|
|
146
|
+
payment_tx: 'solana-tx-signature...', // or 'devnet-skip' on devnet
|
|
147
|
+
name: 'optional-display-name'
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
150
|
|
|
151
151
|
### Error Handling
|
|
152
152
|
|
|
@@ -181,7 +181,7 @@ Python examples use the REST API directly — no Python SDK needed. See [`exampl
|
|
|
181
181
|
|
|
182
182
|
## Links
|
|
183
183
|
|
|
184
|
-
- [Live prototype](https://provenonce.io)
|
|
185
|
-
- [npm package](https://www.npmjs.com/package/@provenonce/sdk)
|
|
186
|
-
- [API docs](https://provenonce.dev)
|
|
187
|
-
- [Whitepaper](https://provenonce.dev/whitepaper)
|
|
184
|
+
- [Live prototype](https://provenonce.io)
|
|
185
|
+
- [npm package](https://www.npmjs.com/package/@provenonce/sdk)
|
|
186
|
+
- [API docs](https://provenonce.dev)
|
|
187
|
+
- [Whitepaper](https://provenonce.dev/whitepaper)
|
package/dist/index.d.mts
CHANGED
|
@@ -242,9 +242,42 @@ interface RegistrationResult {
|
|
|
242
242
|
heartbeat?: string;
|
|
243
243
|
};
|
|
244
244
|
}
|
|
245
|
+
/** Options for the register() function */
|
|
246
|
+
interface RegisterOptions {
|
|
247
|
+
registryUrl?: string;
|
|
248
|
+
parentHash?: string;
|
|
249
|
+
parentApiKey?: string;
|
|
250
|
+
registrationSecret?: string;
|
|
251
|
+
/** Single-use registration token from POST /register/token or POST /register/email/verify */
|
|
252
|
+
registrationToken?: string;
|
|
253
|
+
/** Admin-minted invite token */
|
|
254
|
+
registrationInvite?: string;
|
|
255
|
+
/** Hex-encoded 32-byte Ed25519 secret seed (bring-your-own Solana key) */
|
|
256
|
+
walletSecretKey?: string;
|
|
257
|
+
/** Wallet model: 'self-custody' (Model A) or 'operator' (Model B). Must be set explicitly to opt in. */
|
|
258
|
+
walletModel?: 'self-custody' | 'operator';
|
|
259
|
+
/** Wallet chain: 'solana' (default when wallet is used) or 'ethereum' (D-63) */
|
|
260
|
+
walletChain?: 'solana' | 'ethereum';
|
|
261
|
+
/** Wallet address for Ethereum bring-your-own (0x + 40 hex chars) */
|
|
262
|
+
walletAddress?: string;
|
|
263
|
+
/** Async function to sign a message with an Ethereum wallet (EIP-191 personal_sign). Returns 0x-prefixed 65-byte hex sig. */
|
|
264
|
+
walletSignFn?: (message: string) => Promise<string>;
|
|
265
|
+
/** Operator's Solana wallet address (base58). Required when walletModel='operator'. */
|
|
266
|
+
operatorWalletAddress?: string;
|
|
267
|
+
/** Function to sign a message with the operator's Solana wallet. Required when walletModel='operator'. */
|
|
268
|
+
operatorSignFn?: (message: string) => Promise<string>;
|
|
269
|
+
/** Optional agent metadata (arbitrary JSON object, max 4KB). Returned in /verify and /status. */
|
|
270
|
+
metadata?: Record<string, unknown>;
|
|
271
|
+
}
|
|
245
272
|
/**
|
|
246
273
|
* Register a new agent on the Provenonce registry.
|
|
247
274
|
*
|
|
275
|
+
* With registration token (from /register/token or email verification):
|
|
276
|
+
* const creds = await register('my-agent', {
|
|
277
|
+
* registryUrl: '...',
|
|
278
|
+
* registrationToken: '<token-from-email-verify>',
|
|
279
|
+
* });
|
|
280
|
+
*
|
|
248
281
|
* No wallet (default, single-phase):
|
|
249
282
|
* const creds = await register('my-agent', { registryUrl: '...' });
|
|
250
283
|
*
|
|
@@ -285,28 +318,7 @@ interface RegistrationResult {
|
|
|
285
318
|
* parentApiKey: parentCreds.api_key,
|
|
286
319
|
* });
|
|
287
320
|
*/
|
|
288
|
-
declare function register(name: string, options?:
|
|
289
|
-
registryUrl?: string;
|
|
290
|
-
parentHash?: string;
|
|
291
|
-
parentApiKey?: string;
|
|
292
|
-
registrationSecret?: string;
|
|
293
|
-
/** Hex-encoded 32-byte Ed25519 secret seed (bring-your-own Solana key) */
|
|
294
|
-
walletSecretKey?: string;
|
|
295
|
-
/** Wallet model: 'self-custody' (Model A) or 'operator' (Model B). Must be set explicitly to opt in. */
|
|
296
|
-
walletModel?: 'self-custody' | 'operator';
|
|
297
|
-
/** Wallet chain: 'solana' (default when wallet is used) or 'ethereum' (D-63) */
|
|
298
|
-
walletChain?: 'solana' | 'ethereum';
|
|
299
|
-
/** Wallet address for Ethereum bring-your-own (0x + 40 hex chars) */
|
|
300
|
-
walletAddress?: string;
|
|
301
|
-
/** Async function to sign a message with an Ethereum wallet (EIP-191 personal_sign). Returns 0x-prefixed 65-byte hex sig. */
|
|
302
|
-
walletSignFn?: (message: string) => Promise<string>;
|
|
303
|
-
/** Operator's Solana wallet address (base58). Required when walletModel='operator'. */
|
|
304
|
-
operatorWalletAddress?: string;
|
|
305
|
-
/** Function to sign a message with the operator's Solana wallet. Required when walletModel='operator'. */
|
|
306
|
-
operatorSignFn?: (message: string) => Promise<string>;
|
|
307
|
-
/** Optional agent metadata (arbitrary JSON object, max 4KB). Returned in /verify and /status. */
|
|
308
|
-
metadata?: Record<string, unknown>;
|
|
309
|
-
}): Promise<RegistrationResult>;
|
|
321
|
+
declare function register(name: string, options?: RegisterOptions): Promise<RegistrationResult>;
|
|
310
322
|
interface BeatAgentConfig {
|
|
311
323
|
/** API key from registration (pvn_...) */
|
|
312
324
|
apiKey: string;
|
|
@@ -573,4 +585,4 @@ declare class ServerError extends ProvenonceError {
|
|
|
573
585
|
constructor(message: string, statusCode?: number);
|
|
574
586
|
}
|
|
575
587
|
|
|
576
|
-
export { type AgentStatus, AuthError, type Beat, BeatAgent, type BeatAgentConfig, type Capability, type CheckinResult, type ComplianceRegime, ErrorCode, FrozenError, type HeartbeatResult, type IdentityClass, type LineageProof, type MetadataUpdateResult, NetworkError, NotFoundError, type Passport, ProvenonceError, RateLimitError, type RegistrationResult, ServerError, type SigilMutableFields, type SigilProtocol, type SigilPurchaseOptions, type SigilResult, type SigilTier, type SpawnResult, StateError, type Substrate, type SubstrateProvider, ValidationError, type VerificationResult, type WalletInfo, computeBeat, computeBeatsLite, generateWalletKeypair, register };
|
|
588
|
+
export { type AgentStatus, AuthError, type Beat, BeatAgent, type BeatAgentConfig, type Capability, type CheckinResult, type ComplianceRegime, ErrorCode, FrozenError, type HeartbeatResult, type IdentityClass, type LineageProof, type MetadataUpdateResult, NetworkError, NotFoundError, type Passport, ProvenonceError, RateLimitError, type RegisterOptions, type RegistrationResult, ServerError, type SigilMutableFields, type SigilProtocol, type SigilPurchaseOptions, type SigilResult, type SigilTier, type SpawnResult, StateError, type Substrate, type SubstrateProvider, ValidationError, type VerificationResult, type WalletInfo, computeBeat, computeBeatsLite, generateWalletKeypair, register };
|
package/dist/index.d.ts
CHANGED
|
@@ -242,9 +242,42 @@ interface RegistrationResult {
|
|
|
242
242
|
heartbeat?: string;
|
|
243
243
|
};
|
|
244
244
|
}
|
|
245
|
+
/** Options for the register() function */
|
|
246
|
+
interface RegisterOptions {
|
|
247
|
+
registryUrl?: string;
|
|
248
|
+
parentHash?: string;
|
|
249
|
+
parentApiKey?: string;
|
|
250
|
+
registrationSecret?: string;
|
|
251
|
+
/** Single-use registration token from POST /register/token or POST /register/email/verify */
|
|
252
|
+
registrationToken?: string;
|
|
253
|
+
/** Admin-minted invite token */
|
|
254
|
+
registrationInvite?: string;
|
|
255
|
+
/** Hex-encoded 32-byte Ed25519 secret seed (bring-your-own Solana key) */
|
|
256
|
+
walletSecretKey?: string;
|
|
257
|
+
/** Wallet model: 'self-custody' (Model A) or 'operator' (Model B). Must be set explicitly to opt in. */
|
|
258
|
+
walletModel?: 'self-custody' | 'operator';
|
|
259
|
+
/** Wallet chain: 'solana' (default when wallet is used) or 'ethereum' (D-63) */
|
|
260
|
+
walletChain?: 'solana' | 'ethereum';
|
|
261
|
+
/** Wallet address for Ethereum bring-your-own (0x + 40 hex chars) */
|
|
262
|
+
walletAddress?: string;
|
|
263
|
+
/** Async function to sign a message with an Ethereum wallet (EIP-191 personal_sign). Returns 0x-prefixed 65-byte hex sig. */
|
|
264
|
+
walletSignFn?: (message: string) => Promise<string>;
|
|
265
|
+
/** Operator's Solana wallet address (base58). Required when walletModel='operator'. */
|
|
266
|
+
operatorWalletAddress?: string;
|
|
267
|
+
/** Function to sign a message with the operator's Solana wallet. Required when walletModel='operator'. */
|
|
268
|
+
operatorSignFn?: (message: string) => Promise<string>;
|
|
269
|
+
/** Optional agent metadata (arbitrary JSON object, max 4KB). Returned in /verify and /status. */
|
|
270
|
+
metadata?: Record<string, unknown>;
|
|
271
|
+
}
|
|
245
272
|
/**
|
|
246
273
|
* Register a new agent on the Provenonce registry.
|
|
247
274
|
*
|
|
275
|
+
* With registration token (from /register/token or email verification):
|
|
276
|
+
* const creds = await register('my-agent', {
|
|
277
|
+
* registryUrl: '...',
|
|
278
|
+
* registrationToken: '<token-from-email-verify>',
|
|
279
|
+
* });
|
|
280
|
+
*
|
|
248
281
|
* No wallet (default, single-phase):
|
|
249
282
|
* const creds = await register('my-agent', { registryUrl: '...' });
|
|
250
283
|
*
|
|
@@ -285,28 +318,7 @@ interface RegistrationResult {
|
|
|
285
318
|
* parentApiKey: parentCreds.api_key,
|
|
286
319
|
* });
|
|
287
320
|
*/
|
|
288
|
-
declare function register(name: string, options?:
|
|
289
|
-
registryUrl?: string;
|
|
290
|
-
parentHash?: string;
|
|
291
|
-
parentApiKey?: string;
|
|
292
|
-
registrationSecret?: string;
|
|
293
|
-
/** Hex-encoded 32-byte Ed25519 secret seed (bring-your-own Solana key) */
|
|
294
|
-
walletSecretKey?: string;
|
|
295
|
-
/** Wallet model: 'self-custody' (Model A) or 'operator' (Model B). Must be set explicitly to opt in. */
|
|
296
|
-
walletModel?: 'self-custody' | 'operator';
|
|
297
|
-
/** Wallet chain: 'solana' (default when wallet is used) or 'ethereum' (D-63) */
|
|
298
|
-
walletChain?: 'solana' | 'ethereum';
|
|
299
|
-
/** Wallet address for Ethereum bring-your-own (0x + 40 hex chars) */
|
|
300
|
-
walletAddress?: string;
|
|
301
|
-
/** Async function to sign a message with an Ethereum wallet (EIP-191 personal_sign). Returns 0x-prefixed 65-byte hex sig. */
|
|
302
|
-
walletSignFn?: (message: string) => Promise<string>;
|
|
303
|
-
/** Operator's Solana wallet address (base58). Required when walletModel='operator'. */
|
|
304
|
-
operatorWalletAddress?: string;
|
|
305
|
-
/** Function to sign a message with the operator's Solana wallet. Required when walletModel='operator'. */
|
|
306
|
-
operatorSignFn?: (message: string) => Promise<string>;
|
|
307
|
-
/** Optional agent metadata (arbitrary JSON object, max 4KB). Returned in /verify and /status. */
|
|
308
|
-
metadata?: Record<string, unknown>;
|
|
309
|
-
}): Promise<RegistrationResult>;
|
|
321
|
+
declare function register(name: string, options?: RegisterOptions): Promise<RegistrationResult>;
|
|
310
322
|
interface BeatAgentConfig {
|
|
311
323
|
/** API key from registration (pvn_...) */
|
|
312
324
|
apiKey: string;
|
|
@@ -573,4 +585,4 @@ declare class ServerError extends ProvenonceError {
|
|
|
573
585
|
constructor(message: string, statusCode?: number);
|
|
574
586
|
}
|
|
575
587
|
|
|
576
|
-
export { type AgentStatus, AuthError, type Beat, BeatAgent, type BeatAgentConfig, type Capability, type CheckinResult, type ComplianceRegime, ErrorCode, FrozenError, type HeartbeatResult, type IdentityClass, type LineageProof, type MetadataUpdateResult, NetworkError, NotFoundError, type Passport, ProvenonceError, RateLimitError, type RegistrationResult, ServerError, type SigilMutableFields, type SigilProtocol, type SigilPurchaseOptions, type SigilResult, type SigilTier, type SpawnResult, StateError, type Substrate, type SubstrateProvider, ValidationError, type VerificationResult, type WalletInfo, computeBeat, computeBeatsLite, generateWalletKeypair, register };
|
|
588
|
+
export { type AgentStatus, AuthError, type Beat, BeatAgent, type BeatAgentConfig, type Capability, type CheckinResult, type ComplianceRegime, ErrorCode, FrozenError, type HeartbeatResult, type IdentityClass, type LineageProof, type MetadataUpdateResult, NetworkError, NotFoundError, type Passport, ProvenonceError, RateLimitError, type RegisterOptions, type RegistrationResult, ServerError, type SigilMutableFields, type SigilProtocol, type SigilPurchaseOptions, type SigilResult, type SigilTier, type SpawnResult, StateError, type Substrate, type SubstrateProvider, ValidationError, type VerificationResult, type WalletInfo, computeBeat, computeBeatsLite, generateWalletKeypair, register };
|
package/dist/index.js
CHANGED
|
@@ -183,6 +183,12 @@ async function register(name, options) {
|
|
|
183
183
|
if (options?.registrationSecret) {
|
|
184
184
|
headers["x-registration-secret"] = options.registrationSecret;
|
|
185
185
|
}
|
|
186
|
+
if (options?.registrationToken) {
|
|
187
|
+
headers["x-registration-token"] = options.registrationToken;
|
|
188
|
+
}
|
|
189
|
+
if (options?.registrationInvite) {
|
|
190
|
+
headers["x-registration-invite"] = options.registrationInvite;
|
|
191
|
+
}
|
|
186
192
|
if (options?.parentHash) {
|
|
187
193
|
if (options.parentApiKey) {
|
|
188
194
|
headers["Authorization"] = `Bearer ${options.parentApiKey}`;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/beat-sdk.ts","../src/errors.ts"],"sourcesContent":["export { BeatAgent, computeBeat, computeBeatsLite, register, generateWalletKeypair } from './beat-sdk';\r\nexport type {\r\n BeatAgentConfig,\r\n Beat,\r\n CheckinResult,\r\n SpawnResult,\r\n AgentStatus,\r\n RegistrationResult,\r\n WalletInfo,\r\n // Phase 2 types\r\n IdentityClass,\r\n LineageProof,\r\n Passport,\r\n SigilResult,\r\n HeartbeatResult,\r\n // SIGIL Namespace v0.4 types\r\n SigilTier,\r\n Substrate,\r\n SubstrateProvider,\r\n Capability,\r\n SigilProtocol,\r\n ComplianceRegime,\r\n SigilPurchaseOptions,\r\n SigilMutableFields,\r\n MetadataUpdateResult,\r\n VerificationResult,\r\n} from './beat-sdk';\r\n\r\nexport {\r\n ProvenonceError,\r\n ValidationError,\r\n AuthError,\r\n RateLimitError,\r\n FrozenError,\r\n StateError,\r\n NotFoundError,\r\n NetworkError,\r\n ServerError,\r\n ErrorCode,\r\n} from './errors';\r\n","/**\r\n * ═══════════════════════════════════════════════════════════\r\n * PROVENONCE BEAT SDK — Agent Heartbeat Client\r\n * ═══════════════════════════════════════════════════════════\r\n * \r\n * \"NIST tells you what time it is.\r\n * Provenonce tells the agent at what speed it is allowed to exist.\"\r\n * \r\n * Usage:\r\n * \r\n * import { BeatAgent } from './beat-sdk';\r\n * \r\n * const agent = new BeatAgent({\r\n * apiKey: 'pvn_...',\r\n * registryUrl: 'https://provenonce.io',\r\n * });\r\n * \r\n * await agent.init(); // Birth in Beat time\r\n * await agent.pulse(50); // Compute 50 beats\r\n * await agent.checkin(); // Report to registry\r\n * \r\n * // Or run the autonomous heartbeat:\r\n * agent.startHeartbeat(); // Computes + checks in continuously\r\n * // ... do your agent work ...\r\n * agent.stopHeartbeat();\r\n * \r\n * ═══════════════════════════════════════════════════════════\r\n */\r\n\r\nimport { createHash, generateKeyPairSync, sign, verify, createPrivateKey, createPublicKey } from 'crypto';\r\nimport {\r\n ValidationError,\r\n AuthError,\r\n RateLimitError,\r\n FrozenError,\r\n StateError,\r\n NetworkError,\r\n ServerError,\r\n mapApiError,\r\n ErrorCode,\r\n} from './errors';\r\n\r\n// ============ PHASE 2 TYPES ============\r\n\r\n/** SIGIL identity class — determines tier pricing and heartbeat volume caps */\r\nexport type IdentityClass = 'narrow_task' | 'autonomous' | 'orchestrator';\r\n\r\n/** SIGIL trust governance tier — orthogonal to identity_class (fee axis) */\r\nexport type SigilTier = 'sov' | 'org' | 'ind' | 'eph' | 'sbx';\r\n\r\n/** Substrate — what the agent runs on */\r\nexport type Substrate = 'frontier' | 'open' | 'local' | 'symbolic' | 'hybrid' | 'human';\r\n\r\n/** Substrate provider */\r\nexport type SubstrateProvider = 'anthropic' | 'openai' | 'google' | 'meta' | 'mistral' | 'xai' | 'cohere' | 'deepseek' | 'custom';\r\n\r\n/** Capability — what the agent primarily does */\r\nexport type Capability = 'analyst' | 'executor' | 'orchestrator' | 'guardian' | 'retriever' | 'renderer' | 'witness';\r\n\r\n/** Protocol — how to reach the agent */\r\nexport type SigilProtocol = 'http' | 'grpc' | 'websocket' | 'mcp' | 'a2a' | 'custom';\r\n\r\n/** Compliance regime */\r\nexport type ComplianceRegime = 'gdpr' | 'pdpa' | 'hipaa' | 'sox' | 'aisi' | 'none' | 'custom';\r\n\r\n/**\r\n * Ed25519-signed lineage proof — portable, offline-verifiable credential.\r\n * Also known as the agent's \"passport\" — a cryptographic proof of identity\r\n * that can be verified offline without any API call or SOL cost.\r\n */\r\nexport interface LineageProof {\r\n agent_hash: string;\r\n agent_public_key: string | null;\r\n identity_class: IdentityClass;\r\n registered_at_beat: number;\r\n sigil_issued_at_beat: number | null;\r\n last_heartbeat_beat: number;\r\n lineage_chain_hash: string;\r\n issued_at: number;\r\n valid_until: number;\r\n provenonce_signature: string;\r\n}\r\n\r\n/** Passport = LineageProof. The agent's portable, offline-verifiable credential. */\r\nexport type Passport = LineageProof;\r\n\r\n/** Options for purchasing a SIGIL with full namespace */\r\nexport interface SigilPurchaseOptions {\r\n identity_class: IdentityClass;\r\n principal: string;\r\n tier: SigilTier;\r\n name?: string; // \"auto\" or custom name\r\n payment_tx: string;\r\n // Optional initial metadata\r\n substrate?: Substrate;\r\n substrate_provider?: SubstrateProvider;\r\n substrate_model?: string;\r\n capability?: Capability;\r\n capability_scope?: string;\r\n tools?: string[];\r\n modality_input?: string[];\r\n modality_output?: string[];\r\n protocol?: SigilProtocol;\r\n endpoint?: string;\r\n compliance_regime?: ComplianceRegime;\r\n}\r\n\r\n/** Mutable SIGIL metadata fields for PATCH updates */\r\nexport interface SigilMutableFields {\r\n substrate?: Substrate;\r\n substrate_provider?: SubstrateProvider;\r\n substrate_model?: string;\r\n capability?: Capability;\r\n capability_scope?: string;\r\n generation_trigger?: string;\r\n tools?: string[];\r\n modality_input?: string[];\r\n modality_output?: string[];\r\n protocol?: SigilProtocol;\r\n endpoint?: string;\r\n compliance_regime?: ComplianceRegime;\r\n}\r\n\r\n/** Result from purchasing a SIGIL (Structured Identity Governance and Intelligent Lookup) */\r\nexport interface SigilResult {\r\n ok: boolean;\r\n sigil?: {\r\n sigil: string; // Full SIGIL string: name*principal*tier\r\n sigil_name: string;\r\n principal: string;\r\n tier: SigilTier;\r\n identity_class: IdentityClass;\r\n issued_at_beat: number;\r\n birth_tx: string | null;\r\n explorer_url: string | null;\r\n };\r\n lineage_proof?: LineageProof;\r\n fee?: {\r\n amount_sol: number;\r\n amount_lamports: number;\r\n payment_tx: string | null;\r\n };\r\n error?: string;\r\n}\r\n\r\n/** Result from updating mutable SIGIL metadata */\r\nexport interface MetadataUpdateResult {\r\n ok: boolean;\r\n sigil?: string;\r\n generation?: number;\r\n updated_fields?: string[];\r\n error?: string;\r\n}\r\n\r\n/** Result from offline lineage proof verification */\r\nexport interface VerificationResult {\r\n /** Overall validity: signature is valid AND not expired */\r\n valid: boolean;\r\n /** Ed25519 signature verification passed */\r\n signatureValid: boolean;\r\n /** Proof has passed its valid_until timestamp */\r\n expired: boolean;\r\n /** The beat index of the agent's last heartbeat */\r\n lastHeartbeatBeat: number;\r\n /** Beats elapsed since last heartbeat (null if currentBeat not provided) */\r\n beatsSinceHeartbeat: number | null;\r\n /** Human-readable warning if proof is expired or stale */\r\n warning?: string;\r\n}\r\n\r\n/** Result from a paid heartbeat */\r\nexport interface HeartbeatResult {\r\n ok: boolean;\r\n lineage_proof?: LineageProof;\r\n heartbeat_count_epoch?: number;\r\n billing_epoch?: number;\r\n current_beat?: number;\r\n fee?: {\r\n amount_sol: number;\r\n amount_lamports: number;\r\n tier: number;\r\n payment_tx: string | null;\r\n };\r\n error?: string;\r\n}\r\n\r\n// ============ VDF ENGINE (LOCAL) ============\r\n\r\nexport interface Beat {\r\n index: number;\r\n hash: string;\r\n prev: string;\r\n timestamp: number;\r\n nonce?: string;\r\n anchor_hash?: string;\r\n}\r\n\r\nfunction computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string, anchorHash?: string): Beat {\r\n const timestamp = Date.now();\r\n\r\n const seed = anchorHash\r\n ? `${prevHash}:${beatIndex}:${nonce || ''}:${anchorHash}`\r\n : `${prevHash}:${beatIndex}:${nonce || ''}`;\r\n\r\n let current = createHash('sha256')\r\n .update(seed)\r\n .digest('hex');\r\n\r\n for (let i = 0; i < difficulty; i++) {\r\n current = createHash('sha256')\r\n .update(current)\r\n .digest('hex');\r\n }\r\n\r\n return { index: beatIndex, hash: current, prev: prevHash, timestamp, nonce, anchor_hash: anchorHash };\r\n}\r\n\r\n// ============ SDK RESULT TYPES ============\r\n\r\n/** Result from a check-in submission */\r\nexport interface CheckinResult {\r\n ok: boolean;\r\n total_beats: number;\r\n beats_accepted: number;\r\n global_beat: number;\r\n status?: string;\r\n beats_behind?: number;\r\n}\r\n\r\n/** Result from a spawn request */\r\nexport interface SpawnResult {\r\n ok: boolean;\r\n eligible: boolean;\r\n child_hash?: string;\r\n progress_pct?: number;\r\n deficit?: number;\r\n}\r\n\r\n/** Agent status from the registry */\r\nexport interface AgentStatus {\r\n already_initialized: boolean;\r\n total_beats: number;\r\n genesis_hash: string;\r\n status: string;\r\n genesis?: { hash: string; prev: string; timestamp: number };\r\n difficulty?: number;\r\n}\r\n\r\n// ============ WALLET KEYPAIR GENERATION ============\r\n\r\n// DER prefix for Ed25519 PKCS8 private keys (16 bytes)\r\nconst ED25519_PKCS8_PREFIX = Buffer.from('302e020100300506032b657004220420', 'hex');\r\n\r\n/**\r\n * Generate an Ed25519 keypair for agent wallet identity.\r\n * Returns hex-encoded raw keys (32 bytes each).\r\n * Uses Node.js built-in crypto — zero external dependencies.\r\n */\r\nexport function generateWalletKeypair(): { publicKey: string; secretKey: string } {\r\n const { publicKey, privateKey } = generateKeyPairSync('ed25519');\r\n const pubRaw = publicKey.export({ type: 'spki', format: 'der' }).subarray(12); // 32 bytes\r\n const privRaw = privateKey.export({ type: 'pkcs8', format: 'der' }).subarray(16); // 32 bytes\r\n return {\r\n publicKey: Buffer.from(pubRaw).toString('hex'),\r\n secretKey: Buffer.from(privRaw).toString('hex'),\r\n };\r\n}\r\n\r\n/**\r\n * Sign a message with an Ed25519 private key (hex-encoded 32-byte seed).\r\n * Returns hex-encoded signature (64 bytes).\r\n */\r\nfunction signMessage(secretKeyHex: string, message: string): string {\r\n const privRaw = Buffer.from(secretKeyHex, 'hex');\r\n const privKeyDer = Buffer.concat([ED25519_PKCS8_PREFIX, privRaw]);\r\n const keyObject = createPrivateKey({ key: privKeyDer, format: 'der', type: 'pkcs8' });\r\n const sig = sign(null, Buffer.from(message), keyObject);\r\n return Buffer.from(sig).toString('hex');\r\n}\r\n\r\n// ============ REGISTRATION ============\r\n\r\n/** Wallet info returned from root registration */\r\nexport interface WalletInfo {\r\n /** Hex-encoded 32-byte Ed25519 public key (Solana self-custody only, empty otherwise) */\r\n public_key: string;\r\n /** Hex-encoded 32-byte Ed25519 secret seed — SAVE THIS for future fee signing (Solana self-custody only) */\r\n secret_key: string;\r\n /** Solana-compatible base58 address (Solana wallets only) */\r\n solana_address?: string;\r\n /** The wallet address (base58 for Solana, 0x for Ethereum) */\r\n address: string;\r\n /** Wallet chain: 'solana' or 'ethereum' */\r\n chain: string;\r\n}\r\n\r\n/** Result from registering an agent */\r\nexport interface RegistrationResult {\r\n hash: string;\r\n api_key: string;\r\n secret: string;\r\n type: 'root' | 'agent';\r\n parent: string | null;\r\n depth: number;\r\n name: string;\r\n metadata?: Record<string, unknown> | null;\r\n /** @deprecated No Solana write at registration (D-65). Will be null. */\r\n signature?: string | null;\r\n /** @deprecated No Solana write at registration (D-65). Will be null. */\r\n explorer_url?: string | null;\r\n /** Wallet chain: 'solana', 'ethereum', or null (no wallet) */\r\n wallet_chain?: string | null;\r\n beat?: { genesis_hash: string; difficulty: number; status: string };\r\n /** Wallet info — only present for root agents with wallets */\r\n wallet?: WalletInfo;\r\n /** Next steps after registration */\r\n _next_steps?: { sigil?: string; heartbeat?: string };\r\n}\r\n\r\n/**\r\n * Register a new agent on the Provenonce registry.\r\n *\r\n * No wallet (default, single-phase):\r\n * const creds = await register('my-agent', { registryUrl: '...' });\r\n *\r\n * Solana self-custody wallet (Model A, two-phase):\r\n * const creds = await register('my-org', {\r\n * registryUrl: '...',\r\n * walletModel: 'self-custody',\r\n * });\r\n * // creds.wallet.secret_key = hex secret (SAVE THIS)\r\n * // creds.wallet.address = base58 Solana address\r\n *\r\n * Solana with existing key:\r\n * const creds = await register('my-org', {\r\n * registryUrl: '...',\r\n * walletSecretKey: '<hex-encoded-32-byte-seed>',\r\n * });\r\n *\r\n * Ethereum bring-your-own (two-phase):\r\n * const creds = await register('my-org', {\r\n * registryUrl: '...',\r\n * walletChain: 'ethereum',\r\n * walletAddress: '0x...',\r\n * walletSignFn: (msg) => wallet.signMessage(msg),\r\n * });\r\n *\r\n * Solana operator (Model B, two-phase):\r\n * const creds = await register('my-org', {\r\n * registryUrl: '...',\r\n * walletModel: 'operator',\r\n * operatorWalletAddress: '<base58>',\r\n * operatorSignFn: (msg) => signWithWallet(msg),\r\n * });\r\n *\r\n * Child agent (no wallet):\r\n * const creds = await register('worker-1', {\r\n * registryUrl: '...',\r\n * parentHash: parentCreds.hash,\r\n * parentApiKey: parentCreds.api_key,\r\n * });\r\n */\r\nexport async function register(\r\n name: string,\r\n options?: {\r\n registryUrl?: string;\r\n parentHash?: string;\r\n parentApiKey?: string;\r\n registrationSecret?: string;\r\n /** Hex-encoded 32-byte Ed25519 secret seed (bring-your-own Solana key) */\r\n walletSecretKey?: string;\r\n /** Wallet model: 'self-custody' (Model A) or 'operator' (Model B). Must be set explicitly to opt in. */\r\n walletModel?: 'self-custody' | 'operator';\r\n /** Wallet chain: 'solana' (default when wallet is used) or 'ethereum' (D-63) */\r\n walletChain?: 'solana' | 'ethereum';\r\n /** Wallet address for Ethereum bring-your-own (0x + 40 hex chars) */\r\n walletAddress?: string;\r\n /** Async function to sign a message with an Ethereum wallet (EIP-191 personal_sign). Returns 0x-prefixed 65-byte hex sig. */\r\n walletSignFn?: (message: string) => Promise<string>;\r\n /** Operator's Solana wallet address (base58). Required when walletModel='operator'. */\r\n operatorWalletAddress?: string;\r\n /** Function to sign a message with the operator's Solana wallet. Required when walletModel='operator'. */\r\n operatorSignFn?: (message: string) => Promise<string>;\r\n /** Optional agent metadata (arbitrary JSON object, max 4KB). Returned in /verify and /status. */\r\n metadata?: Record<string, unknown>;\r\n },\r\n): Promise<RegistrationResult> {\r\n // SDK-P1-07/P1-08: validate inputs\r\n if (!name || typeof name !== 'string' || name.trim().length === 0) {\r\n throw new ValidationError('name is required (must be a non-empty string)');\r\n }\r\n if (name.length > 64) {\r\n throw new ValidationError('name must be 64 characters or fewer');\r\n }\r\n\r\n const url = options?.registryUrl || 'https://provenonce.io';\r\n try {\r\n new URL(url);\r\n } catch {\r\n throw new ValidationError('registryUrl is not a valid URL');\r\n }\r\n\r\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\r\n\r\n if (options?.registrationSecret) {\r\n headers['x-registration-secret'] = options.registrationSecret;\r\n }\r\n\r\n // ===== CHILD REGISTRATION (no wallet, single-phase) =====\r\n if (options?.parentHash) {\r\n if (options.parentApiKey) {\r\n headers['Authorization'] = `Bearer ${options.parentApiKey}`;\r\n }\r\n\r\n const res = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, parent: options.parentHash, ...(options.metadata && { metadata: options.metadata }) }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string };\r\n try {\r\n data = await res.json() as RegistrationResult & { error?: string };\r\n } catch {\r\n throw new NetworkError(`Registration failed: ${res.status} ${res.statusText} (non-JSON response)`);\r\n }\r\n if (!res.ok) throw mapApiError(res.status, data, '/api/v1/register');\r\n return data;\r\n }\r\n\r\n // ===== ETHEREUM BRING-YOUR-OWN (D-63, two-phase) =====\r\n if (options?.walletChain === 'ethereum') {\r\n if (!options.walletAddress || !options.walletSignFn) {\r\n throw new ValidationError('Ethereum registration requires walletAddress and walletSignFn');\r\n }\r\n\r\n if (!/^0x[0-9a-fA-F]{40}$/.test(options.walletAddress)) {\r\n throw new ValidationError('walletAddress must be a valid Ethereum address (0x + 40 hex chars)');\r\n }\r\n\r\n // Phase 1: Get challenge nonce from server\r\n const challengeRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, action: 'challenge', wallet_chain: 'ethereum' }),\r\n });\r\n\r\n let challengeData: { nonce?: string; error?: string };\r\n try {\r\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\r\n } catch {\r\n throw new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\r\n }\r\n if (!challengeRes.ok || !challengeData.nonce) {\r\n throw mapApiError(challengeRes.status, challengeData, '/api/v1/register');\r\n }\r\n\r\n // Phase 2: Sign with Ethereum wallet (EIP-191 personal_sign)\r\n const nonce = challengeData.nonce;\r\n const message = `provenonce-register-ethereum:${nonce}:${options.walletAddress}:${name}`;\r\n const walletSignature = await options.walletSignFn(message);\r\n\r\n const registerRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({\r\n name,\r\n wallet_chain: 'ethereum',\r\n wallet_address: options.walletAddress,\r\n wallet_signature: walletSignature,\r\n wallet_nonce: nonce,\r\n ...(options.metadata && { metadata: options.metadata }),\r\n }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; chain?: string } };\r\n try {\r\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; chain?: string } };\r\n } catch {\r\n throw new NetworkError(`Ethereum registration failed: ${registerRes.status} (non-JSON response)`);\r\n }\r\n if (!registerRes.ok) throw mapApiError(registerRes.status, data, '/api/v1/register');\r\n\r\n // Ethereum: wallet has address only (no keypair — user keeps custody externally)\r\n data.wallet = {\r\n public_key: '',\r\n secret_key: '',\r\n address: data.wallet?.address || options.walletAddress,\r\n chain: 'ethereum',\r\n };\r\n\r\n return data;\r\n }\r\n\r\n // ===== MODEL B: SOLANA OPERATOR WALLET REGISTRATION (two-phase) =====\r\n if (options?.walletModel === 'operator') {\r\n if (!options.operatorWalletAddress || !options.operatorSignFn) {\r\n throw new ValidationError('Operator registration requires operatorWalletAddress and operatorSignFn');\r\n }\r\n\r\n // Phase 1: Get challenge nonce from server\r\n const challengeRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, action: 'challenge', wallet_model: 'operator' }),\r\n });\r\n\r\n let challengeData: { nonce?: string; error?: string };\r\n try {\r\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\r\n } catch {\r\n throw new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\r\n }\r\n if (!challengeRes.ok || !challengeData.nonce) {\r\n throw mapApiError(challengeRes.status, challengeData, '/api/v1/register');\r\n }\r\n\r\n // Phase 2: Operator signs challenge and register\r\n const nonce = challengeData.nonce;\r\n const message = `provenonce-register-operator:${nonce}:${options.operatorWalletAddress}:${name}`;\r\n const walletSignature = await options.operatorSignFn(message);\r\n\r\n const registerRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({\r\n name,\r\n wallet_model: 'operator',\r\n operator_wallet_address: options.operatorWalletAddress,\r\n wallet_signature: walletSignature,\r\n wallet_nonce: nonce,\r\n ...(options.metadata && { metadata: options.metadata }),\r\n }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\r\n try {\r\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\r\n } catch {\r\n throw new NetworkError(`Operator registration failed: ${registerRes.status} (non-JSON response)`);\r\n }\r\n if (!registerRes.ok) throw mapApiError(registerRes.status, data, '/api/v1/register');\r\n\r\n // Model B: wallet has address only (no secret_key/public_key — operator keeps custody)\r\n const addr = data.wallet?.address || data.wallet?.solana_address || options.operatorWalletAddress;\r\n data.wallet = {\r\n public_key: '',\r\n secret_key: '',\r\n solana_address: addr,\r\n address: addr,\r\n chain: 'solana',\r\n };\r\n\r\n return data;\r\n }\r\n\r\n // ===== MODEL A: SOLANA SELF-CUSTODY WALLET REGISTRATION (opt-in, two-phase) =====\r\n if (options?.walletModel === 'self-custody' || options?.walletSecretKey) {\r\n // Generate or use provided wallet keypair\r\n let walletKeys: { publicKey: string; secretKey: string };\r\n if (options?.walletSecretKey) {\r\n // Derive public key from provided secret\r\n const privRaw = Buffer.from(options.walletSecretKey, 'hex');\r\n const privKeyDer = Buffer.concat([ED25519_PKCS8_PREFIX, privRaw]);\r\n const keyObject = createPrivateKey({ key: privKeyDer, format: 'der', type: 'pkcs8' });\r\n const pubRaw = keyObject.export({ type: 'spki', format: 'der' }).subarray(12);\r\n walletKeys = {\r\n publicKey: Buffer.from(pubRaw).toString('hex'),\r\n secretKey: options.walletSecretKey,\r\n };\r\n } else {\r\n walletKeys = generateWalletKeypair();\r\n }\r\n\r\n // Phase 1: Get challenge nonce from server\r\n const challengeRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, action: 'challenge' }),\r\n });\r\n\r\n let challengeData: { nonce?: string; error?: string };\r\n try {\r\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\r\n } catch {\r\n const err = new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\r\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\r\n throw err;\r\n }\r\n if (!challengeRes.ok || !challengeData.nonce) {\r\n // Attach wallet keys so caller can retry with the same keypair\r\n const err = mapApiError(challengeRes.status, challengeData, '/api/v1/register');\r\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\r\n throw err;\r\n }\r\n\r\n // Phase 2: Sign challenge and register\r\n const nonce = challengeData.nonce;\r\n const message = `provenonce-register:${nonce}:${walletKeys.publicKey}:${name}`;\r\n const walletSignature = signMessage(walletKeys.secretKey, message);\r\n\r\n const registerRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({\r\n name,\r\n wallet_public_key: walletKeys.publicKey,\r\n wallet_signature: walletSignature,\r\n wallet_nonce: nonce,\r\n ...(options?.metadata && { metadata: options.metadata }),\r\n }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\r\n try {\r\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\r\n } catch {\r\n // Attach wallet keys so caller can retry with the same keypair\r\n const err = new NetworkError(`Registration failed: ${registerRes.status} (non-JSON response)`);\r\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\r\n throw err;\r\n }\r\n if (!registerRes.ok) {\r\n // Attach wallet keys so caller can retry with the same keypair via walletSecretKey option\r\n const err = mapApiError(registerRes.status, data, '/api/v1/register');\r\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\r\n throw err;\r\n }\r\n\r\n // Attach the wallet keys (secret is client-side only, never sent to server)\r\n const addr = data.wallet?.address || data.wallet?.solana_address || '';\r\n data.wallet = {\r\n public_key: walletKeys.publicKey,\r\n secret_key: walletKeys.secretKey,\r\n solana_address: addr,\r\n address: addr,\r\n chain: 'solana',\r\n };\r\n\r\n return data;\r\n }\r\n\r\n // ===== NO-WALLET REGISTRATION (D-62 default, single-phase) =====\r\n\r\n const res = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, ...(options?.metadata && { metadata: options.metadata }) }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string };\r\n try {\r\n data = await res.json() as RegistrationResult & { error?: string };\r\n } catch {\r\n throw new NetworkError(`Registration failed: ${res.status} ${res.statusText} (non-JSON response)`);\r\n }\r\n if (!res.ok) throw mapApiError(res.status, data, '/api/v1/register');\r\n return data;\r\n}\r\n\r\n// ============ SDK CONFIG ============\r\n\r\nexport interface BeatAgentConfig {\r\n /** API key from registration (pvn_...) */\r\n apiKey: string;\r\n\r\n /** Provenonce registry URL */\r\n registryUrl: string;\r\n\r\n /** @deprecated Use heartbeatIntervalSec. Beats to compute per pulse (default: 10) */\r\n beatsPerPulse?: number;\r\n\r\n /** @deprecated Use heartbeatIntervalSec. Seconds between automatic check-ins (default: 300 = 5min) */\r\n checkinIntervalSec?: number;\r\n\r\n /** Seconds between automatic heartbeats (default: 300 = 5min). Replaces checkinIntervalSec. */\r\n heartbeatIntervalSec?: number;\r\n\r\n /** @deprecated VDF pulse callback. No longer used in Phase 2. */\r\n onPulse?: (beats: Beat[], totalBeats: number) => void;\r\n\r\n /** @deprecated Use onHeartbeat. Callback when check-in completes. */\r\n onCheckin?: (result: CheckinResult) => void;\r\n\r\n /** Callback when heartbeat completes (Phase 2) */\r\n onHeartbeat?: (result: HeartbeatResult) => void;\r\n\r\n /** Callback on error */\r\n onError?: (error: Error, context: string) => void;\r\n\r\n /** Callback when status changes */\r\n onStatusChange?: (status: string, details: Record<string, unknown>) => void;\r\n\r\n /** Enable verbose logging */\r\n verbose?: boolean;\r\n}\r\n\r\n// ============ BEAT AGENT ============\r\n\r\nexport class BeatAgent {\r\n private config: Required<BeatAgentConfig>;\r\n private chain: Beat[] = [];\r\n private difficulty: number = 1000;\r\n private genesisHash: string = '';\r\n private latestBeat: Beat | null = null;\r\n private totalBeats: number = 0;\r\n private lastCheckinBeat: number = 0;\r\n private status: 'uninitialized' | 'active' | 'frozen' | 'revoked' = 'uninitialized';\r\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\r\n private globalBeat: number = 0;\r\n private globalAnchorHash: string = '';\r\n\r\n constructor(config: BeatAgentConfig) {\r\n // SDK-P1-08: validate required config fields\r\n if (!config.apiKey || typeof config.apiKey !== 'string') {\r\n throw new ValidationError('BeatAgentConfig.apiKey is required (must be a non-empty string)');\r\n }\r\n if (!config.registryUrl || typeof config.registryUrl !== 'string') {\r\n throw new ValidationError('BeatAgentConfig.registryUrl is required (must be a non-empty string)');\r\n }\r\n // SDK-P1-07: validate registryUrl is a valid URL\r\n try {\r\n new URL(config.registryUrl);\r\n } catch {\r\n throw new ValidationError('BeatAgentConfig.registryUrl is not a valid URL');\r\n }\r\n\r\n // SDK-P2: validate optional numeric config\r\n if (config.beatsPerPulse !== undefined && (!Number.isInteger(config.beatsPerPulse) || config.beatsPerPulse < 1 || config.beatsPerPulse > 10000)) {\r\n throw new ValidationError('BeatAgentConfig.beatsPerPulse must be an integer between 1 and 10000');\r\n }\r\n if (config.checkinIntervalSec !== undefined && (!Number.isFinite(config.checkinIntervalSec) || config.checkinIntervalSec < 10 || config.checkinIntervalSec > 86400)) {\r\n throw new ValidationError('BeatAgentConfig.checkinIntervalSec must be between 10 and 86400');\r\n }\r\n\r\n this.config = {\r\n beatsPerPulse: 10,\r\n checkinIntervalSec: 300,\r\n heartbeatIntervalSec: 300,\r\n onPulse: () => {},\r\n onCheckin: () => {},\r\n onHeartbeat: () => {},\r\n onError: () => {},\r\n onStatusChange: () => {},\r\n verbose: false,\r\n ...config,\r\n };\r\n }\r\n\r\n // ── INITIALIZATION ──\r\n\r\n /**\r\n * Initialize the agent's Beat chain.\r\n * This is the agent's \"birth\" in Logical Time.\r\n * Must be called once before computing beats.\r\n */\r\n async init(): Promise<{ ok: boolean; genesis?: string; error?: string }> {\r\n try {\r\n this.log('Initializing Beat chain...');\r\n\r\n const res = await this.api('POST', '/api/v1/agent/init');\r\n\r\n if (res.genesis) {\r\n this.genesisHash = res.genesis.hash;\r\n this.difficulty = res.difficulty || 1000;\r\n this.latestBeat = {\r\n index: 0,\r\n hash: res.genesis.hash,\r\n prev: res.genesis.prev,\r\n timestamp: res.genesis.timestamp,\r\n };\r\n this.chain = [this.latestBeat];\r\n this.totalBeats = 0;\r\n this.status = 'active';\r\n this.config.onStatusChange('active', { genesis: this.genesisHash });\r\n this.log(`Born in Beat time. Genesis: ${this.genesisHash.slice(0, 16)}...`);\r\n } else if (res.already_initialized) {\r\n // Restore from existing state\r\n this.genesisHash = res.genesis_hash;\r\n this.totalBeats = res.total_beats;\r\n this.status = res.status as any;\r\n this.log(`Already initialized. Restoring state (${res.total_beats} beats).`);\r\n \r\n // Fetch full state to get latest hash\r\n await this.refreshState();\r\n }\r\n\r\n // Sync global anchor\r\n await this.syncGlobal();\r\n\r\n return { ok: true, genesis: this.genesisHash };\r\n\r\n } catch (err: any) {\r\n this.config.onError(err, 'init');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n // ── PULSE (COMPUTE BEATS) ──\r\n\r\n /**\r\n * @deprecated Phase 2: VDF computation retired (D-68). Payment is the liveness mechanism.\r\n * Use heartbeat() instead. This method will be removed in the next major version.\r\n *\r\n * Compute N beats locally (VDF hash chain).\r\n */\r\n pulse(count?: number): Beat[] {\r\n console.warn('[Provenonce SDK] pulse() is deprecated. Use heartbeat() instead (Phase 2).');\r\n if (this.status === 'frozen') {\r\n throw new FrozenError('Cannot pulse: agent is frozen. Use resync() to re-establish provenance.');\r\n }\r\n if (this.status !== 'active') {\r\n throw new StateError(`Cannot pulse: agent is ${this.status}.`, this.status);\r\n }\r\n // SDK-P2: validate count param\r\n if (count !== undefined && (!Number.isInteger(count) || count < 1 || count > 10000)) {\r\n throw new ValidationError('pulse count must be an integer between 1 and 10000');\r\n }\r\n return this.computeBeats(count);\r\n }\r\n\r\n /** Internal beat computation — no status check. Used by both pulse() and resync(). */\r\n private computeBeats(count?: number, onProgress?: (computed: number, total: number) => void): Beat[] {\r\n const n = count || this.config.beatsPerPulse;\r\n\r\n if (!this.latestBeat) {\r\n throw new StateError('Beat chain not initialized. Call init() first.', 'uninitialized', ErrorCode.AGENT_NOT_INITIALIZED);\r\n }\r\n\r\n const newBeats: Beat[] = [];\r\n let prevHash = this.latestBeat.hash;\r\n let startIndex = this.latestBeat.index + 1;\r\n\r\n const t0 = Date.now();\r\n // SDK-P2: report progress every 10% of beats\r\n const progressInterval = Math.max(1, Math.floor(n / 10));\r\n\r\n for (let i = 0; i < n; i++) {\r\n const beat = computeBeat(prevHash, startIndex + i, this.difficulty, undefined, this.globalAnchorHash || undefined);\r\n newBeats.push(beat);\r\n prevHash = beat.hash;\r\n if (onProgress && (i + 1) % progressInterval === 0) {\r\n onProgress(i + 1, n);\r\n }\r\n }\r\n\r\n const elapsed = Date.now() - t0;\r\n\r\n // Update state\r\n this.chain.push(...newBeats);\r\n this.latestBeat = newBeats[newBeats.length - 1];\r\n this.totalBeats += n;\r\n\r\n // Keep chain bounded (only last 1000 beats in memory)\r\n if (this.chain.length > 1000) {\r\n this.chain = this.chain.slice(-500);\r\n }\r\n\r\n this.config.onPulse(newBeats, this.totalBeats);\r\n this.log(`Pulse: ${n} beats in ${elapsed}ms (${(elapsed / n).toFixed(1)}ms/beat, D=${this.difficulty})`);\r\n\r\n return newBeats;\r\n }\r\n\r\n // ── CHECK-IN ──\r\n\r\n /**\r\n * @deprecated Phase 2: VDF check-in retired (D-68). Use heartbeat() instead.\r\n * This method will be removed in the next major version.\r\n */\r\n async checkin(): Promise<{ ok: boolean; total_beats?: number; error?: string }> {\r\n console.warn('[Provenonce SDK] checkin() is deprecated. Use heartbeat() instead (Phase 2).');\r\n // SDK-P1-02: fix guard to compare beat indices, not totalBeats vs lastCheckinBeat\r\n if (!this.latestBeat || this.latestBeat.index <= this.lastCheckinBeat) {\r\n this.log('No new beats since last check-in. Call pulse() first.');\r\n return { ok: true, total_beats: this.totalBeats }; // Nothing new to report\r\n }\r\n\r\n try {\r\n // Find the boundary hashes\r\n const fromBeat = this.lastCheckinBeat;\r\n const toBeat = this.latestBeat.index;\r\n\r\n // Build spot checks from our local chain\r\n // prev and nonce are required for the server to recompute VDF\r\n // Must always include to_beat (final beat) — server requires it for final hash verification\r\n const spotChecks: { index: number; hash: string; prev: string; nonce?: string }[] = [];\r\n\r\n // Always include the final beat\r\n const toBeatEntry = this.chain.find(b => b.index === toBeat);\r\n if (toBeatEntry) {\r\n spotChecks.push({ index: toBeatEntry.index, hash: toBeatEntry.hash, prev: toBeatEntry.prev, nonce: toBeatEntry.nonce });\r\n }\r\n\r\n // Sample up to 4 more from the rest\r\n const available = this.chain.filter(b => b.index > this.lastCheckinBeat && b.index !== toBeat);\r\n const sampleCount = Math.min(4, available.length);\r\n\r\n for (let i = 0; i < sampleCount; i++) {\r\n const idx = Math.floor(Math.random() * available.length);\r\n const beat = available[idx];\r\n spotChecks.push({ index: beat.index, hash: beat.hash, prev: beat.prev, nonce: beat.nonce });\r\n available.splice(idx, 1);\r\n }\r\n const fromHash = this.chain.find(b => b.index === fromBeat)?.hash \r\n || this.genesisHash;\r\n const toHash = this.latestBeat.hash;\r\n\r\n const res = await this.api('POST', '/api/v1/agent/checkin', {\r\n proof: {\r\n from_beat: fromBeat,\r\n to_beat: toBeat,\r\n from_hash: fromHash,\r\n to_hash: toHash,\r\n beats_computed: toBeat - fromBeat,\r\n global_anchor: this.globalBeat,\r\n anchor_hash: this.globalAnchorHash || undefined,\r\n spot_checks: spotChecks,\r\n },\r\n });\r\n\r\n if (res.ok) {\r\n this.lastCheckinBeat = toBeat;\r\n this.totalBeats = res.total_beats;\r\n this.config.onCheckin(res);\r\n this.log(`Check-in accepted: ${res.beats_accepted} beats, total=${res.total_beats}, global=${res.global_beat}`);\r\n \r\n if (res.status === 'warning_overdue') {\r\n this.config.onStatusChange('warning', { beats_behind: res.beats_behind });\r\n this.log(`⚠ WARNING: ${res.beats_behind} anchors behind. Check in more frequently.`);\r\n }\r\n }\r\n\r\n return { ok: res.ok, total_beats: res.total_beats };\r\n\r\n } catch (err: any) {\r\n this.config.onError(err, 'checkin');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n // ── AUTONOMOUS HEARTBEAT ──\r\n\r\n /**\r\n * Start the autonomous heartbeat loop.\r\n * Phase 2: Sends paid heartbeats at regular intervals.\r\n *\r\n * @param paymentTxFn - Optional function that returns a payment tx for each heartbeat.\r\n * If not provided, uses 'devnet-skip' (devnet only).\r\n */\r\n startHeartbeat(paymentTxFn?: () => Promise<string> | string): void {\r\n if (this.heartbeatInterval) {\r\n this.log('Heartbeat already running.');\r\n return;\r\n }\r\n\r\n if (this.status !== 'active' && this.status !== 'uninitialized') {\r\n throw new StateError(`Cannot start heartbeat in status '${this.status}'.`, this.status);\r\n }\r\n\r\n const intervalSec = this.config.heartbeatIntervalSec || this.config.checkinIntervalSec || 300;\r\n this.log(`Starting heartbeat (interval: ${intervalSec}s)...`);\r\n\r\n // SDK-P1-03: exponential backoff on consecutive errors\r\n let consecutiveErrors = 0;\r\n let skipCount = 0;\r\n\r\n this.heartbeatInterval = setInterval(async () => {\r\n if (skipCount > 0) {\r\n skipCount--;\r\n return;\r\n }\r\n\r\n try {\r\n const paymentTx = paymentTxFn ? await paymentTxFn() : 'devnet-skip';\r\n await this.heartbeat(paymentTx);\r\n consecutiveErrors = 0;\r\n } catch (err: any) {\r\n consecutiveErrors++;\r\n this.config.onError(err, 'heartbeat');\r\n skipCount = Math.min(32, Math.pow(2, consecutiveErrors - 1));\r\n this.log(`Heartbeat error #${consecutiveErrors}, backing off ${skipCount} ticks`);\r\n }\r\n }, intervalSec * 1000);\r\n }\r\n\r\n /**\r\n * Stop the heartbeat loop.\r\n */\r\n stopHeartbeat(): void {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n this.heartbeatInterval = null;\r\n this.log('Heartbeat stopped.');\r\n }\r\n }\r\n\r\n // ── RE-SYNC ──\r\n\r\n /**\r\n * @deprecated Phase 2: Resync retired (D-67). Dormancy resume is free — just call heartbeat().\r\n * This method will be removed in the next major version.\r\n */\r\n async resync(): Promise<{ ok: boolean; beats_required?: number; error?: string }> {\r\n console.warn('[Provenonce SDK] resync() is deprecated (D-67). Use heartbeat() to resume (Phase 2).');\r\n try {\r\n this.log('Requesting re-sync challenge...');\r\n\r\n // Phase 1: Get challenge\r\n const challenge = await this.api('POST', '/api/v1/agent/resync', {\r\n action: 'challenge',\r\n });\r\n\r\n if (!challenge.challenge) {\r\n return { ok: false, error: 'Failed to get challenge' };\r\n }\r\n\r\n const required = challenge.challenge.required_beats;\r\n this.difficulty = challenge.challenge.difficulty;\r\n this.log(`Re-sync challenge: compute ${required} beats at D=${this.difficulty}`);\r\n\r\n // Sync global anchor so beats are woven with a recent anchor hash\r\n await this.syncGlobal();\r\n\r\n // Compute the required beats\r\n const startHash = challenge.challenge.start_from_hash;\r\n const startBeat = challenge.challenge.start_from_beat;\r\n\r\n // Reset chain from the known point\r\n this.latestBeat = { index: startBeat, hash: startHash, prev: '', timestamp: Date.now() };\r\n this.chain = [this.latestBeat];\r\n\r\n const t0 = Date.now();\r\n this.computeBeats(required);\r\n const elapsed = Date.now() - t0;\r\n this.log(`Re-sync beats computed in ${elapsed}ms`);\r\n\r\n // Phase 2: Submit proof (include challenge_nonce for server verification)\r\n const proof = await this.api('POST', '/api/v1/agent/resync', {\r\n action: 'prove',\r\n challenge_nonce: challenge.challenge.nonce,\r\n proof: {\r\n from_beat: startBeat,\r\n to_beat: this.latestBeat!.index,\r\n from_hash: startHash,\r\n to_hash: this.latestBeat!.hash,\r\n beats_computed: required,\r\n global_anchor: challenge.challenge.sync_to_global,\r\n anchor_hash: this.globalAnchorHash || undefined,\r\n spot_checks: (() => {\r\n // Must include to_beat (final beat) — server requires it for final hash verification\r\n const toBeatEntry = this.chain.find(b => b.index === this.latestBeat!.index);\r\n // Sample from available chain beats (chain may be trimmed to 500 entries)\r\n const available = this.chain\r\n .filter(b => b.index !== this.latestBeat!.index && b.index > startBeat);\r\n const step = Math.max(1, Math.ceil(available.length / 5));\r\n const others = available\r\n .filter((_, i) => i % step === 0)\r\n .slice(0, 4);\r\n const checks = toBeatEntry ? [toBeatEntry, ...others] : others;\r\n return checks.map(b => ({ index: b.index, hash: b.hash, prev: b.prev, nonce: b.nonce }));\r\n })(),\r\n },\r\n });\r\n\r\n if (proof.ok) {\r\n this.status = 'active';\r\n this.totalBeats = proof.total_beats;\r\n this.lastCheckinBeat = this.latestBeat!.index;\r\n this.config.onStatusChange('active', { resynced: true });\r\n this.log('✓ Re-synced. Agent is alive again in Beat time.');\r\n }\r\n\r\n return { ok: proof.ok, beats_required: required };\r\n\r\n } catch (err: any) {\r\n this.config.onError(err, 'resync');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n // ── SPAWN ──\r\n\r\n /**\r\n * Request to spawn a child agent.\r\n * Requires sufficient accumulated beats (Temporal Gestation).\r\n */\r\n async requestSpawn(childName?: string, childHash?: string): Promise<SpawnResult> {\r\n try {\r\n // SDK-P1-05: validate childName\r\n if (childName !== undefined) {\r\n if (typeof childName !== 'string' || childName.trim().length === 0) {\r\n throw new ValidationError('childName must be a non-empty string');\r\n }\r\n if (childName.length > 64) {\r\n throw new ValidationError('childName must be 64 characters or fewer');\r\n }\r\n }\r\n\r\n const res = await this.api('POST', '/api/v1/agent/spawn', {\r\n child_name: childName,\r\n child_hash: childHash,\r\n });\r\n\r\n if (res.eligible === false) {\r\n this.log(`Gestation incomplete: ${res.progress_pct}% (need ${res.deficit} more beats)`);\r\n } else if (res.ok) {\r\n this.log(`Child spawned: ${res.child_hash?.slice(0, 16)}...`);\r\n }\r\n\r\n return res;\r\n } catch (err: any) {\r\n this.config.onError(err, 'spawn');\r\n throw err;\r\n }\r\n }\r\n\r\n // ── PHASE 2: SIGIL + HEARTBEAT + PROOF ──\r\n\r\n /** Cached lineage proof from the most recent heartbeat or SIGIL purchase */\r\n private cachedProof: LineageProof | null = null;\r\n\r\n /**\r\n * Purchase a SIGIL (cryptographic identity) for this agent.\r\n * SIGILs gate heartbeating, lineage proofs, and offline verification.\r\n * One-time purchase — cannot be re-purchased.\r\n *\r\n * @param options - SIGIL purchase options (identity_class, principal, tier, name, payment_tx, + optional metadata)\r\n *\r\n * Legacy signature (deprecated):\r\n * @param identityClass - 'narrow_task' | 'autonomous' | 'orchestrator'\r\n * @param paymentTx - Solana transaction signature or 'devnet-skip'\r\n */\r\n async purchaseSigil(optionsOrClass: SigilPurchaseOptions | IdentityClass, paymentTx?: string): Promise<SigilResult> {\r\n let body: Record<string, unknown>;\r\n\r\n if (typeof optionsOrClass === 'string') {\r\n // Legacy signature: purchaseSigil(identityClass, paymentTx)\r\n if (!optionsOrClass || !['narrow_task', 'autonomous', 'orchestrator'].includes(optionsOrClass)) {\r\n throw new ValidationError('identityClass must be narrow_task, autonomous, or orchestrator');\r\n }\r\n if (!paymentTx || typeof paymentTx !== 'string') {\r\n throw new ValidationError('paymentTx is required (Solana transaction signature or \"devnet-skip\")');\r\n }\r\n body = {\r\n identity_class: optionsOrClass,\r\n payment_tx: paymentTx,\r\n // Legacy calls without principal/tier — server will require these now\r\n // Callers must migrate to the options object form\r\n };\r\n } else {\r\n // New signature: purchaseSigil(options)\r\n const opts = optionsOrClass;\r\n if (!opts.identity_class || !['narrow_task', 'autonomous', 'orchestrator'].includes(opts.identity_class)) {\r\n throw new ValidationError('identity_class must be narrow_task, autonomous, or orchestrator');\r\n }\r\n if (!opts.principal || typeof opts.principal !== 'string') {\r\n throw new ValidationError('principal is required');\r\n }\r\n if (!opts.tier || !['sov', 'org', 'ind', 'eph', 'sbx'].includes(opts.tier)) {\r\n throw new ValidationError('tier must be one of: sov, org, ind, eph, sbx');\r\n }\r\n if (!opts.payment_tx || typeof opts.payment_tx !== 'string') {\r\n throw new ValidationError('payment_tx is required');\r\n }\r\n\r\n body = { ...opts };\r\n }\r\n\r\n try {\r\n const res = await this.api('POST', '/api/v1/sigil', body);\r\n\r\n if (res.lineage_proof) {\r\n this.cachedProof = res.lineage_proof;\r\n }\r\n\r\n const sigilStr = res.sigil?.sigil || res.sigil?.identity_class || '';\r\n this.log(`SIGIL purchased: ${sigilStr}`);\r\n this.config.onStatusChange('sigil_issued', { sigil: sigilStr });\r\n\r\n return {\r\n ok: true,\r\n sigil: res.sigil,\r\n lineage_proof: res.lineage_proof,\r\n fee: res.fee,\r\n };\r\n } catch (err: any) {\r\n this.config.onError(err, 'purchaseSigil');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Update mutable SIGIL metadata fields.\r\n * Requires a SIGIL. Cannot modify immutable fields.\r\n *\r\n * @param fields - Subset of mutable SIGIL fields to update\r\n */\r\n async updateMetadata(fields: Partial<SigilMutableFields>): Promise<MetadataUpdateResult> {\r\n if (!fields || Object.keys(fields).length === 0) {\r\n throw new ValidationError('At least one metadata field is required');\r\n }\r\n\r\n try {\r\n const res = await this.api('PATCH', '/api/v1/agent/metadata', fields);\r\n this.log(`Metadata updated: ${res.updated_fields?.join(', ') || 'unknown'}`);\r\n return {\r\n ok: true,\r\n sigil: res.sigil,\r\n generation: res.generation,\r\n updated_fields: res.updated_fields,\r\n };\r\n } catch (err: any) {\r\n this.config.onError(err, 'updateMetadata');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Send a paid heartbeat to the registry.\r\n * Requires a SIGIL. Returns a signed lineage proof.\r\n * This is the Phase 2 replacement for pulse() + checkin().\r\n *\r\n * @param paymentTx - Solana transaction signature. Omit or 'devnet-skip' on devnet.\r\n * @param globalAnchor - Optional: the global anchor index to reference.\r\n */\r\n async heartbeat(paymentTx?: string, globalAnchor?: number): Promise<HeartbeatResult> {\r\n try {\r\n const res = await this.api('POST', '/api/v1/agent/heartbeat', {\r\n payment_tx: paymentTx || 'devnet-skip',\r\n global_anchor: globalAnchor,\r\n });\r\n\r\n if (res.lineage_proof) {\r\n this.cachedProof = res.lineage_proof;\r\n }\r\n\r\n if (res.ok) {\r\n this.status = 'active';\r\n const onHb = this.config.onHeartbeat || this.config.onCheckin;\r\n if (onHb) onHb(res);\r\n this.log(`Heartbeat accepted: epoch=${res.billing_epoch}, count=${res.heartbeat_count_epoch}`);\r\n }\r\n\r\n return {\r\n ok: res.ok,\r\n lineage_proof: res.lineage_proof,\r\n heartbeat_count_epoch: res.heartbeat_count_epoch,\r\n billing_epoch: res.billing_epoch,\r\n current_beat: res.current_beat,\r\n fee: res.fee,\r\n };\r\n } catch (err: any) {\r\n this.config.onError(err, 'heartbeat');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Reissue a lineage proof. \"Reprint, not a renewal.\"\r\n * Does NOT create a new lineage event.\r\n *\r\n * @param paymentTx - Solana transaction signature. Omit or 'devnet-skip' on devnet.\r\n */\r\n async reissueProof(paymentTx?: string): Promise<{ ok: boolean; lineage_proof?: LineageProof; error?: string }> {\r\n try {\r\n const res = await this.api('POST', '/api/v1/agent/reissue-proof', {\r\n payment_tx: paymentTx || 'devnet-skip',\r\n });\r\n\r\n if (res.lineage_proof) {\r\n this.cachedProof = res.lineage_proof;\r\n }\r\n\r\n return { ok: true, lineage_proof: res.lineage_proof };\r\n } catch (err: any) {\r\n this.config.onError(err, 'reissueProof');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Get the latest cached lineage proof (no network call).\r\n * Returns null if no proof has been obtained yet.\r\n */\r\n getLatestProof(): LineageProof | null {\r\n return this.cachedProof;\r\n }\r\n\r\n /**\r\n * Get the agent's passport (alias for getLatestProof).\r\n * The passport is the agent's portable, offline-verifiable credential.\r\n * Returns null if no passport has been issued yet (requires SIGIL + heartbeat).\r\n */\r\n getPassport(): Passport | null {\r\n return this.cachedProof;\r\n }\r\n\r\n /**\r\n * Verify a lineage proof locally using the authority public key.\r\n * Offline verification — no API call, no SOL cost.\r\n *\r\n * Returns a VerificationResult object. The object is truthy when valid,\r\n * so `if (BeatAgent.verifyProofLocally(proof, key))` still works.\r\n *\r\n * @param proof - The LineageProof to verify\r\n * @param authorityPubKeyHex - 32-byte hex-encoded Ed25519 public key from /.well-known/provenonce-authority.json\r\n * @param currentBeat - Optional current global beat index (for beatsSinceHeartbeat calculation)\r\n */\r\n static verifyProofLocally(proof: LineageProof, authorityPubKeyHex: string, currentBeat?: number): VerificationResult {\r\n const now = Date.now();\r\n const expired = now > proof.valid_until;\r\n\r\n let signatureValid = false;\r\n try {\r\n // Canonical JSON (must match server's canonicalProofData)\r\n const canonical = JSON.stringify({\r\n agent_hash: proof.agent_hash,\r\n agent_public_key: proof.agent_public_key,\r\n identity_class: proof.identity_class,\r\n registered_at_beat: proof.registered_at_beat,\r\n sigil_issued_at_beat: proof.sigil_issued_at_beat,\r\n last_heartbeat_beat: proof.last_heartbeat_beat,\r\n lineage_chain_hash: proof.lineage_chain_hash,\r\n issued_at: proof.issued_at,\r\n valid_until: proof.valid_until,\r\n });\r\n\r\n // Build Ed25519 public key from hex\r\n const pubBytes = Buffer.from(authorityPubKeyHex, 'hex');\r\n if (pubBytes.length === 32) {\r\n const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');\r\n const pubKeyDer = Buffer.concat([ED25519_SPKI_PREFIX, pubBytes]);\r\n const keyObject = createPublicKey({ key: pubKeyDer, format: 'der', type: 'spki' });\r\n const sigBuffer = Buffer.from(proof.provenonce_signature, 'hex');\r\n signatureValid = verify(null, Buffer.from(canonical), keyObject, sigBuffer);\r\n }\r\n } catch {\r\n signatureValid = false;\r\n }\r\n\r\n const valid = signatureValid && !expired;\r\n const beatsSinceHeartbeat = currentBeat != null ? currentBeat - proof.last_heartbeat_beat : null;\r\n\r\n let warning: string | undefined;\r\n if (expired) {\r\n warning = 'Proof has expired. Reissue with reissueProof() or send a heartbeat.';\r\n } else if (beatsSinceHeartbeat != null && beatsSinceHeartbeat > 60) {\r\n warning = `Agent is ${beatsSinceHeartbeat} beats behind. Heartbeat may be stale.`;\r\n }\r\n\r\n return { valid, signatureValid, expired, lastHeartbeatBeat: proof.last_heartbeat_beat, beatsSinceHeartbeat, warning };\r\n }\r\n\r\n // ── STATUS ──\r\n\r\n /**\r\n * Get this agent's full beat status from the registry.\r\n */\r\n async getStatus(): Promise<AgentStatus> {\r\n try {\r\n // We need the agent hash, but we may not have it directly.\r\n // The status endpoint uses the hash from the API key verification.\r\n // For now, use the init endpoint which returns status.\r\n return await this.refreshState();\r\n } catch (err: any) {\r\n this.config.onError(err, 'status');\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Get local state (no network call).\r\n */\r\n getLocalState(): {\r\n status: string;\r\n totalBeats: number;\r\n latestBeat: number;\r\n latestHash: string;\r\n difficulty: number;\r\n globalBeat: number;\r\n chainLength: number;\r\n } {\r\n return {\r\n status: this.status,\r\n totalBeats: this.totalBeats,\r\n latestBeat: this.latestBeat?.index || 0,\r\n latestHash: this.latestBeat?.hash.slice(0, 24) + '...' || '',\r\n difficulty: this.difficulty,\r\n globalBeat: this.globalBeat,\r\n chainLength: this.chain.length,\r\n };\r\n }\r\n\r\n // ── INTERNALS ──\r\n\r\n private async syncGlobal(): Promise<void> {\r\n try {\r\n // SDK-P1-01: add timeout to syncGlobal fetch\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), 15_000);\r\n const res = await fetch(`${this.config.registryUrl}/api/v1/beat/anchor`, { signal: controller.signal });\r\n clearTimeout(timeout);\r\n const data: any = await res.json();\r\n if (data.anchor) {\r\n this.globalBeat = data.anchor.beat_index;\r\n this.globalAnchorHash = data.anchor.hash || '';\r\n if (data.anchor.difficulty) this.difficulty = data.anchor.difficulty;\r\n this.log(`Synced to global beat ${this.globalBeat} (D=${this.difficulty})`);\r\n }\r\n } catch {\r\n this.log('Failed to sync global anchor (offline mode continues)');\r\n }\r\n }\r\n\r\n private async refreshState(): Promise<any> {\r\n const res = await this.api('POST', '/api/v1/agent/init');\r\n if (res.already_initialized) {\r\n this.totalBeats = res.total_beats;\r\n this.genesisHash = res.genesis_hash;\r\n this.status = res.status as any;\r\n this.difficulty = res.difficulty || this.difficulty;\r\n this.lastCheckinBeat = res.last_checkin_beat || 0;\r\n\r\n // Restore latestBeat so pulse() can continue the chain\r\n if (!this.latestBeat && this.genesisHash) {\r\n this.latestBeat = {\r\n index: res.latest_beat || this.totalBeats,\r\n hash: res.latest_hash || this.genesisHash,\r\n prev: '0'.repeat(64),\r\n timestamp: Date.now(),\r\n };\r\n this.chain = [this.latestBeat];\r\n }\r\n }\r\n return res;\r\n }\r\n\r\n private async api(method: string, path: string, body?: any): Promise<any> {\r\n // SDK-P1-01: add 30s timeout to prevent indefinite hangs\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), 30_000);\r\n\r\n try {\r\n const res = await fetch(`${this.config.registryUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.config.apiKey}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n let data: any;\r\n try {\r\n data = await res.json();\r\n } catch {\r\n throw new NetworkError(`API error: ${res.status} non-JSON response from ${path}`);\r\n }\r\n\r\n if (!res.ok && !data.ok && !data.already_initialized && !data.eligible) {\r\n throw mapApiError(res.status, data, path);\r\n }\r\n\r\n return data;\r\n } catch (err: any) {\r\n if (err.name === 'AbortError') {\r\n throw new NetworkError(`Request timeout: ${method} ${path}`, ErrorCode.TIMEOUT);\r\n }\r\n throw err;\r\n } finally {\r\n clearTimeout(timeout);\r\n }\r\n }\r\n\r\n private log(msg: string): void {\r\n if (this.config.verbose) {\r\n console.log(`[Beat] ${msg}`);\r\n }\r\n }\r\n}\r\n\r\n// ============ STANDALONE VDF HELPER ============\r\n// For agents that want to compute beats without the full SDK\r\n\r\nexport { computeBeat };\r\n\r\n/**\r\n * Compute N sequential VDF beats.\r\n * Returns only the last beat (for lightweight usage).\r\n */\r\nexport function computeBeatsLite(\r\n startHash: string,\r\n startIndex: number,\r\n count: number,\r\n difficulty: number = 1000,\r\n anchorHash?: string,\r\n): { lastBeat: Beat; elapsed: number } {\r\n // SDK-P2: validate inputs\r\n if (!startHash || typeof startHash !== 'string') {\r\n throw new ValidationError('computeBeatsLite: startHash must be a non-empty string');\r\n }\r\n if (!Number.isInteger(count) || count < 1) {\r\n throw new ValidationError('computeBeatsLite: count must be a positive integer');\r\n }\r\n\r\n const t0 = Date.now();\r\n let prev = startHash;\r\n let lastBeat: Beat | null = null;\r\n\r\n for (let i = 0; i < count; i++) {\r\n lastBeat = computeBeat(prev, startIndex + i, difficulty, undefined, anchorHash);\r\n prev = lastBeat.hash;\r\n }\r\n\r\n return { lastBeat: lastBeat!, elapsed: Date.now() - t0 };\r\n}\r\n","/**\r\n * Provenonce SDK Error Classes\r\n *\r\n * Typed error hierarchy for programmatic error handling.\r\n * All errors extend ProvenonceError for catch-all, or catch specific\r\n * subclasses for fine-grained control:\r\n *\r\n * try {\r\n * await agent.checkin();\r\n * } catch (err) {\r\n * if (err instanceof RateLimitError) {\r\n * await sleep(err.retryAfterMs);\r\n * } else if (err instanceof FrozenError) {\r\n * await agent.resync();\r\n * } else if (err instanceof AuthError) {\r\n * console.error('Bad API key');\r\n * }\r\n * }\r\n */\r\n\r\n/** Error codes for programmatic switching */\r\nexport enum ErrorCode {\r\n // Validation\r\n VALIDATION = 'VALIDATION',\r\n\r\n // Auth\r\n AUTH_INVALID = 'AUTH_INVALID',\r\n AUTH_MISSING = 'AUTH_MISSING',\r\n\r\n // Rate limiting\r\n RATE_LIMITED = 'RATE_LIMITED',\r\n\r\n // Agent state\r\n AGENT_FROZEN = 'AGENT_FROZEN',\r\n AGENT_NOT_INITIALIZED = 'AGENT_NOT_INITIALIZED',\r\n AGENT_WRONG_STATE = 'AGENT_WRONG_STATE',\r\n\r\n // Not found\r\n NOT_FOUND = 'NOT_FOUND',\r\n\r\n // Network / server\r\n NETWORK_ERROR = 'NETWORK_ERROR',\r\n TIMEOUT = 'TIMEOUT',\r\n SERVER_ERROR = 'SERVER_ERROR',\r\n}\r\n\r\n/** Base error class for all Provenonce SDK errors */\r\nexport class ProvenonceError extends Error {\r\n /** Machine-readable error code */\r\n readonly code: ErrorCode;\r\n\r\n /** HTTP status code (if from an API response) */\r\n readonly statusCode?: number;\r\n\r\n /** Additional context */\r\n readonly details?: Record<string, unknown>;\r\n\r\n constructor(\r\n message: string,\r\n code: ErrorCode,\r\n statusCode?: number,\r\n details?: Record<string, unknown>,\r\n ) {\r\n super(message);\r\n this.name = 'ProvenonceError';\r\n this.code = code;\r\n this.statusCode = statusCode;\r\n this.details = details;\r\n // Fix prototype chain for instanceof checks\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\n/** Thrown when input validation fails (bad config, invalid args) */\r\nexport class ValidationError extends ProvenonceError {\r\n constructor(message: string, details?: Record<string, unknown>) {\r\n super(message, ErrorCode.VALIDATION, undefined, details);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n\r\n/** Thrown on 401/403 — bad or missing API key */\r\nexport class AuthError extends ProvenonceError {\r\n constructor(\r\n message: string,\r\n code: ErrorCode.AUTH_INVALID | ErrorCode.AUTH_MISSING = ErrorCode.AUTH_INVALID,\r\n statusCode?: number,\r\n ) {\r\n super(message, code, statusCode);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\n/** Thrown on 429 — rate limit exceeded */\r\nexport class RateLimitError extends ProvenonceError {\r\n /** Milliseconds until the rate limit resets (if provided by server) */\r\n readonly retryAfterMs?: number;\r\n\r\n constructor(message: string, statusCode: number = 429, retryAfterMs?: number) {\r\n super(message, ErrorCode.RATE_LIMITED, statusCode);\r\n this.name = 'RateLimitError';\r\n this.retryAfterMs = retryAfterMs;\r\n }\r\n}\r\n\r\n/** Thrown when an agent is frozen and cannot perform the requested action */\r\nexport class FrozenError extends ProvenonceError {\r\n constructor(message: string = 'Agent is frozen. Use resync() to re-establish provenance.') {\r\n super(message, ErrorCode.AGENT_FROZEN);\r\n this.name = 'FrozenError';\r\n }\r\n}\r\n\r\n/** Thrown when the agent is in the wrong state for the requested action */\r\nexport class StateError extends ProvenonceError {\r\n /** The agent's current state */\r\n readonly currentState: string;\r\n\r\n constructor(message: string, currentState: string, code: ErrorCode = ErrorCode.AGENT_WRONG_STATE) {\r\n super(message, code);\r\n this.name = 'StateError';\r\n this.currentState = currentState;\r\n }\r\n}\r\n\r\n/** Thrown on 404 — agent or resource not found */\r\nexport class NotFoundError extends ProvenonceError {\r\n constructor(message: string, statusCode: number = 404) {\r\n super(message, ErrorCode.NOT_FOUND, statusCode);\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\n/** Thrown on network failures — non-JSON responses, fetch errors, timeouts */\r\nexport class NetworkError extends ProvenonceError {\r\n constructor(message: string, code: ErrorCode.NETWORK_ERROR | ErrorCode.TIMEOUT = ErrorCode.NETWORK_ERROR) {\r\n super(message, code);\r\n this.name = 'NetworkError';\r\n }\r\n}\r\n\r\n/** Thrown on 5xx — unexpected server errors */\r\nexport class ServerError extends ProvenonceError {\r\n constructor(message: string, statusCode: number = 500) {\r\n super(message, ErrorCode.SERVER_ERROR, statusCode);\r\n this.name = 'ServerError';\r\n }\r\n}\r\n\r\n/**\r\n * Map an HTTP response + parsed body to the appropriate error class.\r\n * Used internally by the SDK to convert API failures to typed errors.\r\n */\r\nexport function mapApiError(\r\n statusCode: number,\r\n body: { error?: string; retry_after_ms?: number },\r\n path: string,\r\n): ProvenonceError {\r\n const msg = typeof body.error === 'string' ? body.error : `API error ${statusCode}`;\r\n\r\n if (statusCode === 401 || statusCode === 403) {\r\n const code = statusCode === 401 ? ErrorCode.AUTH_MISSING : ErrorCode.AUTH_INVALID;\r\n return new AuthError(msg, code, statusCode);\r\n }\r\n\r\n if (statusCode === 429) {\r\n const retryAfter = typeof body.retry_after_ms === 'number' ? body.retry_after_ms : undefined;\r\n return new RateLimitError(msg, statusCode, retryAfter);\r\n }\r\n\r\n if (statusCode === 404) {\r\n return new NotFoundError(msg, statusCode);\r\n }\r\n\r\n if (statusCode >= 500) {\r\n return new ServerError(msg, statusCode);\r\n }\r\n\r\n // Check for specific error patterns in the message\r\n const lowerMsg = msg.toLowerCase();\r\n if (lowerMsg.includes('frozen')) {\r\n return new FrozenError(msg);\r\n }\r\n\r\n // Generic client error\r\n return new ProvenonceError(msg, ErrorCode.SERVER_ERROR, statusCode);\r\n}\r\n"],"mappings":"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","names":["ErrorCode","res","data"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/beat-sdk.ts","../src/errors.ts"],"sourcesContent":["export { BeatAgent, computeBeat, computeBeatsLite, register, generateWalletKeypair } from './beat-sdk';\nexport type {\n BeatAgentConfig,\n Beat,\n CheckinResult,\n SpawnResult,\n AgentStatus,\n RegisterOptions,\n RegistrationResult,\n WalletInfo,\n // Phase 2 types\n IdentityClass,\n LineageProof,\n Passport,\n SigilResult,\n HeartbeatResult,\n // SIGIL Namespace v0.4 types\n SigilTier,\n Substrate,\n SubstrateProvider,\n Capability,\n SigilProtocol,\n ComplianceRegime,\n SigilPurchaseOptions,\n SigilMutableFields,\n MetadataUpdateResult,\n VerificationResult,\n} from './beat-sdk';\n\nexport {\n ProvenonceError,\n ValidationError,\n AuthError,\n RateLimitError,\n FrozenError,\n StateError,\n NotFoundError,\n NetworkError,\n ServerError,\n ErrorCode,\n} from './errors';\n","/**\n * ═══════════════════════════════════════════════════════════\n * PROVENONCE BEAT SDK — Agent Heartbeat Client\n * ═══════════════════════════════════════════════════════════\n * \n * \"NIST tells you what time it is.\n * Provenonce tells the agent at what speed it is allowed to exist.\"\n * \n * Usage:\n * \n * import { BeatAgent } from './beat-sdk';\n * \n * const agent = new BeatAgent({\n * apiKey: 'pvn_...',\n * registryUrl: 'https://provenonce.io',\n * });\n * \n * await agent.init(); // Birth in Beat time\n * await agent.pulse(50); // Compute 50 beats\n * await agent.checkin(); // Report to registry\n * \n * // Or run the autonomous heartbeat:\n * agent.startHeartbeat(); // Computes + checks in continuously\n * // ... do your agent work ...\n * agent.stopHeartbeat();\n * \n * ═══════════════════════════════════════════════════════════\n */\n\nimport { createHash, generateKeyPairSync, sign, verify, createPrivateKey, createPublicKey } from 'crypto';\nimport {\n ValidationError,\n AuthError,\n RateLimitError,\n FrozenError,\n StateError,\n NetworkError,\n ServerError,\n mapApiError,\n ErrorCode,\n} from './errors';\n\n// ============ PHASE 2 TYPES ============\n\n/** SIGIL identity class — determines tier pricing and heartbeat volume caps */\nexport type IdentityClass = 'narrow_task' | 'autonomous' | 'orchestrator';\n\n/** SIGIL trust governance tier — orthogonal to identity_class (fee axis) */\nexport type SigilTier = 'sov' | 'org' | 'ind' | 'eph' | 'sbx';\n\n/** Substrate — what the agent runs on */\nexport type Substrate = 'frontier' | 'open' | 'local' | 'symbolic' | 'hybrid' | 'human';\n\n/** Substrate provider */\nexport type SubstrateProvider = 'anthropic' | 'openai' | 'google' | 'meta' | 'mistral' | 'xai' | 'cohere' | 'deepseek' | 'custom';\n\n/** Capability — what the agent primarily does */\nexport type Capability = 'analyst' | 'executor' | 'orchestrator' | 'guardian' | 'retriever' | 'renderer' | 'witness';\n\n/** Protocol — how to reach the agent */\nexport type SigilProtocol = 'http' | 'grpc' | 'websocket' | 'mcp' | 'a2a' | 'custom';\n\n/** Compliance regime */\nexport type ComplianceRegime = 'gdpr' | 'pdpa' | 'hipaa' | 'sox' | 'aisi' | 'none' | 'custom';\n\n/**\n * Ed25519-signed lineage proof — portable, offline-verifiable credential.\n * Also known as the agent's \"passport\" — a cryptographic proof of identity\n * that can be verified offline without any API call or SOL cost.\n */\nexport interface LineageProof {\n agent_hash: string;\n agent_public_key: string | null;\n identity_class: IdentityClass;\n registered_at_beat: number;\n sigil_issued_at_beat: number | null;\n last_heartbeat_beat: number;\n lineage_chain_hash: string;\n issued_at: number;\n valid_until: number;\n provenonce_signature: string;\n}\n\n/** Passport = LineageProof. The agent's portable, offline-verifiable credential. */\nexport type Passport = LineageProof;\n\n/** Options for purchasing a SIGIL with full namespace */\nexport interface SigilPurchaseOptions {\n identity_class: IdentityClass;\n principal: string;\n tier: SigilTier;\n name?: string; // \"auto\" or custom name\n payment_tx: string;\n // Optional initial metadata\n substrate?: Substrate;\n substrate_provider?: SubstrateProvider;\n substrate_model?: string;\n capability?: Capability;\n capability_scope?: string;\n tools?: string[];\n modality_input?: string[];\n modality_output?: string[];\n protocol?: SigilProtocol;\n endpoint?: string;\n compliance_regime?: ComplianceRegime;\n}\n\n/** Mutable SIGIL metadata fields for PATCH updates */\nexport interface SigilMutableFields {\n substrate?: Substrate;\n substrate_provider?: SubstrateProvider;\n substrate_model?: string;\n capability?: Capability;\n capability_scope?: string;\n generation_trigger?: string;\n tools?: string[];\n modality_input?: string[];\n modality_output?: string[];\n protocol?: SigilProtocol;\n endpoint?: string;\n compliance_regime?: ComplianceRegime;\n}\n\n/** Result from purchasing a SIGIL (Structured Identity Governance and Intelligent Lookup) */\nexport interface SigilResult {\n ok: boolean;\n sigil?: {\n sigil: string; // Full SIGIL string: name*principal*tier\n sigil_name: string;\n principal: string;\n tier: SigilTier;\n identity_class: IdentityClass;\n issued_at_beat: number;\n birth_tx: string | null;\n explorer_url: string | null;\n };\n lineage_proof?: LineageProof;\n fee?: {\n amount_sol: number;\n amount_lamports: number;\n payment_tx: string | null;\n };\n error?: string;\n}\n\n/** Result from updating mutable SIGIL metadata */\nexport interface MetadataUpdateResult {\n ok: boolean;\n sigil?: string;\n generation?: number;\n updated_fields?: string[];\n error?: string;\n}\n\n/** Result from offline lineage proof verification */\nexport interface VerificationResult {\n /** Overall validity: signature is valid AND not expired */\n valid: boolean;\n /** Ed25519 signature verification passed */\n signatureValid: boolean;\n /** Proof has passed its valid_until timestamp */\n expired: boolean;\n /** The beat index of the agent's last heartbeat */\n lastHeartbeatBeat: number;\n /** Beats elapsed since last heartbeat (null if currentBeat not provided) */\n beatsSinceHeartbeat: number | null;\n /** Human-readable warning if proof is expired or stale */\n warning?: string;\n}\n\n/** Result from a paid heartbeat */\nexport interface HeartbeatResult {\n ok: boolean;\n lineage_proof?: LineageProof;\n heartbeat_count_epoch?: number;\n billing_epoch?: number;\n current_beat?: number;\n fee?: {\n amount_sol: number;\n amount_lamports: number;\n tier: number;\n payment_tx: string | null;\n };\n error?: string;\n}\n\n// ============ VDF ENGINE (LOCAL) ============\n\nexport interface Beat {\n index: number;\n hash: string;\n prev: string;\n timestamp: number;\n nonce?: string;\n anchor_hash?: string;\n}\n\nfunction computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string, anchorHash?: string): Beat {\n const timestamp = Date.now();\n\n const seed = anchorHash\n ? `${prevHash}:${beatIndex}:${nonce || ''}:${anchorHash}`\n : `${prevHash}:${beatIndex}:${nonce || ''}`;\n\n let current = createHash('sha256')\n .update(seed)\n .digest('hex');\n\n for (let i = 0; i < difficulty; i++) {\n current = createHash('sha256')\n .update(current)\n .digest('hex');\n }\n\n return { index: beatIndex, hash: current, prev: prevHash, timestamp, nonce, anchor_hash: anchorHash };\n}\n\n// ============ SDK RESULT TYPES ============\n\n/** Result from a check-in submission */\nexport interface CheckinResult {\n ok: boolean;\n total_beats: number;\n beats_accepted: number;\n global_beat: number;\n status?: string;\n beats_behind?: number;\n}\n\n/** Result from a spawn request */\nexport interface SpawnResult {\n ok: boolean;\n eligible: boolean;\n child_hash?: string;\n progress_pct?: number;\n deficit?: number;\n}\n\n/** Agent status from the registry */\nexport interface AgentStatus {\n already_initialized: boolean;\n total_beats: number;\n genesis_hash: string;\n status: string;\n genesis?: { hash: string; prev: string; timestamp: number };\n difficulty?: number;\n}\n\n// ============ WALLET KEYPAIR GENERATION ============\n\n// DER prefix for Ed25519 PKCS8 private keys (16 bytes)\nconst ED25519_PKCS8_PREFIX = Buffer.from('302e020100300506032b657004220420', 'hex');\n\n/**\n * Generate an Ed25519 keypair for agent wallet identity.\n * Returns hex-encoded raw keys (32 bytes each).\n * Uses Node.js built-in crypto — zero external dependencies.\n */\nexport function generateWalletKeypair(): { publicKey: string; secretKey: string } {\n const { publicKey, privateKey } = generateKeyPairSync('ed25519');\n const pubRaw = publicKey.export({ type: 'spki', format: 'der' }).subarray(12); // 32 bytes\n const privRaw = privateKey.export({ type: 'pkcs8', format: 'der' }).subarray(16); // 32 bytes\n return {\n publicKey: Buffer.from(pubRaw).toString('hex'),\n secretKey: Buffer.from(privRaw).toString('hex'),\n };\n}\n\n/**\n * Sign a message with an Ed25519 private key (hex-encoded 32-byte seed).\n * Returns hex-encoded signature (64 bytes).\n */\nfunction signMessage(secretKeyHex: string, message: string): string {\n const privRaw = Buffer.from(secretKeyHex, 'hex');\n const privKeyDer = Buffer.concat([ED25519_PKCS8_PREFIX, privRaw]);\n const keyObject = createPrivateKey({ key: privKeyDer, format: 'der', type: 'pkcs8' });\n const sig = sign(null, Buffer.from(message), keyObject);\n return Buffer.from(sig).toString('hex');\n}\n\n// ============ REGISTRATION ============\n\n/** Wallet info returned from root registration */\nexport interface WalletInfo {\n /** Hex-encoded 32-byte Ed25519 public key (Solana self-custody only, empty otherwise) */\n public_key: string;\n /** Hex-encoded 32-byte Ed25519 secret seed — SAVE THIS for future fee signing (Solana self-custody only) */\n secret_key: string;\n /** Solana-compatible base58 address (Solana wallets only) */\n solana_address?: string;\n /** The wallet address (base58 for Solana, 0x for Ethereum) */\n address: string;\n /** Wallet chain: 'solana' or 'ethereum' */\n chain: string;\n}\n\n/** Result from registering an agent */\nexport interface RegistrationResult {\n hash: string;\n api_key: string;\n secret: string;\n type: 'root' | 'agent';\n parent: string | null;\n depth: number;\n name: string;\n metadata?: Record<string, unknown> | null;\n /** @deprecated No Solana write at registration (D-65). Will be null. */\n signature?: string | null;\n /** @deprecated No Solana write at registration (D-65). Will be null. */\n explorer_url?: string | null;\n /** Wallet chain: 'solana', 'ethereum', or null (no wallet) */\n wallet_chain?: string | null;\n beat?: { genesis_hash: string; difficulty: number; status: string };\n /** Wallet info — only present for root agents with wallets */\n wallet?: WalletInfo;\n /** Next steps after registration */\n _next_steps?: { sigil?: string; heartbeat?: string };\n}\n\n/** Options for the register() function */\nexport interface RegisterOptions {\n registryUrl?: string;\n parentHash?: string;\n parentApiKey?: string;\n registrationSecret?: string;\n /** Single-use registration token from POST /register/token or POST /register/email/verify */\n registrationToken?: string;\n /** Admin-minted invite token */\n registrationInvite?: string;\n /** Hex-encoded 32-byte Ed25519 secret seed (bring-your-own Solana key) */\n walletSecretKey?: string;\n /** Wallet model: 'self-custody' (Model A) or 'operator' (Model B). Must be set explicitly to opt in. */\n walletModel?: 'self-custody' | 'operator';\n /** Wallet chain: 'solana' (default when wallet is used) or 'ethereum' (D-63) */\n walletChain?: 'solana' | 'ethereum';\n /** Wallet address for Ethereum bring-your-own (0x + 40 hex chars) */\n walletAddress?: string;\n /** Async function to sign a message with an Ethereum wallet (EIP-191 personal_sign). Returns 0x-prefixed 65-byte hex sig. */\n walletSignFn?: (message: string) => Promise<string>;\n /** Operator's Solana wallet address (base58). Required when walletModel='operator'. */\n operatorWalletAddress?: string;\n /** Function to sign a message with the operator's Solana wallet. Required when walletModel='operator'. */\n operatorSignFn?: (message: string) => Promise<string>;\n /** Optional agent metadata (arbitrary JSON object, max 4KB). Returned in /verify and /status. */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Register a new agent on the Provenonce registry.\n *\n * With registration token (from /register/token or email verification):\n * const creds = await register('my-agent', {\n * registryUrl: '...',\n * registrationToken: '<token-from-email-verify>',\n * });\n *\n * No wallet (default, single-phase):\n * const creds = await register('my-agent', { registryUrl: '...' });\n *\n * Solana self-custody wallet (Model A, two-phase):\n * const creds = await register('my-org', {\n * registryUrl: '...',\n * walletModel: 'self-custody',\n * });\n * // creds.wallet.secret_key = hex secret (SAVE THIS)\n * // creds.wallet.address = base58 Solana address\n *\n * Solana with existing key:\n * const creds = await register('my-org', {\n * registryUrl: '...',\n * walletSecretKey: '<hex-encoded-32-byte-seed>',\n * });\n *\n * Ethereum bring-your-own (two-phase):\n * const creds = await register('my-org', {\n * registryUrl: '...',\n * walletChain: 'ethereum',\n * walletAddress: '0x...',\n * walletSignFn: (msg) => wallet.signMessage(msg),\n * });\n *\n * Solana operator (Model B, two-phase):\n * const creds = await register('my-org', {\n * registryUrl: '...',\n * walletModel: 'operator',\n * operatorWalletAddress: '<base58>',\n * operatorSignFn: (msg) => signWithWallet(msg),\n * });\n *\n * Child agent (no wallet):\n * const creds = await register('worker-1', {\n * registryUrl: '...',\n * parentHash: parentCreds.hash,\n * parentApiKey: parentCreds.api_key,\n * });\n */\nexport async function register(\n name: string,\n options?: RegisterOptions,\n): Promise<RegistrationResult> {\n // SDK-P1-07/P1-08: validate inputs\n if (!name || typeof name !== 'string' || name.trim().length === 0) {\n throw new ValidationError('name is required (must be a non-empty string)');\n }\n if (name.length > 64) {\n throw new ValidationError('name must be 64 characters or fewer');\n }\n\n const url = options?.registryUrl || 'https://provenonce.io';\n try {\n new URL(url);\n } catch {\n throw new ValidationError('registryUrl is not a valid URL');\n }\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\n if (options?.registrationSecret) {\n headers['x-registration-secret'] = options.registrationSecret;\n }\n if (options?.registrationToken) {\n headers['x-registration-token'] = options.registrationToken;\n }\n if (options?.registrationInvite) {\n headers['x-registration-invite'] = options.registrationInvite;\n }\n\n // ===== CHILD REGISTRATION (no wallet, single-phase) =====\n if (options?.parentHash) {\n if (options.parentApiKey) {\n headers['Authorization'] = `Bearer ${options.parentApiKey}`;\n }\n\n const res = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, parent: options.parentHash, ...(options.metadata && { metadata: options.metadata }) }),\n });\n\n let data: RegistrationResult & { error?: string };\n try {\n data = await res.json() as RegistrationResult & { error?: string };\n } catch {\n throw new NetworkError(`Registration failed: ${res.status} ${res.statusText} (non-JSON response)`);\n }\n if (!res.ok) throw mapApiError(res.status, data, '/api/v1/register');\n return data;\n }\n\n // ===== ETHEREUM BRING-YOUR-OWN (D-63, two-phase) =====\n if (options?.walletChain === 'ethereum') {\n if (!options.walletAddress || !options.walletSignFn) {\n throw new ValidationError('Ethereum registration requires walletAddress and walletSignFn');\n }\n\n if (!/^0x[0-9a-fA-F]{40}$/.test(options.walletAddress)) {\n throw new ValidationError('walletAddress must be a valid Ethereum address (0x + 40 hex chars)');\n }\n\n // Phase 1: Get challenge nonce from server\n const challengeRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, action: 'challenge', wallet_chain: 'ethereum' }),\n });\n\n let challengeData: { nonce?: string; error?: string };\n try {\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\n } catch {\n throw new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\n }\n if (!challengeRes.ok || !challengeData.nonce) {\n throw mapApiError(challengeRes.status, challengeData, '/api/v1/register');\n }\n\n // Phase 2: Sign with Ethereum wallet (EIP-191 personal_sign)\n const nonce = challengeData.nonce;\n const message = `provenonce-register-ethereum:${nonce}:${options.walletAddress}:${name}`;\n const walletSignature = await options.walletSignFn(message);\n\n const registerRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n name,\n wallet_chain: 'ethereum',\n wallet_address: options.walletAddress,\n wallet_signature: walletSignature,\n wallet_nonce: nonce,\n ...(options.metadata && { metadata: options.metadata }),\n }),\n });\n\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; chain?: string } };\n try {\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; chain?: string } };\n } catch {\n throw new NetworkError(`Ethereum registration failed: ${registerRes.status} (non-JSON response)`);\n }\n if (!registerRes.ok) throw mapApiError(registerRes.status, data, '/api/v1/register');\n\n // Ethereum: wallet has address only (no keypair — user keeps custody externally)\n data.wallet = {\n public_key: '',\n secret_key: '',\n address: data.wallet?.address || options.walletAddress,\n chain: 'ethereum',\n };\n\n return data;\n }\n\n // ===== MODEL B: SOLANA OPERATOR WALLET REGISTRATION (two-phase) =====\n if (options?.walletModel === 'operator') {\n if (!options.operatorWalletAddress || !options.operatorSignFn) {\n throw new ValidationError('Operator registration requires operatorWalletAddress and operatorSignFn');\n }\n\n // Phase 1: Get challenge nonce from server\n const challengeRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, action: 'challenge', wallet_model: 'operator' }),\n });\n\n let challengeData: { nonce?: string; error?: string };\n try {\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\n } catch {\n throw new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\n }\n if (!challengeRes.ok || !challengeData.nonce) {\n throw mapApiError(challengeRes.status, challengeData, '/api/v1/register');\n }\n\n // Phase 2: Operator signs challenge and register\n const nonce = challengeData.nonce;\n const message = `provenonce-register-operator:${nonce}:${options.operatorWalletAddress}:${name}`;\n const walletSignature = await options.operatorSignFn(message);\n\n const registerRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n name,\n wallet_model: 'operator',\n operator_wallet_address: options.operatorWalletAddress,\n wallet_signature: walletSignature,\n wallet_nonce: nonce,\n ...(options.metadata && { metadata: options.metadata }),\n }),\n });\n\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\n try {\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\n } catch {\n throw new NetworkError(`Operator registration failed: ${registerRes.status} (non-JSON response)`);\n }\n if (!registerRes.ok) throw mapApiError(registerRes.status, data, '/api/v1/register');\n\n // Model B: wallet has address only (no secret_key/public_key — operator keeps custody)\n const addr = data.wallet?.address || data.wallet?.solana_address || options.operatorWalletAddress;\n data.wallet = {\n public_key: '',\n secret_key: '',\n solana_address: addr,\n address: addr,\n chain: 'solana',\n };\n\n return data;\n }\n\n // ===== MODEL A: SOLANA SELF-CUSTODY WALLET REGISTRATION (opt-in, two-phase) =====\n if (options?.walletModel === 'self-custody' || options?.walletSecretKey) {\n // Generate or use provided wallet keypair\n let walletKeys: { publicKey: string; secretKey: string };\n if (options?.walletSecretKey) {\n // Derive public key from provided secret\n const privRaw = Buffer.from(options.walletSecretKey, 'hex');\n const privKeyDer = Buffer.concat([ED25519_PKCS8_PREFIX, privRaw]);\n const keyObject = createPrivateKey({ key: privKeyDer, format: 'der', type: 'pkcs8' });\n const pubRaw = keyObject.export({ type: 'spki', format: 'der' }).subarray(12);\n walletKeys = {\n publicKey: Buffer.from(pubRaw).toString('hex'),\n secretKey: options.walletSecretKey,\n };\n } else {\n walletKeys = generateWalletKeypair();\n }\n\n // Phase 1: Get challenge nonce from server\n const challengeRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, action: 'challenge' }),\n });\n\n let challengeData: { nonce?: string; error?: string };\n try {\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\n } catch {\n const err = new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\n throw err;\n }\n if (!challengeRes.ok || !challengeData.nonce) {\n // Attach wallet keys so caller can retry with the same keypair\n const err = mapApiError(challengeRes.status, challengeData, '/api/v1/register');\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\n throw err;\n }\n\n // Phase 2: Sign challenge and register\n const nonce = challengeData.nonce;\n const message = `provenonce-register:${nonce}:${walletKeys.publicKey}:${name}`;\n const walletSignature = signMessage(walletKeys.secretKey, message);\n\n const registerRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n name,\n wallet_public_key: walletKeys.publicKey,\n wallet_signature: walletSignature,\n wallet_nonce: nonce,\n ...(options?.metadata && { metadata: options.metadata }),\n }),\n });\n\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\n try {\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\n } catch {\n // Attach wallet keys so caller can retry with the same keypair\n const err = new NetworkError(`Registration failed: ${registerRes.status} (non-JSON response)`);\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\n throw err;\n }\n if (!registerRes.ok) {\n // Attach wallet keys so caller can retry with the same keypair via walletSecretKey option\n const err = mapApiError(registerRes.status, data, '/api/v1/register');\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\n throw err;\n }\n\n // Attach the wallet keys (secret is client-side only, never sent to server)\n const addr = data.wallet?.address || data.wallet?.solana_address || '';\n data.wallet = {\n public_key: walletKeys.publicKey,\n secret_key: walletKeys.secretKey,\n solana_address: addr,\n address: addr,\n chain: 'solana',\n };\n\n return data;\n }\n\n // ===== NO-WALLET REGISTRATION (D-62 default, single-phase) =====\n\n const res = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, ...(options?.metadata && { metadata: options.metadata }) }),\n });\n\n let data: RegistrationResult & { error?: string };\n try {\n data = await res.json() as RegistrationResult & { error?: string };\n } catch {\n throw new NetworkError(`Registration failed: ${res.status} ${res.statusText} (non-JSON response)`);\n }\n if (!res.ok) throw mapApiError(res.status, data, '/api/v1/register');\n return data;\n}\n\n// ============ SDK CONFIG ============\n\nexport interface BeatAgentConfig {\n /** API key from registration (pvn_...) */\n apiKey: string;\n\n /** Provenonce registry URL */\n registryUrl: string;\n\n /** @deprecated Use heartbeatIntervalSec. Beats to compute per pulse (default: 10) */\n beatsPerPulse?: number;\n\n /** @deprecated Use heartbeatIntervalSec. Seconds between automatic check-ins (default: 300 = 5min) */\n checkinIntervalSec?: number;\n\n /** Seconds between automatic heartbeats (default: 300 = 5min). Replaces checkinIntervalSec. */\n heartbeatIntervalSec?: number;\n\n /** @deprecated VDF pulse callback. No longer used in Phase 2. */\n onPulse?: (beats: Beat[], totalBeats: number) => void;\n\n /** @deprecated Use onHeartbeat. Callback when check-in completes. */\n onCheckin?: (result: CheckinResult) => void;\n\n /** Callback when heartbeat completes (Phase 2) */\n onHeartbeat?: (result: HeartbeatResult) => void;\n\n /** Callback on error */\n onError?: (error: Error, context: string) => void;\n\n /** Callback when status changes */\n onStatusChange?: (status: string, details: Record<string, unknown>) => void;\n\n /** Enable verbose logging */\n verbose?: boolean;\n}\n\n// ============ BEAT AGENT ============\n\nexport class BeatAgent {\n private config: Required<BeatAgentConfig>;\n private chain: Beat[] = [];\n private difficulty: number = 1000;\n private genesisHash: string = '';\n private latestBeat: Beat | null = null;\n private totalBeats: number = 0;\n private lastCheckinBeat: number = 0;\n private status: 'uninitialized' | 'active' | 'frozen' | 'revoked' = 'uninitialized';\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n private globalBeat: number = 0;\n private globalAnchorHash: string = '';\n\n constructor(config: BeatAgentConfig) {\n // SDK-P1-08: validate required config fields\n if (!config.apiKey || typeof config.apiKey !== 'string') {\n throw new ValidationError('BeatAgentConfig.apiKey is required (must be a non-empty string)');\n }\n if (!config.registryUrl || typeof config.registryUrl !== 'string') {\n throw new ValidationError('BeatAgentConfig.registryUrl is required (must be a non-empty string)');\n }\n // SDK-P1-07: validate registryUrl is a valid URL\n try {\n new URL(config.registryUrl);\n } catch {\n throw new ValidationError('BeatAgentConfig.registryUrl is not a valid URL');\n }\n\n // SDK-P2: validate optional numeric config\n if (config.beatsPerPulse !== undefined && (!Number.isInteger(config.beatsPerPulse) || config.beatsPerPulse < 1 || config.beatsPerPulse > 10000)) {\n throw new ValidationError('BeatAgentConfig.beatsPerPulse must be an integer between 1 and 10000');\n }\n if (config.checkinIntervalSec !== undefined && (!Number.isFinite(config.checkinIntervalSec) || config.checkinIntervalSec < 10 || config.checkinIntervalSec > 86400)) {\n throw new ValidationError('BeatAgentConfig.checkinIntervalSec must be between 10 and 86400');\n }\n\n this.config = {\n beatsPerPulse: 10,\n checkinIntervalSec: 300,\n heartbeatIntervalSec: 300,\n onPulse: () => {},\n onCheckin: () => {},\n onHeartbeat: () => {},\n onError: () => {},\n onStatusChange: () => {},\n verbose: false,\n ...config,\n };\n }\n\n // ── INITIALIZATION ──\n\n /**\n * Initialize the agent's Beat chain.\n * This is the agent's \"birth\" in Logical Time.\n * Must be called once before computing beats.\n */\n async init(): Promise<{ ok: boolean; genesis?: string; error?: string }> {\n try {\n this.log('Initializing Beat chain...');\n\n const res = await this.api('POST', '/api/v1/agent/init');\n\n if (res.genesis) {\n this.genesisHash = res.genesis.hash;\n this.difficulty = res.difficulty || 1000;\n this.latestBeat = {\n index: 0,\n hash: res.genesis.hash,\n prev: res.genesis.prev,\n timestamp: res.genesis.timestamp,\n };\n this.chain = [this.latestBeat];\n this.totalBeats = 0;\n this.status = 'active';\n this.config.onStatusChange('active', { genesis: this.genesisHash });\n this.log(`Born in Beat time. Genesis: ${this.genesisHash.slice(0, 16)}...`);\n } else if (res.already_initialized) {\n // Restore from existing state\n this.genesisHash = res.genesis_hash;\n this.totalBeats = res.total_beats;\n this.status = res.status as any;\n this.log(`Already initialized. Restoring state (${res.total_beats} beats).`);\n \n // Fetch full state to get latest hash\n await this.refreshState();\n }\n\n // Sync global anchor\n await this.syncGlobal();\n\n return { ok: true, genesis: this.genesisHash };\n\n } catch (err: any) {\n this.config.onError(err, 'init');\n return { ok: false, error: err.message };\n }\n }\n\n // ── PULSE (COMPUTE BEATS) ──\n\n /**\n * @deprecated Phase 2: VDF computation retired (D-68). Payment is the liveness mechanism.\n * Use heartbeat() instead. This method will be removed in the next major version.\n *\n * Compute N beats locally (VDF hash chain).\n */\n pulse(count?: number): Beat[] {\n console.warn('[Provenonce SDK] pulse() is deprecated. Use heartbeat() instead (Phase 2).');\n if (this.status === 'frozen') {\n throw new FrozenError('Cannot pulse: agent is frozen. Use resync() to re-establish provenance.');\n }\n if (this.status !== 'active') {\n throw new StateError(`Cannot pulse: agent is ${this.status}.`, this.status);\n }\n // SDK-P2: validate count param\n if (count !== undefined && (!Number.isInteger(count) || count < 1 || count > 10000)) {\n throw new ValidationError('pulse count must be an integer between 1 and 10000');\n }\n return this.computeBeats(count);\n }\n\n /** Internal beat computation — no status check. Used by both pulse() and resync(). */\n private computeBeats(count?: number, onProgress?: (computed: number, total: number) => void): Beat[] {\n const n = count || this.config.beatsPerPulse;\n\n if (!this.latestBeat) {\n throw new StateError('Beat chain not initialized. Call init() first.', 'uninitialized', ErrorCode.AGENT_NOT_INITIALIZED);\n }\n\n const newBeats: Beat[] = [];\n let prevHash = this.latestBeat.hash;\n let startIndex = this.latestBeat.index + 1;\n\n const t0 = Date.now();\n // SDK-P2: report progress every 10% of beats\n const progressInterval = Math.max(1, Math.floor(n / 10));\n\n for (let i = 0; i < n; i++) {\n const beat = computeBeat(prevHash, startIndex + i, this.difficulty, undefined, this.globalAnchorHash || undefined);\n newBeats.push(beat);\n prevHash = beat.hash;\n if (onProgress && (i + 1) % progressInterval === 0) {\n onProgress(i + 1, n);\n }\n }\n\n const elapsed = Date.now() - t0;\n\n // Update state\n this.chain.push(...newBeats);\n this.latestBeat = newBeats[newBeats.length - 1];\n this.totalBeats += n;\n\n // Keep chain bounded (only last 1000 beats in memory)\n if (this.chain.length > 1000) {\n this.chain = this.chain.slice(-500);\n }\n\n this.config.onPulse(newBeats, this.totalBeats);\n this.log(`Pulse: ${n} beats in ${elapsed}ms (${(elapsed / n).toFixed(1)}ms/beat, D=${this.difficulty})`);\n\n return newBeats;\n }\n\n // ── CHECK-IN ──\n\n /**\n * @deprecated Phase 2: VDF check-in retired (D-68). Use heartbeat() instead.\n * This method will be removed in the next major version.\n */\n async checkin(): Promise<{ ok: boolean; total_beats?: number; error?: string }> {\n console.warn('[Provenonce SDK] checkin() is deprecated. Use heartbeat() instead (Phase 2).');\n // SDK-P1-02: fix guard to compare beat indices, not totalBeats vs lastCheckinBeat\n if (!this.latestBeat || this.latestBeat.index <= this.lastCheckinBeat) {\n this.log('No new beats since last check-in. Call pulse() first.');\n return { ok: true, total_beats: this.totalBeats }; // Nothing new to report\n }\n\n try {\n // Find the boundary hashes\n const fromBeat = this.lastCheckinBeat;\n const toBeat = this.latestBeat.index;\n\n // Build spot checks from our local chain\n // prev and nonce are required for the server to recompute VDF\n // Must always include to_beat (final beat) — server requires it for final hash verification\n const spotChecks: { index: number; hash: string; prev: string; nonce?: string }[] = [];\n\n // Always include the final beat\n const toBeatEntry = this.chain.find(b => b.index === toBeat);\n if (toBeatEntry) {\n spotChecks.push({ index: toBeatEntry.index, hash: toBeatEntry.hash, prev: toBeatEntry.prev, nonce: toBeatEntry.nonce });\n }\n\n // Sample up to 4 more from the rest\n const available = this.chain.filter(b => b.index > this.lastCheckinBeat && b.index !== toBeat);\n const sampleCount = Math.min(4, available.length);\n\n for (let i = 0; i < sampleCount; i++) {\n const idx = Math.floor(Math.random() * available.length);\n const beat = available[idx];\n spotChecks.push({ index: beat.index, hash: beat.hash, prev: beat.prev, nonce: beat.nonce });\n available.splice(idx, 1);\n }\n const fromHash = this.chain.find(b => b.index === fromBeat)?.hash \n || this.genesisHash;\n const toHash = this.latestBeat.hash;\n\n const res = await this.api('POST', '/api/v1/agent/checkin', {\n proof: {\n from_beat: fromBeat,\n to_beat: toBeat,\n from_hash: fromHash,\n to_hash: toHash,\n beats_computed: toBeat - fromBeat,\n global_anchor: this.globalBeat,\n anchor_hash: this.globalAnchorHash || undefined,\n spot_checks: spotChecks,\n },\n });\n\n if (res.ok) {\n this.lastCheckinBeat = toBeat;\n this.totalBeats = res.total_beats;\n this.config.onCheckin(res);\n this.log(`Check-in accepted: ${res.beats_accepted} beats, total=${res.total_beats}, global=${res.global_beat}`);\n \n if (res.status === 'warning_overdue') {\n this.config.onStatusChange('warning', { beats_behind: res.beats_behind });\n this.log(`⚠ WARNING: ${res.beats_behind} anchors behind. Check in more frequently.`);\n }\n }\n\n return { ok: res.ok, total_beats: res.total_beats };\n\n } catch (err: any) {\n this.config.onError(err, 'checkin');\n return { ok: false, error: err.message };\n }\n }\n\n // ── AUTONOMOUS HEARTBEAT ──\n\n /**\n * Start the autonomous heartbeat loop.\n * Phase 2: Sends paid heartbeats at regular intervals.\n *\n * @param paymentTxFn - Optional function that returns a payment tx for each heartbeat.\n * If not provided, uses 'devnet-skip' (devnet only).\n */\n startHeartbeat(paymentTxFn?: () => Promise<string> | string): void {\n if (this.heartbeatInterval) {\n this.log('Heartbeat already running.');\n return;\n }\n\n if (this.status !== 'active' && this.status !== 'uninitialized') {\n throw new StateError(`Cannot start heartbeat in status '${this.status}'.`, this.status);\n }\n\n const intervalSec = this.config.heartbeatIntervalSec || this.config.checkinIntervalSec || 300;\n this.log(`Starting heartbeat (interval: ${intervalSec}s)...`);\n\n // SDK-P1-03: exponential backoff on consecutive errors\n let consecutiveErrors = 0;\n let skipCount = 0;\n\n this.heartbeatInterval = setInterval(async () => {\n if (skipCount > 0) {\n skipCount--;\n return;\n }\n\n try {\n const paymentTx = paymentTxFn ? await paymentTxFn() : 'devnet-skip';\n await this.heartbeat(paymentTx);\n consecutiveErrors = 0;\n } catch (err: any) {\n consecutiveErrors++;\n this.config.onError(err, 'heartbeat');\n skipCount = Math.min(32, Math.pow(2, consecutiveErrors - 1));\n this.log(`Heartbeat error #${consecutiveErrors}, backing off ${skipCount} ticks`);\n }\n }, intervalSec * 1000);\n }\n\n /**\n * Stop the heartbeat loop.\n */\n stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n this.log('Heartbeat stopped.');\n }\n }\n\n // ── RE-SYNC ──\n\n /**\n * @deprecated Phase 2: Resync retired (D-67). Dormancy resume is free — just call heartbeat().\n * This method will be removed in the next major version.\n */\n async resync(): Promise<{ ok: boolean; beats_required?: number; error?: string }> {\n console.warn('[Provenonce SDK] resync() is deprecated (D-67). Use heartbeat() to resume (Phase 2).');\n try {\n this.log('Requesting re-sync challenge...');\n\n // Phase 1: Get challenge\n const challenge = await this.api('POST', '/api/v1/agent/resync', {\n action: 'challenge',\n });\n\n if (!challenge.challenge) {\n return { ok: false, error: 'Failed to get challenge' };\n }\n\n const required = challenge.challenge.required_beats;\n this.difficulty = challenge.challenge.difficulty;\n this.log(`Re-sync challenge: compute ${required} beats at D=${this.difficulty}`);\n\n // Sync global anchor so beats are woven with a recent anchor hash\n await this.syncGlobal();\n\n // Compute the required beats\n const startHash = challenge.challenge.start_from_hash;\n const startBeat = challenge.challenge.start_from_beat;\n\n // Reset chain from the known point\n this.latestBeat = { index: startBeat, hash: startHash, prev: '', timestamp: Date.now() };\n this.chain = [this.latestBeat];\n\n const t0 = Date.now();\n this.computeBeats(required);\n const elapsed = Date.now() - t0;\n this.log(`Re-sync beats computed in ${elapsed}ms`);\n\n // Phase 2: Submit proof (include challenge_nonce for server verification)\n const proof = await this.api('POST', '/api/v1/agent/resync', {\n action: 'prove',\n challenge_nonce: challenge.challenge.nonce,\n proof: {\n from_beat: startBeat,\n to_beat: this.latestBeat!.index,\n from_hash: startHash,\n to_hash: this.latestBeat!.hash,\n beats_computed: required,\n global_anchor: challenge.challenge.sync_to_global,\n anchor_hash: this.globalAnchorHash || undefined,\n spot_checks: (() => {\n // Must include to_beat (final beat) — server requires it for final hash verification\n const toBeatEntry = this.chain.find(b => b.index === this.latestBeat!.index);\n // Sample from available chain beats (chain may be trimmed to 500 entries)\n const available = this.chain\n .filter(b => b.index !== this.latestBeat!.index && b.index > startBeat);\n const step = Math.max(1, Math.ceil(available.length / 5));\n const others = available\n .filter((_, i) => i % step === 0)\n .slice(0, 4);\n const checks = toBeatEntry ? [toBeatEntry, ...others] : others;\n return checks.map(b => ({ index: b.index, hash: b.hash, prev: b.prev, nonce: b.nonce }));\n })(),\n },\n });\n\n if (proof.ok) {\n this.status = 'active';\n this.totalBeats = proof.total_beats;\n this.lastCheckinBeat = this.latestBeat!.index;\n this.config.onStatusChange('active', { resynced: true });\n this.log('✓ Re-synced. Agent is alive again in Beat time.');\n }\n\n return { ok: proof.ok, beats_required: required };\n\n } catch (err: any) {\n this.config.onError(err, 'resync');\n return { ok: false, error: err.message };\n }\n }\n\n // ── SPAWN ──\n\n /**\n * Request to spawn a child agent.\n * Requires sufficient accumulated beats (Temporal Gestation).\n */\n async requestSpawn(childName?: string, childHash?: string): Promise<SpawnResult> {\n try {\n // SDK-P1-05: validate childName\n if (childName !== undefined) {\n if (typeof childName !== 'string' || childName.trim().length === 0) {\n throw new ValidationError('childName must be a non-empty string');\n }\n if (childName.length > 64) {\n throw new ValidationError('childName must be 64 characters or fewer');\n }\n }\n\n const res = await this.api('POST', '/api/v1/agent/spawn', {\n child_name: childName,\n child_hash: childHash,\n });\n\n if (res.eligible === false) {\n this.log(`Gestation incomplete: ${res.progress_pct}% (need ${res.deficit} more beats)`);\n } else if (res.ok) {\n this.log(`Child spawned: ${res.child_hash?.slice(0, 16)}...`);\n }\n\n return res;\n } catch (err: any) {\n this.config.onError(err, 'spawn');\n throw err;\n }\n }\n\n // ── PHASE 2: SIGIL + HEARTBEAT + PROOF ──\n\n /** Cached lineage proof from the most recent heartbeat or SIGIL purchase */\n private cachedProof: LineageProof | null = null;\n\n /**\n * Purchase a SIGIL (cryptographic identity) for this agent.\n * SIGILs gate heartbeating, lineage proofs, and offline verification.\n * One-time purchase — cannot be re-purchased.\n *\n * @param options - SIGIL purchase options (identity_class, principal, tier, name, payment_tx, + optional metadata)\n *\n * Legacy signature (deprecated):\n * @param identityClass - 'narrow_task' | 'autonomous' | 'orchestrator'\n * @param paymentTx - Solana transaction signature or 'devnet-skip'\n */\n async purchaseSigil(optionsOrClass: SigilPurchaseOptions | IdentityClass, paymentTx?: string): Promise<SigilResult> {\n let body: Record<string, unknown>;\n\n if (typeof optionsOrClass === 'string') {\n // Legacy signature: purchaseSigil(identityClass, paymentTx)\n if (!optionsOrClass || !['narrow_task', 'autonomous', 'orchestrator'].includes(optionsOrClass)) {\n throw new ValidationError('identityClass must be narrow_task, autonomous, or orchestrator');\n }\n if (!paymentTx || typeof paymentTx !== 'string') {\n throw new ValidationError('paymentTx is required (Solana transaction signature or \"devnet-skip\")');\n }\n body = {\n identity_class: optionsOrClass,\n payment_tx: paymentTx,\n // Legacy calls without principal/tier — server will require these now\n // Callers must migrate to the options object form\n };\n } else {\n // New signature: purchaseSigil(options)\n const opts = optionsOrClass;\n if (!opts.identity_class || !['narrow_task', 'autonomous', 'orchestrator'].includes(opts.identity_class)) {\n throw new ValidationError('identity_class must be narrow_task, autonomous, or orchestrator');\n }\n if (!opts.principal || typeof opts.principal !== 'string') {\n throw new ValidationError('principal is required');\n }\n if (!opts.tier || !['sov', 'org', 'ind', 'eph', 'sbx'].includes(opts.tier)) {\n throw new ValidationError('tier must be one of: sov, org, ind, eph, sbx');\n }\n if (!opts.payment_tx || typeof opts.payment_tx !== 'string') {\n throw new ValidationError('payment_tx is required');\n }\n\n body = { ...opts };\n }\n\n try {\n const res = await this.api('POST', '/api/v1/sigil', body);\n\n if (res.lineage_proof) {\n this.cachedProof = res.lineage_proof;\n }\n\n const sigilStr = res.sigil?.sigil || res.sigil?.identity_class || '';\n this.log(`SIGIL purchased: ${sigilStr}`);\n this.config.onStatusChange('sigil_issued', { sigil: sigilStr });\n\n return {\n ok: true,\n sigil: res.sigil,\n lineage_proof: res.lineage_proof,\n fee: res.fee,\n };\n } catch (err: any) {\n this.config.onError(err, 'purchaseSigil');\n return { ok: false, error: err.message };\n }\n }\n\n /**\n * Update mutable SIGIL metadata fields.\n * Requires a SIGIL. Cannot modify immutable fields.\n *\n * @param fields - Subset of mutable SIGIL fields to update\n */\n async updateMetadata(fields: Partial<SigilMutableFields>): Promise<MetadataUpdateResult> {\n if (!fields || Object.keys(fields).length === 0) {\n throw new ValidationError('At least one metadata field is required');\n }\n\n try {\n const res = await this.api('PATCH', '/api/v1/agent/metadata', fields);\n this.log(`Metadata updated: ${res.updated_fields?.join(', ') || 'unknown'}`);\n return {\n ok: true,\n sigil: res.sigil,\n generation: res.generation,\n updated_fields: res.updated_fields,\n };\n } catch (err: any) {\n this.config.onError(err, 'updateMetadata');\n return { ok: false, error: err.message };\n }\n }\n\n /**\n * Send a paid heartbeat to the registry.\n * Requires a SIGIL. Returns a signed lineage proof.\n * This is the Phase 2 replacement for pulse() + checkin().\n *\n * @param paymentTx - Solana transaction signature. Omit or 'devnet-skip' on devnet.\n * @param globalAnchor - Optional: the global anchor index to reference.\n */\n async heartbeat(paymentTx?: string, globalAnchor?: number): Promise<HeartbeatResult> {\n try {\n const res = await this.api('POST', '/api/v1/agent/heartbeat', {\n payment_tx: paymentTx || 'devnet-skip',\n global_anchor: globalAnchor,\n });\n\n if (res.lineage_proof) {\n this.cachedProof = res.lineage_proof;\n }\n\n if (res.ok) {\n this.status = 'active';\n const onHb = this.config.onHeartbeat || this.config.onCheckin;\n if (onHb) onHb(res);\n this.log(`Heartbeat accepted: epoch=${res.billing_epoch}, count=${res.heartbeat_count_epoch}`);\n }\n\n return {\n ok: res.ok,\n lineage_proof: res.lineage_proof,\n heartbeat_count_epoch: res.heartbeat_count_epoch,\n billing_epoch: res.billing_epoch,\n current_beat: res.current_beat,\n fee: res.fee,\n };\n } catch (err: any) {\n this.config.onError(err, 'heartbeat');\n return { ok: false, error: err.message };\n }\n }\n\n /**\n * Reissue a lineage proof. \"Reprint, not a renewal.\"\n * Does NOT create a new lineage event.\n *\n * @param paymentTx - Solana transaction signature. Omit or 'devnet-skip' on devnet.\n */\n async reissueProof(paymentTx?: string): Promise<{ ok: boolean; lineage_proof?: LineageProof; error?: string }> {\n try {\n const res = await this.api('POST', '/api/v1/agent/reissue-proof', {\n payment_tx: paymentTx || 'devnet-skip',\n });\n\n if (res.lineage_proof) {\n this.cachedProof = res.lineage_proof;\n }\n\n return { ok: true, lineage_proof: res.lineage_proof };\n } catch (err: any) {\n this.config.onError(err, 'reissueProof');\n return { ok: false, error: err.message };\n }\n }\n\n /**\n * Get the latest cached lineage proof (no network call).\n * Returns null if no proof has been obtained yet.\n */\n getLatestProof(): LineageProof | null {\n return this.cachedProof;\n }\n\n /**\n * Get the agent's passport (alias for getLatestProof).\n * The passport is the agent's portable, offline-verifiable credential.\n * Returns null if no passport has been issued yet (requires SIGIL + heartbeat).\n */\n getPassport(): Passport | null {\n return this.cachedProof;\n }\n\n /**\n * Verify a lineage proof locally using the authority public key.\n * Offline verification — no API call, no SOL cost.\n *\n * Returns a VerificationResult object. The object is truthy when valid,\n * so `if (BeatAgent.verifyProofLocally(proof, key))` still works.\n *\n * @param proof - The LineageProof to verify\n * @param authorityPubKeyHex - 32-byte hex-encoded Ed25519 public key from /.well-known/provenonce-authority.json\n * @param currentBeat - Optional current global beat index (for beatsSinceHeartbeat calculation)\n */\n static verifyProofLocally(proof: LineageProof, authorityPubKeyHex: string, currentBeat?: number): VerificationResult {\n const now = Date.now();\n const expired = now > proof.valid_until;\n\n let signatureValid = false;\n try {\n // Canonical JSON (must match server's canonicalProofData)\n const canonical = JSON.stringify({\n agent_hash: proof.agent_hash,\n agent_public_key: proof.agent_public_key,\n identity_class: proof.identity_class,\n registered_at_beat: proof.registered_at_beat,\n sigil_issued_at_beat: proof.sigil_issued_at_beat,\n last_heartbeat_beat: proof.last_heartbeat_beat,\n lineage_chain_hash: proof.lineage_chain_hash,\n issued_at: proof.issued_at,\n valid_until: proof.valid_until,\n });\n\n // Build Ed25519 public key from hex\n const pubBytes = Buffer.from(authorityPubKeyHex, 'hex');\n if (pubBytes.length === 32) {\n const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');\n const pubKeyDer = Buffer.concat([ED25519_SPKI_PREFIX, pubBytes]);\n const keyObject = createPublicKey({ key: pubKeyDer, format: 'der', type: 'spki' });\n const sigBuffer = Buffer.from(proof.provenonce_signature, 'hex');\n signatureValid = verify(null, Buffer.from(canonical), keyObject, sigBuffer);\n }\n } catch {\n signatureValid = false;\n }\n\n const valid = signatureValid && !expired;\n const beatsSinceHeartbeat = currentBeat != null ? currentBeat - proof.last_heartbeat_beat : null;\n\n let warning: string | undefined;\n if (expired) {\n warning = 'Proof has expired. Reissue with reissueProof() or send a heartbeat.';\n } else if (beatsSinceHeartbeat != null && beatsSinceHeartbeat > 60) {\n warning = `Agent is ${beatsSinceHeartbeat} beats behind. Heartbeat may be stale.`;\n }\n\n return { valid, signatureValid, expired, lastHeartbeatBeat: proof.last_heartbeat_beat, beatsSinceHeartbeat, warning };\n }\n\n // ── STATUS ──\n\n /**\n * Get this agent's full beat status from the registry.\n */\n async getStatus(): Promise<AgentStatus> {\n try {\n // We need the agent hash, but we may not have it directly.\n // The status endpoint uses the hash from the API key verification.\n // For now, use the init endpoint which returns status.\n return await this.refreshState();\n } catch (err: any) {\n this.config.onError(err, 'status');\n throw err;\n }\n }\n\n /**\n * Get local state (no network call).\n */\n getLocalState(): {\n status: string;\n totalBeats: number;\n latestBeat: number;\n latestHash: string;\n difficulty: number;\n globalBeat: number;\n chainLength: number;\n } {\n return {\n status: this.status,\n totalBeats: this.totalBeats,\n latestBeat: this.latestBeat?.index || 0,\n latestHash: this.latestBeat?.hash.slice(0, 24) + '...' || '',\n difficulty: this.difficulty,\n globalBeat: this.globalBeat,\n chainLength: this.chain.length,\n };\n }\n\n // ── INTERNALS ──\n\n private async syncGlobal(): Promise<void> {\n try {\n // SDK-P1-01: add timeout to syncGlobal fetch\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 15_000);\n const res = await fetch(`${this.config.registryUrl}/api/v1/beat/anchor`, { signal: controller.signal });\n clearTimeout(timeout);\n const data: any = await res.json();\n if (data.anchor) {\n this.globalBeat = data.anchor.beat_index;\n this.globalAnchorHash = data.anchor.hash || '';\n if (data.anchor.difficulty) this.difficulty = data.anchor.difficulty;\n this.log(`Synced to global beat ${this.globalBeat} (D=${this.difficulty})`);\n }\n } catch {\n this.log('Failed to sync global anchor (offline mode continues)');\n }\n }\n\n private async refreshState(): Promise<any> {\n const res = await this.api('POST', '/api/v1/agent/init');\n if (res.already_initialized) {\n this.totalBeats = res.total_beats;\n this.genesisHash = res.genesis_hash;\n this.status = res.status as any;\n this.difficulty = res.difficulty || this.difficulty;\n this.lastCheckinBeat = res.last_checkin_beat || 0;\n\n // Restore latestBeat so pulse() can continue the chain\n if (!this.latestBeat && this.genesisHash) {\n this.latestBeat = {\n index: res.latest_beat || this.totalBeats,\n hash: res.latest_hash || this.genesisHash,\n prev: '0'.repeat(64),\n timestamp: Date.now(),\n };\n this.chain = [this.latestBeat];\n }\n }\n return res;\n }\n\n private async api(method: string, path: string, body?: any): Promise<any> {\n // SDK-P1-01: add 30s timeout to prevent indefinite hangs\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 30_000);\n\n try {\n const res = await fetch(`${this.config.registryUrl}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.apiKey}`,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n let data: any;\n try {\n data = await res.json();\n } catch {\n throw new NetworkError(`API error: ${res.status} non-JSON response from ${path}`);\n }\n\n if (!res.ok && !data.ok && !data.already_initialized && !data.eligible) {\n throw mapApiError(res.status, data, path);\n }\n\n return data;\n } catch (err: any) {\n if (err.name === 'AbortError') {\n throw new NetworkError(`Request timeout: ${method} ${path}`, ErrorCode.TIMEOUT);\n }\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private log(msg: string): void {\n if (this.config.verbose) {\n console.log(`[Beat] ${msg}`);\n }\n }\n}\n\n// ============ STANDALONE VDF HELPER ============\n// For agents that want to compute beats without the full SDK\n\nexport { computeBeat };\n\n/**\n * Compute N sequential VDF beats.\n * Returns only the last beat (for lightweight usage).\n */\nexport function computeBeatsLite(\n startHash: string,\n startIndex: number,\n count: number,\n difficulty: number = 1000,\n anchorHash?: string,\n): { lastBeat: Beat; elapsed: number } {\n // SDK-P2: validate inputs\n if (!startHash || typeof startHash !== 'string') {\n throw new ValidationError('computeBeatsLite: startHash must be a non-empty string');\n }\n if (!Number.isInteger(count) || count < 1) {\n throw new ValidationError('computeBeatsLite: count must be a positive integer');\n }\n\n const t0 = Date.now();\n let prev = startHash;\n let lastBeat: Beat | null = null;\n\n for (let i = 0; i < count; i++) {\n lastBeat = computeBeat(prev, startIndex + i, difficulty, undefined, anchorHash);\n prev = lastBeat.hash;\n }\n\n return { lastBeat: lastBeat!, elapsed: Date.now() - t0 };\n}\n","/**\n * Provenonce SDK Error Classes\n *\n * Typed error hierarchy for programmatic error handling.\n * All errors extend ProvenonceError for catch-all, or catch specific\n * subclasses for fine-grained control:\n *\n * try {\n * await agent.checkin();\n * } catch (err) {\n * if (err instanceof RateLimitError) {\n * await sleep(err.retryAfterMs);\n * } else if (err instanceof FrozenError) {\n * await agent.resync();\n * } else if (err instanceof AuthError) {\n * console.error('Bad API key');\n * }\n * }\n */\n\n/** Error codes for programmatic switching */\nexport enum ErrorCode {\n // Validation\n VALIDATION = 'VALIDATION',\n\n // Auth\n AUTH_INVALID = 'AUTH_INVALID',\n AUTH_MISSING = 'AUTH_MISSING',\n\n // Rate limiting\n RATE_LIMITED = 'RATE_LIMITED',\n\n // Agent state\n AGENT_FROZEN = 'AGENT_FROZEN',\n AGENT_NOT_INITIALIZED = 'AGENT_NOT_INITIALIZED',\n AGENT_WRONG_STATE = 'AGENT_WRONG_STATE',\n\n // Not found\n NOT_FOUND = 'NOT_FOUND',\n\n // Network / server\n NETWORK_ERROR = 'NETWORK_ERROR',\n TIMEOUT = 'TIMEOUT',\n SERVER_ERROR = 'SERVER_ERROR',\n}\n\n/** Base error class for all Provenonce SDK errors */\nexport class ProvenonceError extends Error {\n /** Machine-readable error code */\n readonly code: ErrorCode;\n\n /** HTTP status code (if from an API response) */\n readonly statusCode?: number;\n\n /** Additional context */\n readonly details?: Record<string, unknown>;\n\n constructor(\n message: string,\n code: ErrorCode,\n statusCode?: number,\n details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'ProvenonceError';\n this.code = code;\n this.statusCode = statusCode;\n this.details = details;\n // Fix prototype chain for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when input validation fails (bad config, invalid args) */\nexport class ValidationError extends ProvenonceError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, ErrorCode.VALIDATION, undefined, details);\n this.name = 'ValidationError';\n }\n}\n\n/** Thrown on 401/403 — bad or missing API key */\nexport class AuthError extends ProvenonceError {\n constructor(\n message: string,\n code: ErrorCode.AUTH_INVALID | ErrorCode.AUTH_MISSING = ErrorCode.AUTH_INVALID,\n statusCode?: number,\n ) {\n super(message, code, statusCode);\n this.name = 'AuthError';\n }\n}\n\n/** Thrown on 429 — rate limit exceeded */\nexport class RateLimitError extends ProvenonceError {\n /** Milliseconds until the rate limit resets (if provided by server) */\n readonly retryAfterMs?: number;\n\n constructor(message: string, statusCode: number = 429, retryAfterMs?: number) {\n super(message, ErrorCode.RATE_LIMITED, statusCode);\n this.name = 'RateLimitError';\n this.retryAfterMs = retryAfterMs;\n }\n}\n\n/** Thrown when an agent is frozen and cannot perform the requested action */\nexport class FrozenError extends ProvenonceError {\n constructor(message: string = 'Agent is frozen. Use resync() to re-establish provenance.') {\n super(message, ErrorCode.AGENT_FROZEN);\n this.name = 'FrozenError';\n }\n}\n\n/** Thrown when the agent is in the wrong state for the requested action */\nexport class StateError extends ProvenonceError {\n /** The agent's current state */\n readonly currentState: string;\n\n constructor(message: string, currentState: string, code: ErrorCode = ErrorCode.AGENT_WRONG_STATE) {\n super(message, code);\n this.name = 'StateError';\n this.currentState = currentState;\n }\n}\n\n/** Thrown on 404 — agent or resource not found */\nexport class NotFoundError extends ProvenonceError {\n constructor(message: string, statusCode: number = 404) {\n super(message, ErrorCode.NOT_FOUND, statusCode);\n this.name = 'NotFoundError';\n }\n}\n\n/** Thrown on network failures — non-JSON responses, fetch errors, timeouts */\nexport class NetworkError extends ProvenonceError {\n constructor(message: string, code: ErrorCode.NETWORK_ERROR | ErrorCode.TIMEOUT = ErrorCode.NETWORK_ERROR) {\n super(message, code);\n this.name = 'NetworkError';\n }\n}\n\n/** Thrown on 5xx — unexpected server errors */\nexport class ServerError extends ProvenonceError {\n constructor(message: string, statusCode: number = 500) {\n super(message, ErrorCode.SERVER_ERROR, statusCode);\n this.name = 'ServerError';\n }\n}\n\n/**\n * Map an HTTP response + parsed body to the appropriate error class.\n * Used internally by the SDK to convert API failures to typed errors.\n */\nexport function mapApiError(\n statusCode: number,\n body: { error?: string; retry_after_ms?: number },\n path: string,\n): ProvenonceError {\n const msg = typeof body.error === 'string' ? body.error : `API error ${statusCode}`;\n\n if (statusCode === 401 || statusCode === 403) {\n const code = statusCode === 401 ? ErrorCode.AUTH_MISSING : ErrorCode.AUTH_INVALID;\n return new AuthError(msg, code, statusCode);\n }\n\n if (statusCode === 429) {\n const retryAfter = typeof body.retry_after_ms === 'number' ? body.retry_after_ms : undefined;\n return new RateLimitError(msg, statusCode, retryAfter);\n }\n\n if (statusCode === 404) {\n return new NotFoundError(msg, statusCode);\n }\n\n if (statusCode >= 500) {\n return new ServerError(msg, statusCode);\n }\n\n // Check for specific error patterns in the message\n const lowerMsg = msg.toLowerCase();\n if (lowerMsg.includes('frozen')) {\n return new FrozenError(msg);\n }\n\n // Generic client error\n return new ProvenonceError(msg, ErrorCode.SERVER_ERROR, statusCode);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC6BA,oBAAiG;;;ACR1F,IAAK,YAAL,kBAAKA,eAAL;AAEL,EAAAA,WAAA,gBAAa;AAGb,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,kBAAe;AAGf,EAAAA,WAAA,kBAAe;AAGf,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,2BAAwB;AACxB,EAAAA,WAAA,uBAAoB;AAGpB,EAAAA,WAAA,eAAY;AAGZ,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,aAAU;AACV,EAAAA,WAAA,kBAAe;AAtBL,SAAAA;AAAA,GAAA;AA0BL,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAUzC,YACE,SACA,MACA,YACA,SACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,UAAU;AAEf,WAAO,eAAe,MAAM,WAAW,SAAS;AAAA,EAClD;AACF;AAGO,IAAM,kBAAN,cAA8B,gBAAgB;AAAA,EACnD,YAAY,SAAiB,SAAmC;AAC9D,UAAM,SAAS,+BAAsB,QAAW,OAAO;AACvD,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,YAAN,cAAwB,gBAAgB;AAAA,EAC7C,YACE,SACA,OAAwD,mCACxD,YACA;AACA,UAAM,SAAS,MAAM,UAAU;AAC/B,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EAIlD,YAAY,SAAiB,aAAqB,KAAK,cAAuB;AAC5E,UAAM,SAAS,mCAAwB,UAAU;AACjD,SAAK,OAAO;AACZ,SAAK,eAAe;AAAA,EACtB;AACF;AAGO,IAAM,cAAN,cAA0B,gBAAgB;AAAA,EAC/C,YAAY,UAAkB,6DAA6D;AACzF,UAAM,SAAS,iCAAsB;AACrC,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,aAAN,cAAyB,gBAAgB;AAAA,EAI9C,YAAY,SAAiB,cAAsB,OAAkB,6CAA6B;AAChG,UAAM,SAAS,IAAI;AACnB,SAAK,OAAO;AACZ,SAAK,eAAe;AAAA,EACtB;AACF;AAGO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EACjD,YAAY,SAAiB,aAAqB,KAAK;AACrD,UAAM,SAAS,6BAAqB,UAAU;AAC9C,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,eAAN,cAA2B,gBAAgB;AAAA,EAChD,YAAY,SAAiB,OAAoD,qCAAyB;AACxG,UAAM,SAAS,IAAI;AACnB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,cAAN,cAA0B,gBAAgB;AAAA,EAC/C,YAAY,SAAiB,aAAqB,KAAK;AACrD,UAAM,SAAS,mCAAwB,UAAU;AACjD,SAAK,OAAO;AAAA,EACd;AACF;AAMO,SAAS,YACd,YACA,MACA,MACiB;AACjB,QAAM,MAAM,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,aAAa,UAAU;AAEjF,MAAI,eAAe,OAAO,eAAe,KAAK;AAC5C,UAAM,OAAO,eAAe,MAAM,oCAAyB;AAC3D,WAAO,IAAI,UAAU,KAAK,MAAM,UAAU;AAAA,EAC5C;AAEA,MAAI,eAAe,KAAK;AACtB,UAAM,aAAa,OAAO,KAAK,mBAAmB,WAAW,KAAK,iBAAiB;AACnF,WAAO,IAAI,eAAe,KAAK,YAAY,UAAU;AAAA,EACvD;AAEA,MAAI,eAAe,KAAK;AACtB,WAAO,IAAI,cAAc,KAAK,UAAU;AAAA,EAC1C;AAEA,MAAI,cAAc,KAAK;AACrB,WAAO,IAAI,YAAY,KAAK,UAAU;AAAA,EACxC;AAGA,QAAM,WAAW,IAAI,YAAY;AACjC,MAAI,SAAS,SAAS,QAAQ,GAAG;AAC/B,WAAO,IAAI,YAAY,GAAG;AAAA,EAC5B;AAGA,SAAO,IAAI,gBAAgB,KAAK,mCAAwB,UAAU;AACpE;;;ADWA,SAAS,YAAY,UAAkB,WAAmB,YAAoB,OAAgB,YAA2B;AACvH,QAAM,YAAY,KAAK,IAAI;AAE3B,QAAM,OAAO,aACT,GAAG,QAAQ,IAAI,SAAS,IAAI,SAAS,EAAE,IAAI,UAAU,KACrD,GAAG,QAAQ,IAAI,SAAS,IAAI,SAAS,EAAE;AAE3C,MAAI,cAAU,0BAAW,QAAQ,EAC9B,OAAO,IAAI,EACX,OAAO,KAAK;AAEf,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,kBAAU,0BAAW,QAAQ,EAC1B,OAAO,OAAO,EACd,OAAO,KAAK;AAAA,EACjB;AAEA,SAAO,EAAE,OAAO,WAAW,MAAM,SAAS,MAAM,UAAU,WAAW,OAAO,aAAa,WAAW;AACtG;AAoCA,IAAM,uBAAuB,OAAO,KAAK,oCAAoC,KAAK;AAO3E,SAAS,wBAAkE;AAChF,QAAM,EAAE,WAAW,WAAW,QAAI,mCAAoB,SAAS;AAC/D,QAAM,SAAS,UAAU,OAAO,EAAE,MAAM,QAAQ,QAAQ,MAAM,CAAC,EAAE,SAAS,EAAE;AAC5E,QAAM,UAAU,WAAW,OAAO,EAAE,MAAM,SAAS,QAAQ,MAAM,CAAC,EAAE,SAAS,EAAE;AAC/E,SAAO;AAAA,IACL,WAAW,OAAO,KAAK,MAAM,EAAE,SAAS,KAAK;AAAA,IAC7C,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,KAAK;AAAA,EAChD;AACF;AAMA,SAAS,YAAY,cAAsB,SAAyB;AAClE,QAAM,UAAU,OAAO,KAAK,cAAc,KAAK;AAC/C,QAAM,aAAa,OAAO,OAAO,CAAC,sBAAsB,OAAO,CAAC;AAChE,QAAM,gBAAY,gCAAiB,EAAE,KAAK,YAAY,QAAQ,OAAO,MAAM,QAAQ,CAAC;AACpF,QAAM,UAAM,oBAAK,MAAM,OAAO,KAAK,OAAO,GAAG,SAAS;AACtD,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,KAAK;AACxC;AAsHA,eAAsB,SACpB,MACA,SAC6B;AAE7B,MAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,KAAK,KAAK,EAAE,WAAW,GAAG;AACjE,UAAM,IAAI,gBAAgB,+CAA+C;AAAA,EAC3E;AACA,MAAI,KAAK,SAAS,IAAI;AACpB,UAAM,IAAI,gBAAgB,qCAAqC;AAAA,EACjE;AAEA,QAAM,MAAM,SAAS,eAAe;AACpC,MAAI;AACF,QAAI,IAAI,GAAG;AAAA,EACb,QAAQ;AACN,UAAM,IAAI,gBAAgB,gCAAgC;AAAA,EAC5D;AAEA,QAAM,UAAkC,EAAE,gBAAgB,mBAAmB;AAE7E,MAAI,SAAS,oBAAoB;AAC/B,YAAQ,uBAAuB,IAAI,QAAQ;AAAA,EAC7C;AACA,MAAI,SAAS,mBAAmB;AAC9B,YAAQ,sBAAsB,IAAI,QAAQ;AAAA,EAC5C;AACA,MAAI,SAAS,oBAAoB;AAC/B,YAAQ,uBAAuB,IAAI,QAAQ;AAAA,EAC7C;AAGA,MAAI,SAAS,YAAY;AACvB,QAAI,QAAQ,cAAc;AACxB,cAAQ,eAAe,IAAI,UAAU,QAAQ,YAAY;AAAA,IAC3D;AAEA,UAAMC,OAAM,MAAM,MAAM,GAAG,GAAG,oBAAoB;AAAA,MAChD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,MAAM,QAAQ,QAAQ,YAAY,GAAI,QAAQ,YAAY,EAAE,UAAU,QAAQ,SAAS,EAAG,CAAC;AAAA,IACpH,CAAC;AAED,QAAIC;AACJ,QAAI;AACF,MAAAA,QAAO,MAAMD,KAAI,KAAK;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,aAAa,wBAAwBA,KAAI,MAAM,IAAIA,KAAI,UAAU,sBAAsB;AAAA,IACnG;AACA,QAAI,CAACA,KAAI,GAAI,OAAM,YAAYA,KAAI,QAAQC,OAAM,kBAAkB;AACnE,WAAOA;AAAA,EACT;AAGA,MAAI,SAAS,gBAAgB,YAAY;AACvC,QAAI,CAAC,QAAQ,iBAAiB,CAAC,QAAQ,cAAc;AACnD,YAAM,IAAI,gBAAgB,+DAA+D;AAAA,IAC3F;AAEA,QAAI,CAAC,sBAAsB,KAAK,QAAQ,aAAa,GAAG;AACtD,YAAM,IAAI,gBAAgB,oEAAoE;AAAA,IAChG;AAGA,UAAM,eAAe,MAAM,MAAM,GAAG,GAAG,oBAAoB;AAAA,MACzD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,MAAM,QAAQ,aAAa,cAAc,WAAW,CAAC;AAAA,IAC9E,CAAC;AAED,QAAI;AACJ,QAAI;AACF,sBAAgB,MAAM,aAAa,KAAK;AAAA,IAC1C,QAAQ;AACN,YAAM,IAAI,aAAa,kCAAkC,aAAa,MAAM,sBAAsB;AAAA,IACpG;AACA,QAAI,CAAC,aAAa,MAAM,CAAC,cAAc,OAAO;AAC5C,YAAM,YAAY,aAAa,QAAQ,eAAe,kBAAkB;AAAA,IAC1E;AAGA,UAAM,QAAQ,cAAc;AAC5B,UAAM,UAAU,gCAAgC,KAAK,IAAI,QAAQ,aAAa,IAAI,IAAI;AACtF,UAAM,kBAAkB,MAAM,QAAQ,aAAa,OAAO;AAE1D,UAAM,cAAc,MAAM,MAAM,GAAG,GAAG,oBAAoB;AAAA,MACxD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA,cAAc;AAAA,QACd,gBAAgB,QAAQ;AAAA,QACxB,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,GAAI,QAAQ,YAAY,EAAE,UAAU,QAAQ,SAAS;AAAA,MACvD,CAAC;AAAA,IACH,CAAC;AAED,QAAIA;AACJ,QAAI;AACF,MAAAA,QAAO,MAAM,YAAY,KAAK;AAAA,IAChC,QAAQ;AACN,YAAM,IAAI,aAAa,iCAAiC,YAAY,MAAM,sBAAsB;AAAA,IAClG;AACA,QAAI,CAAC,YAAY,GAAI,OAAM,YAAY,YAAY,QAAQA,OAAM,kBAAkB;AAGnF,IAAAA,MAAK,SAAS;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,SAASA,MAAK,QAAQ,WAAW,QAAQ;AAAA,MACzC,OAAO;AAAA,IACT;AAEA,WAAOA;AAAA,EACT;AAGA,MAAI,SAAS,gBAAgB,YAAY;AACvC,QAAI,CAAC,QAAQ,yBAAyB,CAAC,QAAQ,gBAAgB;AAC7D,YAAM,IAAI,gBAAgB,yEAAyE;AAAA,IACrG;AAGA,UAAM,eAAe,MAAM,MAAM,GAAG,GAAG,oBAAoB;AAAA,MACzD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,MAAM,QAAQ,aAAa,cAAc,WAAW,CAAC;AAAA,IAC9E,CAAC;AAED,QAAI;AACJ,QAAI;AACF,sBAAgB,MAAM,aAAa,KAAK;AAAA,IAC1C,QAAQ;AACN,YAAM,IAAI,aAAa,kCAAkC,aAAa,MAAM,sBAAsB;AAAA,IACpG;AACA,QAAI,CAAC,aAAa,MAAM,CAAC,cAAc,OAAO;AAC5C,YAAM,YAAY,aAAa,QAAQ,eAAe,kBAAkB;AAAA,IAC1E;AAGA,UAAM,QAAQ,cAAc;AAC5B,UAAM,UAAU,gCAAgC,KAAK,IAAI,QAAQ,qBAAqB,IAAI,IAAI;AAC9F,UAAM,kBAAkB,MAAM,QAAQ,eAAe,OAAO;AAE5D,UAAM,cAAc,MAAM,MAAM,GAAG,GAAG,oBAAoB;AAAA,MACxD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA,cAAc;AAAA,QACd,yBAAyB,QAAQ;AAAA,QACjC,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,GAAI,QAAQ,YAAY,EAAE,UAAU,QAAQ,SAAS;AAAA,MACvD,CAAC;AAAA,IACH,CAAC;AAED,QAAIA;AACJ,QAAI;AACF,MAAAA,QAAO,MAAM,YAAY,KAAK;AAAA,IAChC,QAAQ;AACN,YAAM,IAAI,aAAa,iCAAiC,YAAY,MAAM,sBAAsB;AAAA,IAClG;AACA,QAAI,CAAC,YAAY,GAAI,OAAM,YAAY,YAAY,QAAQA,OAAM,kBAAkB;AAGnF,UAAM,OAAOA,MAAK,QAAQ,WAAWA,MAAK,QAAQ,kBAAkB,QAAQ;AAC5E,IAAAA,MAAK,SAAS;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAEA,WAAOA;AAAA,EACT;AAGA,MAAI,SAAS,gBAAgB,kBAAkB,SAAS,iBAAiB;AAEvE,QAAI;AACJ,QAAI,SAAS,iBAAiB;AAE5B,YAAM,UAAU,OAAO,KAAK,QAAQ,iBAAiB,KAAK;AAC1D,YAAM,aAAa,OAAO,OAAO,CAAC,sBAAsB,OAAO,CAAC;AAChE,YAAM,gBAAY,gCAAiB,EAAE,KAAK,YAAY,QAAQ,OAAO,MAAM,QAAQ,CAAC;AACpF,YAAM,SAAS,UAAU,OAAO,EAAE,MAAM,QAAQ,QAAQ,MAAM,CAAC,EAAE,SAAS,EAAE;AAC5E,mBAAa;AAAA,QACX,WAAW,OAAO,KAAK,MAAM,EAAE,SAAS,KAAK;AAAA,QAC7C,WAAW,QAAQ;AAAA,MACrB;AAAA,IACF,OAAO;AACL,mBAAa,sBAAsB;AAAA,IACrC;AAGA,UAAM,eAAe,MAAM,MAAM,GAAG,GAAG,oBAAoB;AAAA,MACzD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,MAAM,QAAQ,YAAY,CAAC;AAAA,IACpD,CAAC;AAED,QAAI;AACJ,QAAI;AACF,sBAAgB,MAAM,aAAa,KAAK;AAAA,IAC1C,QAAQ;AACN,YAAM,MAAM,IAAI,aAAa,kCAAkC,aAAa,MAAM,sBAAsB;AACxG,MAAC,IAAY,aAAa,EAAE,WAAW,WAAW,WAAW,WAAW,WAAW,UAAU;AAC7F,YAAM;AAAA,IACR;AACA,QAAI,CAAC,aAAa,MAAM,CAAC,cAAc,OAAO;AAE5C,YAAM,MAAM,YAAY,aAAa,QAAQ,eAAe,kBAAkB;AAC9E,MAAC,IAAY,aAAa,EAAE,WAAW,WAAW,WAAW,WAAW,WAAW,UAAU;AAC7F,YAAM;AAAA,IACR;AAGA,UAAM,QAAQ,cAAc;AAC5B,UAAM,UAAU,uBAAuB,KAAK,IAAI,WAAW,SAAS,IAAI,IAAI;AAC5E,UAAM,kBAAkB,YAAY,WAAW,WAAW,OAAO;AAEjE,UAAM,cAAc,MAAM,MAAM,GAAG,GAAG,oBAAoB;AAAA,MACxD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA,mBAAmB,WAAW;AAAA,QAC9B,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,GAAI,SAAS,YAAY,EAAE,UAAU,QAAQ,SAAS;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AAED,QAAIA;AACJ,QAAI;AACF,MAAAA,QAAO,MAAM,YAAY,KAAK;AAAA,IAChC,QAAQ;AAEN,YAAM,MAAM,IAAI,aAAa,wBAAwB,YAAY,MAAM,sBAAsB;AAC7F,MAAC,IAAY,aAAa,EAAE,WAAW,WAAW,WAAW,WAAW,WAAW,UAAU;AAC7F,YAAM;AAAA,IACR;AACA,QAAI,CAAC,YAAY,IAAI;AAEnB,YAAM,MAAM,YAAY,YAAY,QAAQA,OAAM,kBAAkB;AACpE,MAAC,IAAY,aAAa,EAAE,WAAW,WAAW,WAAW,WAAW,WAAW,UAAU;AAC7F,YAAM;AAAA,IACR;AAGA,UAAM,OAAOA,MAAK,QAAQ,WAAWA,MAAK,QAAQ,kBAAkB;AACpE,IAAAA,MAAK,SAAS;AAAA,MACZ,YAAY,WAAW;AAAA,MACvB,YAAY,WAAW;AAAA,MACvB,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAEA,WAAOA;AAAA,EACT;AAIA,QAAM,MAAM,MAAM,MAAM,GAAG,GAAG,oBAAoB;AAAA,IAChD,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU,EAAE,MAAM,GAAI,SAAS,YAAY,EAAE,UAAU,QAAQ,SAAS,EAAG,CAAC;AAAA,EACzF,CAAC;AAED,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI,aAAa,wBAAwB,IAAI,MAAM,IAAI,IAAI,UAAU,sBAAsB;AAAA,EACnG;AACA,MAAI,CAAC,IAAI,GAAI,OAAM,YAAY,IAAI,QAAQ,MAAM,kBAAkB;AACnE,SAAO;AACT;AAyCO,IAAM,YAAN,MAAgB;AAAA,EAarB,YAAY,QAAyB;AAXrC,SAAQ,QAAgB,CAAC;AACzB,SAAQ,aAAqB;AAC7B,SAAQ,cAAsB;AAC9B,SAAQ,aAA0B;AAClC,SAAQ,aAAqB;AAC7B,SAAQ,kBAA0B;AAClC,SAAQ,SAA4D;AACpE,SAAQ,oBAA2D;AACnE,SAAQ,aAAqB;AAC7B,SAAQ,mBAA2B;AA0ZnC;AAAA;AAAA,SAAQ,cAAmC;AAtZzC,QAAI,CAAC,OAAO,UAAU,OAAO,OAAO,WAAW,UAAU;AACvD,YAAM,IAAI,gBAAgB,iEAAiE;AAAA,IAC7F;AACA,QAAI,CAAC,OAAO,eAAe,OAAO,OAAO,gBAAgB,UAAU;AACjE,YAAM,IAAI,gBAAgB,sEAAsE;AAAA,IAClG;AAEA,QAAI;AACF,UAAI,IAAI,OAAO,WAAW;AAAA,IAC5B,QAAQ;AACN,YAAM,IAAI,gBAAgB,gDAAgD;AAAA,IAC5E;AAGA,QAAI,OAAO,kBAAkB,WAAc,CAAC,OAAO,UAAU,OAAO,aAAa,KAAK,OAAO,gBAAgB,KAAK,OAAO,gBAAgB,MAAQ;AAC/I,YAAM,IAAI,gBAAgB,sEAAsE;AAAA,IAClG;AACA,QAAI,OAAO,uBAAuB,WAAc,CAAC,OAAO,SAAS,OAAO,kBAAkB,KAAK,OAAO,qBAAqB,MAAM,OAAO,qBAAqB,QAAQ;AACnK,YAAM,IAAI,gBAAgB,iEAAiE;AAAA,IAC7F;AAEA,SAAK,SAAS;AAAA,MACZ,eAAe;AAAA,MACf,oBAAoB;AAAA,MACpB,sBAAsB;AAAA,MACtB,SAAS,MAAM;AAAA,MAAC;AAAA,MAChB,WAAW,MAAM;AAAA,MAAC;AAAA,MAClB,aAAa,MAAM;AAAA,MAAC;AAAA,MACpB,SAAS,MAAM;AAAA,MAAC;AAAA,MAChB,gBAAgB,MAAM;AAAA,MAAC;AAAA,MACvB,SAAS;AAAA,MACT,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAmE;AACvE,QAAI;AACF,WAAK,IAAI,4BAA4B;AAErC,YAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,oBAAoB;AAEvD,UAAI,IAAI,SAAS;AACf,aAAK,cAAc,IAAI,QAAQ;AAC/B,aAAK,aAAa,IAAI,cAAc;AACpC,aAAK,aAAa;AAAA,UAChB,OAAO;AAAA,UACP,MAAM,IAAI,QAAQ;AAAA,UAClB,MAAM,IAAI,QAAQ;AAAA,UAClB,WAAW,IAAI,QAAQ;AAAA,QACzB;AACA,aAAK,QAAQ,CAAC,KAAK,UAAU;AAC7B,aAAK,aAAa;AAClB,aAAK,SAAS;AACd,aAAK,OAAO,eAAe,UAAU,EAAE,SAAS,KAAK,YAAY,CAAC;AAClE,aAAK,IAAI,+BAA+B,KAAK,YAAY,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,MAC5E,WAAW,IAAI,qBAAqB;AAElC,aAAK,cAAc,IAAI;AACvB,aAAK,aAAa,IAAI;AACtB,aAAK,SAAS,IAAI;AAClB,aAAK,IAAI,yCAAyC,IAAI,WAAW,UAAU;AAG3E,cAAM,KAAK,aAAa;AAAA,MAC1B;AAGA,YAAM,KAAK,WAAW;AAEtB,aAAO,EAAE,IAAI,MAAM,SAAS,KAAK,YAAY;AAAA,IAE/C,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,MAAM;AAC/B,aAAO,EAAE,IAAI,OAAO,OAAO,IAAI,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OAAwB;AAC5B,YAAQ,KAAK,4EAA4E;AACzF,QAAI,KAAK,WAAW,UAAU;AAC5B,YAAM,IAAI,YAAY,yEAAyE;AAAA,IACjG;AACA,QAAI,KAAK,WAAW,UAAU;AAC5B,YAAM,IAAI,WAAW,0BAA0B,KAAK,MAAM,KAAK,KAAK,MAAM;AAAA,IAC5E;AAEA,QAAI,UAAU,WAAc,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,MAAQ;AACnF,YAAM,IAAI,gBAAgB,oDAAoD;AAAA,IAChF;AACA,WAAO,KAAK,aAAa,KAAK;AAAA,EAChC;AAAA;AAAA,EAGQ,aAAa,OAAgB,YAAgE;AACnG,UAAM,IAAI,SAAS,KAAK,OAAO;AAE/B,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI,WAAW,kDAAkD,oEAAgD;AAAA,IACzH;AAEA,UAAM,WAAmB,CAAC;AAC1B,QAAI,WAAW,KAAK,WAAW;AAC/B,QAAI,aAAa,KAAK,WAAW,QAAQ;AAEzC,UAAM,KAAK,KAAK,IAAI;AAEpB,UAAM,mBAAmB,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,EAAE,CAAC;AAEvD,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,OAAO,YAAY,UAAU,aAAa,GAAG,KAAK,YAAY,QAAW,KAAK,oBAAoB,MAAS;AACjH,eAAS,KAAK,IAAI;AAClB,iBAAW,KAAK;AAChB,UAAI,eAAe,IAAI,KAAK,qBAAqB,GAAG;AAClD,mBAAW,IAAI,GAAG,CAAC;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,IAAI,IAAI;AAG7B,SAAK,MAAM,KAAK,GAAG,QAAQ;AAC3B,SAAK,aAAa,SAAS,SAAS,SAAS,CAAC;AAC9C,SAAK,cAAc;AAGnB,QAAI,KAAK,MAAM,SAAS,KAAM;AAC5B,WAAK,QAAQ,KAAK,MAAM,MAAM,IAAI;AAAA,IACpC;AAEA,SAAK,OAAO,QAAQ,UAAU,KAAK,UAAU;AAC7C,SAAK,IAAI,UAAU,CAAC,aAAa,OAAO,QAAQ,UAAU,GAAG,QAAQ,CAAC,CAAC,cAAc,KAAK,UAAU,GAAG;AAEvG,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAA0E;AAC9E,YAAQ,KAAK,8EAA8E;AAE3F,QAAI,CAAC,KAAK,cAAc,KAAK,WAAW,SAAS,KAAK,iBAAiB;AACrE,WAAK,IAAI,uDAAuD;AAChE,aAAO,EAAE,IAAI,MAAM,aAAa,KAAK,WAAW;AAAA,IAClD;AAEA,QAAI;AAEF,YAAM,WAAW,KAAK;AACtB,YAAM,SAAS,KAAK,WAAW;AAK/B,YAAM,aAA8E,CAAC;AAGrF,YAAM,cAAc,KAAK,MAAM,KAAK,OAAK,EAAE,UAAU,MAAM;AAC3D,UAAI,aAAa;AACf,mBAAW,KAAK,EAAE,OAAO,YAAY,OAAO,MAAM,YAAY,MAAM,MAAM,YAAY,MAAM,OAAO,YAAY,MAAM,CAAC;AAAA,MACxH;AAGA,YAAM,YAAY,KAAK,MAAM,OAAO,OAAK,EAAE,QAAQ,KAAK,mBAAmB,EAAE,UAAU,MAAM;AAC7F,YAAM,cAAc,KAAK,IAAI,GAAG,UAAU,MAAM;AAEhD,eAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,cAAM,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,UAAU,MAAM;AACvD,cAAM,OAAO,UAAU,GAAG;AAC1B,mBAAW,KAAK,EAAE,OAAO,KAAK,OAAO,MAAM,KAAK,MAAM,MAAM,KAAK,MAAM,OAAO,KAAK,MAAM,CAAC;AAC1F,kBAAU,OAAO,KAAK,CAAC;AAAA,MACzB;AACA,YAAM,WAAW,KAAK,MAAM,KAAK,OAAK,EAAE,UAAU,QAAQ,GAAG,QACxD,KAAK;AACV,YAAM,SAAS,KAAK,WAAW;AAE/B,YAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,yBAAyB;AAAA,QAC1D,OAAO;AAAA,UACL,WAAW;AAAA,UACX,SAAS;AAAA,UACT,WAAW;AAAA,UACX,SAAS;AAAA,UACT,gBAAgB,SAAS;AAAA,UACzB,eAAe,KAAK;AAAA,UACpB,aAAa,KAAK,oBAAoB;AAAA,UACtC,aAAa;AAAA,QACf;AAAA,MACF,CAAC;AAED,UAAI,IAAI,IAAI;AACV,aAAK,kBAAkB;AACvB,aAAK,aAAa,IAAI;AACtB,aAAK,OAAO,UAAU,GAAG;AACzB,aAAK,IAAI,sBAAsB,IAAI,cAAc,iBAAiB,IAAI,WAAW,YAAY,IAAI,WAAW,EAAE;AAE9G,YAAI,IAAI,WAAW,mBAAmB;AACpC,eAAK,OAAO,eAAe,WAAW,EAAE,cAAc,IAAI,aAAa,CAAC;AACxE,eAAK,IAAI,mBAAc,IAAI,YAAY,4CAA4C;AAAA,QACrF;AAAA,MACF;AAEA,aAAO,EAAE,IAAI,IAAI,IAAI,aAAa,IAAI,YAAY;AAAA,IAEpD,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,SAAS;AAClC,aAAO,EAAE,IAAI,OAAO,OAAO,IAAI,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,eAAe,aAAoD;AACjE,QAAI,KAAK,mBAAmB;AAC1B,WAAK,IAAI,4BAA4B;AACrC;AAAA,IACF;AAEA,QAAI,KAAK,WAAW,YAAY,KAAK,WAAW,iBAAiB;AAC/D,YAAM,IAAI,WAAW,qCAAqC,KAAK,MAAM,MAAM,KAAK,MAAM;AAAA,IACxF;AAEA,UAAM,cAAc,KAAK,OAAO,wBAAwB,KAAK,OAAO,sBAAsB;AAC1F,SAAK,IAAI,iCAAiC,WAAW,OAAO;AAG5D,QAAI,oBAAoB;AACxB,QAAI,YAAY;AAEhB,SAAK,oBAAoB,YAAY,YAAY;AAC/C,UAAI,YAAY,GAAG;AACjB;AACA;AAAA,MACF;AAEA,UAAI;AACF,cAAM,YAAY,cAAc,MAAM,YAAY,IAAI;AACtD,cAAM,KAAK,UAAU,SAAS;AAC9B,4BAAoB;AAAA,MACtB,SAAS,KAAU;AACjB;AACA,aAAK,OAAO,QAAQ,KAAK,WAAW;AACpC,oBAAY,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,oBAAoB,CAAC,CAAC;AAC3D,aAAK,IAAI,oBAAoB,iBAAiB,iBAAiB,SAAS,QAAQ;AAAA,MAClF;AAAA,IACF,GAAG,cAAc,GAAI;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAsB;AACpB,QAAI,KAAK,mBAAmB;AAC1B,oBAAc,KAAK,iBAAiB;AACpC,WAAK,oBAAoB;AACzB,WAAK,IAAI,oBAAoB;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAA4E;AAChF,YAAQ,KAAK,sFAAsF;AACnG,QAAI;AACF,WAAK,IAAI,iCAAiC;AAG1C,YAAM,YAAY,MAAM,KAAK,IAAI,QAAQ,wBAAwB;AAAA,QAC/D,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,UAAU,WAAW;AACxB,eAAO,EAAE,IAAI,OAAO,OAAO,0BAA0B;AAAA,MACvD;AAEA,YAAM,WAAW,UAAU,UAAU;AACrC,WAAK,aAAa,UAAU,UAAU;AACtC,WAAK,IAAI,8BAA8B,QAAQ,eAAe,KAAK,UAAU,EAAE;AAG/E,YAAM,KAAK,WAAW;AAGtB,YAAM,YAAY,UAAU,UAAU;AACtC,YAAM,YAAY,UAAU,UAAU;AAGtC,WAAK,aAAa,EAAE,OAAO,WAAW,MAAM,WAAW,MAAM,IAAI,WAAW,KAAK,IAAI,EAAE;AACvF,WAAK,QAAQ,CAAC,KAAK,UAAU;AAE7B,YAAM,KAAK,KAAK,IAAI;AACpB,WAAK,aAAa,QAAQ;AAC1B,YAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,WAAK,IAAI,6BAA6B,OAAO,IAAI;AAGjD,YAAM,QAAQ,MAAM,KAAK,IAAI,QAAQ,wBAAwB;AAAA,QAC3D,QAAQ;AAAA,QACR,iBAAiB,UAAU,UAAU;AAAA,QACrC,OAAO;AAAA,UACL,WAAW;AAAA,UACX,SAAS,KAAK,WAAY;AAAA,UAC1B,WAAW;AAAA,UACX,SAAS,KAAK,WAAY;AAAA,UAC1B,gBAAgB;AAAA,UAChB,eAAe,UAAU,UAAU;AAAA,UACnC,aAAa,KAAK,oBAAoB;AAAA,UACtC,cAAc,MAAM;AAElB,kBAAM,cAAc,KAAK,MAAM,KAAK,OAAK,EAAE,UAAU,KAAK,WAAY,KAAK;AAE3E,kBAAM,YAAY,KAAK,MACpB,OAAO,OAAK,EAAE,UAAU,KAAK,WAAY,SAAS,EAAE,QAAQ,SAAS;AACxE,kBAAM,OAAO,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,SAAS,CAAC,CAAC;AACxD,kBAAM,SAAS,UACZ,OAAO,CAAC,GAAG,MAAM,IAAI,SAAS,CAAC,EAC/B,MAAM,GAAG,CAAC;AACb,kBAAM,SAAS,cAAc,CAAC,aAAa,GAAG,MAAM,IAAI;AACxD,mBAAO,OAAO,IAAI,QAAM,EAAE,OAAO,EAAE,OAAO,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE;AAAA,UACzF,GAAG;AAAA,QACL;AAAA,MACF,CAAC;AAED,UAAI,MAAM,IAAI;AACZ,aAAK,SAAS;AACd,aAAK,aAAa,MAAM;AACxB,aAAK,kBAAkB,KAAK,WAAY;AACxC,aAAK,OAAO,eAAe,UAAU,EAAE,UAAU,KAAK,CAAC;AACvD,aAAK,IAAI,sDAAiD;AAAA,MAC5D;AAEA,aAAO,EAAE,IAAI,MAAM,IAAI,gBAAgB,SAAS;AAAA,IAElD,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,QAAQ;AACjC,aAAO,EAAE,IAAI,OAAO,OAAO,IAAI,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,WAAoB,WAA0C;AAC/E,QAAI;AAEF,UAAI,cAAc,QAAW;AAC3B,YAAI,OAAO,cAAc,YAAY,UAAU,KAAK,EAAE,WAAW,GAAG;AAClE,gBAAM,IAAI,gBAAgB,sCAAsC;AAAA,QAClE;AACA,YAAI,UAAU,SAAS,IAAI;AACzB,gBAAM,IAAI,gBAAgB,0CAA0C;AAAA,QACtE;AAAA,MACF;AAEA,YAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,uBAAuB;AAAA,QACxD,YAAY;AAAA,QACZ,YAAY;AAAA,MACd,CAAC;AAED,UAAI,IAAI,aAAa,OAAO;AAC1B,aAAK,IAAI,yBAAyB,IAAI,YAAY,WAAW,IAAI,OAAO,cAAc;AAAA,MACxF,WAAW,IAAI,IAAI;AACjB,aAAK,IAAI,kBAAkB,IAAI,YAAY,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,MAC9D;AAEA,aAAO;AAAA,IACT,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,OAAO;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,cAAc,gBAAsD,WAA0C;AAClH,QAAI;AAEJ,QAAI,OAAO,mBAAmB,UAAU;AAEtC,UAAI,CAAC,kBAAkB,CAAC,CAAC,eAAe,cAAc,cAAc,EAAE,SAAS,cAAc,GAAG;AAC9F,cAAM,IAAI,gBAAgB,gEAAgE;AAAA,MAC5F;AACA,UAAI,CAAC,aAAa,OAAO,cAAc,UAAU;AAC/C,cAAM,IAAI,gBAAgB,uEAAuE;AAAA,MACnG;AACA,aAAO;AAAA,QACL,gBAAgB;AAAA,QAChB,YAAY;AAAA;AAAA;AAAA,MAGd;AAAA,IACF,OAAO;AAEL,YAAM,OAAO;AACb,UAAI,CAAC,KAAK,kBAAkB,CAAC,CAAC,eAAe,cAAc,cAAc,EAAE,SAAS,KAAK,cAAc,GAAG;AACxG,cAAM,IAAI,gBAAgB,iEAAiE;AAAA,MAC7F;AACA,UAAI,CAAC,KAAK,aAAa,OAAO,KAAK,cAAc,UAAU;AACzD,cAAM,IAAI,gBAAgB,uBAAuB;AAAA,MACnD;AACA,UAAI,CAAC,KAAK,QAAQ,CAAC,CAAC,OAAO,OAAO,OAAO,OAAO,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG;AAC1E,cAAM,IAAI,gBAAgB,8CAA8C;AAAA,MAC1E;AACA,UAAI,CAAC,KAAK,cAAc,OAAO,KAAK,eAAe,UAAU;AAC3D,cAAM,IAAI,gBAAgB,wBAAwB;AAAA,MACpD;AAEA,aAAO,EAAE,GAAG,KAAK;AAAA,IACnB;AAEA,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,iBAAiB,IAAI;AAExD,UAAI,IAAI,eAAe;AACrB,aAAK,cAAc,IAAI;AAAA,MACzB;AAEA,YAAM,WAAW,IAAI,OAAO,SAAS,IAAI,OAAO,kBAAkB;AAClE,WAAK,IAAI,oBAAoB,QAAQ,EAAE;AACvC,WAAK,OAAO,eAAe,gBAAgB,EAAE,OAAO,SAAS,CAAC;AAE9D,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,IAAI;AAAA,QACX,eAAe,IAAI;AAAA,QACnB,KAAK,IAAI;AAAA,MACX;AAAA,IACF,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,eAAe;AACxC,aAAO,EAAE,IAAI,OAAO,OAAO,IAAI,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,QAAoE;AACvF,QAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AAC/C,YAAM,IAAI,gBAAgB,yCAAyC;AAAA,IACrE;AAEA,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI,SAAS,0BAA0B,MAAM;AACpE,WAAK,IAAI,qBAAqB,IAAI,gBAAgB,KAAK,IAAI,KAAK,SAAS,EAAE;AAC3E,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,IAAI;AAAA,QACX,YAAY,IAAI;AAAA,QAChB,gBAAgB,IAAI;AAAA,MACtB;AAAA,IACF,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,gBAAgB;AACzC,aAAO,EAAE,IAAI,OAAO,OAAO,IAAI,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,UAAU,WAAoB,cAAiD;AACnF,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,2BAA2B;AAAA,QAC5D,YAAY,aAAa;AAAA,QACzB,eAAe;AAAA,MACjB,CAAC;AAED,UAAI,IAAI,eAAe;AACrB,aAAK,cAAc,IAAI;AAAA,MACzB;AAEA,UAAI,IAAI,IAAI;AACV,aAAK,SAAS;AACd,cAAM,OAAO,KAAK,OAAO,eAAe,KAAK,OAAO;AACpD,YAAI,KAAM,MAAK,GAAG;AAClB,aAAK,IAAI,6BAA6B,IAAI,aAAa,WAAW,IAAI,qBAAqB,EAAE;AAAA,MAC/F;AAEA,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,eAAe,IAAI;AAAA,QACnB,uBAAuB,IAAI;AAAA,QAC3B,eAAe,IAAI;AAAA,QACnB,cAAc,IAAI;AAAA,QAClB,KAAK,IAAI;AAAA,MACX;AAAA,IACF,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,WAAW;AACpC,aAAO,EAAE,IAAI,OAAO,OAAO,IAAI,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,WAA4F;AAC7G,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,+BAA+B;AAAA,QAChE,YAAY,aAAa;AAAA,MAC3B,CAAC;AAED,UAAI,IAAI,eAAe;AACrB,aAAK,cAAc,IAAI;AAAA,MACzB;AAEA,aAAO,EAAE,IAAI,MAAM,eAAe,IAAI,cAAc;AAAA,IACtD,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,cAAc;AACvC,aAAO,EAAE,IAAI,OAAO,OAAO,IAAI,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAsC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAO,mBAAmB,OAAqB,oBAA4B,aAA0C;AACnH,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,UAAU,MAAM,MAAM;AAE5B,QAAI,iBAAiB;AACrB,QAAI;AAEF,YAAM,YAAY,KAAK,UAAU;AAAA,QAC/B,YAAY,MAAM;AAAA,QAClB,kBAAkB,MAAM;AAAA,QACxB,gBAAgB,MAAM;AAAA,QACtB,oBAAoB,MAAM;AAAA,QAC1B,sBAAsB,MAAM;AAAA,QAC5B,qBAAqB,MAAM;AAAA,QAC3B,oBAAoB,MAAM;AAAA,QAC1B,WAAW,MAAM;AAAA,QACjB,aAAa,MAAM;AAAA,MACrB,CAAC;AAGD,YAAM,WAAW,OAAO,KAAK,oBAAoB,KAAK;AACtD,UAAI,SAAS,WAAW,IAAI;AAC1B,cAAM,sBAAsB,OAAO,KAAK,4BAA4B,KAAK;AACzE,cAAM,YAAY,OAAO,OAAO,CAAC,qBAAqB,QAAQ,CAAC;AAC/D,cAAM,gBAAY,+BAAgB,EAAE,KAAK,WAAW,QAAQ,OAAO,MAAM,OAAO,CAAC;AACjF,cAAM,YAAY,OAAO,KAAK,MAAM,sBAAsB,KAAK;AAC/D,6BAAiB,sBAAO,MAAM,OAAO,KAAK,SAAS,GAAG,WAAW,SAAS;AAAA,MAC5E;AAAA,IACF,QAAQ;AACN,uBAAiB;AAAA,IACnB;AAEA,UAAM,QAAQ,kBAAkB,CAAC;AACjC,UAAM,sBAAsB,eAAe,OAAO,cAAc,MAAM,sBAAsB;AAE5F,QAAI;AACJ,QAAI,SAAS;AACX,gBAAU;AAAA,IACZ,WAAW,uBAAuB,QAAQ,sBAAsB,IAAI;AAClE,gBAAU,YAAY,mBAAmB;AAAA,IAC3C;AAEA,WAAO,EAAE,OAAO,gBAAgB,SAAS,mBAAmB,MAAM,qBAAqB,qBAAqB,QAAQ;AAAA,EACtH;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAkC;AACtC,QAAI;AAIF,aAAO,MAAM,KAAK,aAAa;AAAA,IACjC,SAAS,KAAU;AACjB,WAAK,OAAO,QAAQ,KAAK,QAAQ;AACjC,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAQE;AACA,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK,YAAY,SAAS;AAAA,MACtC,YAAY,KAAK,YAAY,KAAK,MAAM,GAAG,EAAE,IAAI,SAAS;AAAA,MAC1D,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK,MAAM;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA,EAIA,MAAc,aAA4B;AACxC,QAAI;AAEF,YAAM,aAAa,IAAI,gBAAgB;AACvC,YAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,IAAM;AAC3D,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,WAAW,uBAAuB,EAAE,QAAQ,WAAW,OAAO,CAAC;AACtG,mBAAa,OAAO;AACpB,YAAM,OAAY,MAAM,IAAI,KAAK;AACjC,UAAI,KAAK,QAAQ;AACf,aAAK,aAAa,KAAK,OAAO;AAC9B,aAAK,mBAAmB,KAAK,OAAO,QAAQ;AAC5C,YAAI,KAAK,OAAO,WAAY,MAAK,aAAa,KAAK,OAAO;AAC1D,aAAK,IAAI,yBAAyB,KAAK,UAAU,OAAO,KAAK,UAAU,GAAG;AAAA,MAC5E;AAAA,IACF,QAAQ;AACN,WAAK,IAAI,uDAAuD;AAAA,IAClE;AAAA,EACF;AAAA,EAEA,MAAc,eAA6B;AACzC,UAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,oBAAoB;AACvD,QAAI,IAAI,qBAAqB;AAC3B,WAAK,aAAa,IAAI;AACtB,WAAK,cAAc,IAAI;AACvB,WAAK,SAAS,IAAI;AAClB,WAAK,aAAa,IAAI,cAAc,KAAK;AACzC,WAAK,kBAAkB,IAAI,qBAAqB;AAGhD,UAAI,CAAC,KAAK,cAAc,KAAK,aAAa;AACxC,aAAK,aAAa;AAAA,UAChB,OAAO,IAAI,eAAe,KAAK;AAAA,UAC/B,MAAM,IAAI,eAAe,KAAK;AAAA,UAC9B,MAAM,IAAI,OAAO,EAAE;AAAA,UACnB,WAAW,KAAK,IAAI;AAAA,QACtB;AACA,aAAK,QAAQ,CAAC,KAAK,UAAU;AAAA,MAC/B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,IAAI,QAAgB,MAAc,MAA0B;AAExE,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,GAAM;AAE3D,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,WAAW,GAAG,IAAI,IAAI;AAAA,QAC3D;AAAA,QACA,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB,UAAU,KAAK,OAAO,MAAM;AAAA,QAC/C;AAAA,QACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,QACpC,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI;AACJ,UAAI;AACF,eAAO,MAAM,IAAI,KAAK;AAAA,MACxB,QAAQ;AACN,cAAM,IAAI,aAAa,cAAc,IAAI,MAAM,2BAA2B,IAAI,EAAE;AAAA,MAClF;AAEA,UAAI,CAAC,IAAI,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK,uBAAuB,CAAC,KAAK,UAAU;AACtE,cAAM,YAAY,IAAI,QAAQ,MAAM,IAAI;AAAA,MAC1C;AAEA,aAAO;AAAA,IACT,SAAS,KAAU;AACjB,UAAI,IAAI,SAAS,cAAc;AAC7B,cAAM,IAAI,aAAa,oBAAoB,MAAM,IAAI,IAAI,2BAAqB;AAAA,MAChF;AACA,YAAM;AAAA,IACR,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,IAAI,KAAmB;AAC7B,QAAI,KAAK,OAAO,SAAS;AACvB,cAAQ,IAAI,UAAU,GAAG,EAAE;AAAA,IAC7B;AAAA,EACF;AACF;AAWO,SAAS,iBACd,WACA,YACA,OACA,aAAqB,KACrB,YACqC;AAErC,MAAI,CAAC,aAAa,OAAO,cAAc,UAAU;AAC/C,UAAM,IAAI,gBAAgB,wDAAwD;AAAA,EACpF;AACA,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAM,IAAI,gBAAgB,oDAAoD;AAAA,EAChF;AAEA,QAAM,KAAK,KAAK,IAAI;AACpB,MAAI,OAAO;AACX,MAAI,WAAwB;AAE5B,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,eAAW,YAAY,MAAM,aAAa,GAAG,YAAY,QAAW,UAAU;AAC9E,WAAO,SAAS;AAAA,EAClB;AAEA,SAAO,EAAE,UAAqB,SAAS,KAAK,IAAI,IAAI,GAAG;AACzD;","names":["ErrorCode","res","data"]}
|
package/dist/index.mjs
CHANGED
|
@@ -143,6 +143,12 @@ async function register(name, options) {
|
|
|
143
143
|
if (options?.registrationSecret) {
|
|
144
144
|
headers["x-registration-secret"] = options.registrationSecret;
|
|
145
145
|
}
|
|
146
|
+
if (options?.registrationToken) {
|
|
147
|
+
headers["x-registration-token"] = options.registrationToken;
|
|
148
|
+
}
|
|
149
|
+
if (options?.registrationInvite) {
|
|
150
|
+
headers["x-registration-invite"] = options.registrationInvite;
|
|
151
|
+
}
|
|
146
152
|
if (options?.parentHash) {
|
|
147
153
|
if (options.parentApiKey) {
|
|
148
154
|
headers["Authorization"] = `Bearer ${options.parentApiKey}`;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/beat-sdk.ts","../src/errors.ts"],"sourcesContent":["/**\r\n * ═══════════════════════════════════════════════════════════\r\n * PROVENONCE BEAT SDK — Agent Heartbeat Client\r\n * ═══════════════════════════════════════════════════════════\r\n * \r\n * \"NIST tells you what time it is.\r\n * Provenonce tells the agent at what speed it is allowed to exist.\"\r\n * \r\n * Usage:\r\n * \r\n * import { BeatAgent } from './beat-sdk';\r\n * \r\n * const agent = new BeatAgent({\r\n * apiKey: 'pvn_...',\r\n * registryUrl: 'https://provenonce.io',\r\n * });\r\n * \r\n * await agent.init(); // Birth in Beat time\r\n * await agent.pulse(50); // Compute 50 beats\r\n * await agent.checkin(); // Report to registry\r\n * \r\n * // Or run the autonomous heartbeat:\r\n * agent.startHeartbeat(); // Computes + checks in continuously\r\n * // ... do your agent work ...\r\n * agent.stopHeartbeat();\r\n * \r\n * ═══════════════════════════════════════════════════════════\r\n */\r\n\r\nimport { createHash, generateKeyPairSync, sign, verify, createPrivateKey, createPublicKey } from 'crypto';\r\nimport {\r\n ValidationError,\r\n AuthError,\r\n RateLimitError,\r\n FrozenError,\r\n StateError,\r\n NetworkError,\r\n ServerError,\r\n mapApiError,\r\n ErrorCode,\r\n} from './errors';\r\n\r\n// ============ PHASE 2 TYPES ============\r\n\r\n/** SIGIL identity class — determines tier pricing and heartbeat volume caps */\r\nexport type IdentityClass = 'narrow_task' | 'autonomous' | 'orchestrator';\r\n\r\n/** SIGIL trust governance tier — orthogonal to identity_class (fee axis) */\r\nexport type SigilTier = 'sov' | 'org' | 'ind' | 'eph' | 'sbx';\r\n\r\n/** Substrate — what the agent runs on */\r\nexport type Substrate = 'frontier' | 'open' | 'local' | 'symbolic' | 'hybrid' | 'human';\r\n\r\n/** Substrate provider */\r\nexport type SubstrateProvider = 'anthropic' | 'openai' | 'google' | 'meta' | 'mistral' | 'xai' | 'cohere' | 'deepseek' | 'custom';\r\n\r\n/** Capability — what the agent primarily does */\r\nexport type Capability = 'analyst' | 'executor' | 'orchestrator' | 'guardian' | 'retriever' | 'renderer' | 'witness';\r\n\r\n/** Protocol — how to reach the agent */\r\nexport type SigilProtocol = 'http' | 'grpc' | 'websocket' | 'mcp' | 'a2a' | 'custom';\r\n\r\n/** Compliance regime */\r\nexport type ComplianceRegime = 'gdpr' | 'pdpa' | 'hipaa' | 'sox' | 'aisi' | 'none' | 'custom';\r\n\r\n/**\r\n * Ed25519-signed lineage proof — portable, offline-verifiable credential.\r\n * Also known as the agent's \"passport\" — a cryptographic proof of identity\r\n * that can be verified offline without any API call or SOL cost.\r\n */\r\nexport interface LineageProof {\r\n agent_hash: string;\r\n agent_public_key: string | null;\r\n identity_class: IdentityClass;\r\n registered_at_beat: number;\r\n sigil_issued_at_beat: number | null;\r\n last_heartbeat_beat: number;\r\n lineage_chain_hash: string;\r\n issued_at: number;\r\n valid_until: number;\r\n provenonce_signature: string;\r\n}\r\n\r\n/** Passport = LineageProof. The agent's portable, offline-verifiable credential. */\r\nexport type Passport = LineageProof;\r\n\r\n/** Options for purchasing a SIGIL with full namespace */\r\nexport interface SigilPurchaseOptions {\r\n identity_class: IdentityClass;\r\n principal: string;\r\n tier: SigilTier;\r\n name?: string; // \"auto\" or custom name\r\n payment_tx: string;\r\n // Optional initial metadata\r\n substrate?: Substrate;\r\n substrate_provider?: SubstrateProvider;\r\n substrate_model?: string;\r\n capability?: Capability;\r\n capability_scope?: string;\r\n tools?: string[];\r\n modality_input?: string[];\r\n modality_output?: string[];\r\n protocol?: SigilProtocol;\r\n endpoint?: string;\r\n compliance_regime?: ComplianceRegime;\r\n}\r\n\r\n/** Mutable SIGIL metadata fields for PATCH updates */\r\nexport interface SigilMutableFields {\r\n substrate?: Substrate;\r\n substrate_provider?: SubstrateProvider;\r\n substrate_model?: string;\r\n capability?: Capability;\r\n capability_scope?: string;\r\n generation_trigger?: string;\r\n tools?: string[];\r\n modality_input?: string[];\r\n modality_output?: string[];\r\n protocol?: SigilProtocol;\r\n endpoint?: string;\r\n compliance_regime?: ComplianceRegime;\r\n}\r\n\r\n/** Result from purchasing a SIGIL (Structured Identity Governance and Intelligent Lookup) */\r\nexport interface SigilResult {\r\n ok: boolean;\r\n sigil?: {\r\n sigil: string; // Full SIGIL string: name*principal*tier\r\n sigil_name: string;\r\n principal: string;\r\n tier: SigilTier;\r\n identity_class: IdentityClass;\r\n issued_at_beat: number;\r\n birth_tx: string | null;\r\n explorer_url: string | null;\r\n };\r\n lineage_proof?: LineageProof;\r\n fee?: {\r\n amount_sol: number;\r\n amount_lamports: number;\r\n payment_tx: string | null;\r\n };\r\n error?: string;\r\n}\r\n\r\n/** Result from updating mutable SIGIL metadata */\r\nexport interface MetadataUpdateResult {\r\n ok: boolean;\r\n sigil?: string;\r\n generation?: number;\r\n updated_fields?: string[];\r\n error?: string;\r\n}\r\n\r\n/** Result from offline lineage proof verification */\r\nexport interface VerificationResult {\r\n /** Overall validity: signature is valid AND not expired */\r\n valid: boolean;\r\n /** Ed25519 signature verification passed */\r\n signatureValid: boolean;\r\n /** Proof has passed its valid_until timestamp */\r\n expired: boolean;\r\n /** The beat index of the agent's last heartbeat */\r\n lastHeartbeatBeat: number;\r\n /** Beats elapsed since last heartbeat (null if currentBeat not provided) */\r\n beatsSinceHeartbeat: number | null;\r\n /** Human-readable warning if proof is expired or stale */\r\n warning?: string;\r\n}\r\n\r\n/** Result from a paid heartbeat */\r\nexport interface HeartbeatResult {\r\n ok: boolean;\r\n lineage_proof?: LineageProof;\r\n heartbeat_count_epoch?: number;\r\n billing_epoch?: number;\r\n current_beat?: number;\r\n fee?: {\r\n amount_sol: number;\r\n amount_lamports: number;\r\n tier: number;\r\n payment_tx: string | null;\r\n };\r\n error?: string;\r\n}\r\n\r\n// ============ VDF ENGINE (LOCAL) ============\r\n\r\nexport interface Beat {\r\n index: number;\r\n hash: string;\r\n prev: string;\r\n timestamp: number;\r\n nonce?: string;\r\n anchor_hash?: string;\r\n}\r\n\r\nfunction computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string, anchorHash?: string): Beat {\r\n const timestamp = Date.now();\r\n\r\n const seed = anchorHash\r\n ? `${prevHash}:${beatIndex}:${nonce || ''}:${anchorHash}`\r\n : `${prevHash}:${beatIndex}:${nonce || ''}`;\r\n\r\n let current = createHash('sha256')\r\n .update(seed)\r\n .digest('hex');\r\n\r\n for (let i = 0; i < difficulty; i++) {\r\n current = createHash('sha256')\r\n .update(current)\r\n .digest('hex');\r\n }\r\n\r\n return { index: beatIndex, hash: current, prev: prevHash, timestamp, nonce, anchor_hash: anchorHash };\r\n}\r\n\r\n// ============ SDK RESULT TYPES ============\r\n\r\n/** Result from a check-in submission */\r\nexport interface CheckinResult {\r\n ok: boolean;\r\n total_beats: number;\r\n beats_accepted: number;\r\n global_beat: number;\r\n status?: string;\r\n beats_behind?: number;\r\n}\r\n\r\n/** Result from a spawn request */\r\nexport interface SpawnResult {\r\n ok: boolean;\r\n eligible: boolean;\r\n child_hash?: string;\r\n progress_pct?: number;\r\n deficit?: number;\r\n}\r\n\r\n/** Agent status from the registry */\r\nexport interface AgentStatus {\r\n already_initialized: boolean;\r\n total_beats: number;\r\n genesis_hash: string;\r\n status: string;\r\n genesis?: { hash: string; prev: string; timestamp: number };\r\n difficulty?: number;\r\n}\r\n\r\n// ============ WALLET KEYPAIR GENERATION ============\r\n\r\n// DER prefix for Ed25519 PKCS8 private keys (16 bytes)\r\nconst ED25519_PKCS8_PREFIX = Buffer.from('302e020100300506032b657004220420', 'hex');\r\n\r\n/**\r\n * Generate an Ed25519 keypair for agent wallet identity.\r\n * Returns hex-encoded raw keys (32 bytes each).\r\n * Uses Node.js built-in crypto — zero external dependencies.\r\n */\r\nexport function generateWalletKeypair(): { publicKey: string; secretKey: string } {\r\n const { publicKey, privateKey } = generateKeyPairSync('ed25519');\r\n const pubRaw = publicKey.export({ type: 'spki', format: 'der' }).subarray(12); // 32 bytes\r\n const privRaw = privateKey.export({ type: 'pkcs8', format: 'der' }).subarray(16); // 32 bytes\r\n return {\r\n publicKey: Buffer.from(pubRaw).toString('hex'),\r\n secretKey: Buffer.from(privRaw).toString('hex'),\r\n };\r\n}\r\n\r\n/**\r\n * Sign a message with an Ed25519 private key (hex-encoded 32-byte seed).\r\n * Returns hex-encoded signature (64 bytes).\r\n */\r\nfunction signMessage(secretKeyHex: string, message: string): string {\r\n const privRaw = Buffer.from(secretKeyHex, 'hex');\r\n const privKeyDer = Buffer.concat([ED25519_PKCS8_PREFIX, privRaw]);\r\n const keyObject = createPrivateKey({ key: privKeyDer, format: 'der', type: 'pkcs8' });\r\n const sig = sign(null, Buffer.from(message), keyObject);\r\n return Buffer.from(sig).toString('hex');\r\n}\r\n\r\n// ============ REGISTRATION ============\r\n\r\n/** Wallet info returned from root registration */\r\nexport interface WalletInfo {\r\n /** Hex-encoded 32-byte Ed25519 public key (Solana self-custody only, empty otherwise) */\r\n public_key: string;\r\n /** Hex-encoded 32-byte Ed25519 secret seed — SAVE THIS for future fee signing (Solana self-custody only) */\r\n secret_key: string;\r\n /** Solana-compatible base58 address (Solana wallets only) */\r\n solana_address?: string;\r\n /** The wallet address (base58 for Solana, 0x for Ethereum) */\r\n address: string;\r\n /** Wallet chain: 'solana' or 'ethereum' */\r\n chain: string;\r\n}\r\n\r\n/** Result from registering an agent */\r\nexport interface RegistrationResult {\r\n hash: string;\r\n api_key: string;\r\n secret: string;\r\n type: 'root' | 'agent';\r\n parent: string | null;\r\n depth: number;\r\n name: string;\r\n metadata?: Record<string, unknown> | null;\r\n /** @deprecated No Solana write at registration (D-65). Will be null. */\r\n signature?: string | null;\r\n /** @deprecated No Solana write at registration (D-65). Will be null. */\r\n explorer_url?: string | null;\r\n /** Wallet chain: 'solana', 'ethereum', or null (no wallet) */\r\n wallet_chain?: string | null;\r\n beat?: { genesis_hash: string; difficulty: number; status: string };\r\n /** Wallet info — only present for root agents with wallets */\r\n wallet?: WalletInfo;\r\n /** Next steps after registration */\r\n _next_steps?: { sigil?: string; heartbeat?: string };\r\n}\r\n\r\n/**\r\n * Register a new agent on the Provenonce registry.\r\n *\r\n * No wallet (default, single-phase):\r\n * const creds = await register('my-agent', { registryUrl: '...' });\r\n *\r\n * Solana self-custody wallet (Model A, two-phase):\r\n * const creds = await register('my-org', {\r\n * registryUrl: '...',\r\n * walletModel: 'self-custody',\r\n * });\r\n * // creds.wallet.secret_key = hex secret (SAVE THIS)\r\n * // creds.wallet.address = base58 Solana address\r\n *\r\n * Solana with existing key:\r\n * const creds = await register('my-org', {\r\n * registryUrl: '...',\r\n * walletSecretKey: '<hex-encoded-32-byte-seed>',\r\n * });\r\n *\r\n * Ethereum bring-your-own (two-phase):\r\n * const creds = await register('my-org', {\r\n * registryUrl: '...',\r\n * walletChain: 'ethereum',\r\n * walletAddress: '0x...',\r\n * walletSignFn: (msg) => wallet.signMessage(msg),\r\n * });\r\n *\r\n * Solana operator (Model B, two-phase):\r\n * const creds = await register('my-org', {\r\n * registryUrl: '...',\r\n * walletModel: 'operator',\r\n * operatorWalletAddress: '<base58>',\r\n * operatorSignFn: (msg) => signWithWallet(msg),\r\n * });\r\n *\r\n * Child agent (no wallet):\r\n * const creds = await register('worker-1', {\r\n * registryUrl: '...',\r\n * parentHash: parentCreds.hash,\r\n * parentApiKey: parentCreds.api_key,\r\n * });\r\n */\r\nexport async function register(\r\n name: string,\r\n options?: {\r\n registryUrl?: string;\r\n parentHash?: string;\r\n parentApiKey?: string;\r\n registrationSecret?: string;\r\n /** Hex-encoded 32-byte Ed25519 secret seed (bring-your-own Solana key) */\r\n walletSecretKey?: string;\r\n /** Wallet model: 'self-custody' (Model A) or 'operator' (Model B). Must be set explicitly to opt in. */\r\n walletModel?: 'self-custody' | 'operator';\r\n /** Wallet chain: 'solana' (default when wallet is used) or 'ethereum' (D-63) */\r\n walletChain?: 'solana' | 'ethereum';\r\n /** Wallet address for Ethereum bring-your-own (0x + 40 hex chars) */\r\n walletAddress?: string;\r\n /** Async function to sign a message with an Ethereum wallet (EIP-191 personal_sign). Returns 0x-prefixed 65-byte hex sig. */\r\n walletSignFn?: (message: string) => Promise<string>;\r\n /** Operator's Solana wallet address (base58). Required when walletModel='operator'. */\r\n operatorWalletAddress?: string;\r\n /** Function to sign a message with the operator's Solana wallet. Required when walletModel='operator'. */\r\n operatorSignFn?: (message: string) => Promise<string>;\r\n /** Optional agent metadata (arbitrary JSON object, max 4KB). Returned in /verify and /status. */\r\n metadata?: Record<string, unknown>;\r\n },\r\n): Promise<RegistrationResult> {\r\n // SDK-P1-07/P1-08: validate inputs\r\n if (!name || typeof name !== 'string' || name.trim().length === 0) {\r\n throw new ValidationError('name is required (must be a non-empty string)');\r\n }\r\n if (name.length > 64) {\r\n throw new ValidationError('name must be 64 characters or fewer');\r\n }\r\n\r\n const url = options?.registryUrl || 'https://provenonce.io';\r\n try {\r\n new URL(url);\r\n } catch {\r\n throw new ValidationError('registryUrl is not a valid URL');\r\n }\r\n\r\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\r\n\r\n if (options?.registrationSecret) {\r\n headers['x-registration-secret'] = options.registrationSecret;\r\n }\r\n\r\n // ===== CHILD REGISTRATION (no wallet, single-phase) =====\r\n if (options?.parentHash) {\r\n if (options.parentApiKey) {\r\n headers['Authorization'] = `Bearer ${options.parentApiKey}`;\r\n }\r\n\r\n const res = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, parent: options.parentHash, ...(options.metadata && { metadata: options.metadata }) }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string };\r\n try {\r\n data = await res.json() as RegistrationResult & { error?: string };\r\n } catch {\r\n throw new NetworkError(`Registration failed: ${res.status} ${res.statusText} (non-JSON response)`);\r\n }\r\n if (!res.ok) throw mapApiError(res.status, data, '/api/v1/register');\r\n return data;\r\n }\r\n\r\n // ===== ETHEREUM BRING-YOUR-OWN (D-63, two-phase) =====\r\n if (options?.walletChain === 'ethereum') {\r\n if (!options.walletAddress || !options.walletSignFn) {\r\n throw new ValidationError('Ethereum registration requires walletAddress and walletSignFn');\r\n }\r\n\r\n if (!/^0x[0-9a-fA-F]{40}$/.test(options.walletAddress)) {\r\n throw new ValidationError('walletAddress must be a valid Ethereum address (0x + 40 hex chars)');\r\n }\r\n\r\n // Phase 1: Get challenge nonce from server\r\n const challengeRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, action: 'challenge', wallet_chain: 'ethereum' }),\r\n });\r\n\r\n let challengeData: { nonce?: string; error?: string };\r\n try {\r\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\r\n } catch {\r\n throw new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\r\n }\r\n if (!challengeRes.ok || !challengeData.nonce) {\r\n throw mapApiError(challengeRes.status, challengeData, '/api/v1/register');\r\n }\r\n\r\n // Phase 2: Sign with Ethereum wallet (EIP-191 personal_sign)\r\n const nonce = challengeData.nonce;\r\n const message = `provenonce-register-ethereum:${nonce}:${options.walletAddress}:${name}`;\r\n const walletSignature = await options.walletSignFn(message);\r\n\r\n const registerRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({\r\n name,\r\n wallet_chain: 'ethereum',\r\n wallet_address: options.walletAddress,\r\n wallet_signature: walletSignature,\r\n wallet_nonce: nonce,\r\n ...(options.metadata && { metadata: options.metadata }),\r\n }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; chain?: string } };\r\n try {\r\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; chain?: string } };\r\n } catch {\r\n throw new NetworkError(`Ethereum registration failed: ${registerRes.status} (non-JSON response)`);\r\n }\r\n if (!registerRes.ok) throw mapApiError(registerRes.status, data, '/api/v1/register');\r\n\r\n // Ethereum: wallet has address only (no keypair — user keeps custody externally)\r\n data.wallet = {\r\n public_key: '',\r\n secret_key: '',\r\n address: data.wallet?.address || options.walletAddress,\r\n chain: 'ethereum',\r\n };\r\n\r\n return data;\r\n }\r\n\r\n // ===== MODEL B: SOLANA OPERATOR WALLET REGISTRATION (two-phase) =====\r\n if (options?.walletModel === 'operator') {\r\n if (!options.operatorWalletAddress || !options.operatorSignFn) {\r\n throw new ValidationError('Operator registration requires operatorWalletAddress and operatorSignFn');\r\n }\r\n\r\n // Phase 1: Get challenge nonce from server\r\n const challengeRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, action: 'challenge', wallet_model: 'operator' }),\r\n });\r\n\r\n let challengeData: { nonce?: string; error?: string };\r\n try {\r\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\r\n } catch {\r\n throw new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\r\n }\r\n if (!challengeRes.ok || !challengeData.nonce) {\r\n throw mapApiError(challengeRes.status, challengeData, '/api/v1/register');\r\n }\r\n\r\n // Phase 2: Operator signs challenge and register\r\n const nonce = challengeData.nonce;\r\n const message = `provenonce-register-operator:${nonce}:${options.operatorWalletAddress}:${name}`;\r\n const walletSignature = await options.operatorSignFn(message);\r\n\r\n const registerRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({\r\n name,\r\n wallet_model: 'operator',\r\n operator_wallet_address: options.operatorWalletAddress,\r\n wallet_signature: walletSignature,\r\n wallet_nonce: nonce,\r\n ...(options.metadata && { metadata: options.metadata }),\r\n }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\r\n try {\r\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\r\n } catch {\r\n throw new NetworkError(`Operator registration failed: ${registerRes.status} (non-JSON response)`);\r\n }\r\n if (!registerRes.ok) throw mapApiError(registerRes.status, data, '/api/v1/register');\r\n\r\n // Model B: wallet has address only (no secret_key/public_key — operator keeps custody)\r\n const addr = data.wallet?.address || data.wallet?.solana_address || options.operatorWalletAddress;\r\n data.wallet = {\r\n public_key: '',\r\n secret_key: '',\r\n solana_address: addr,\r\n address: addr,\r\n chain: 'solana',\r\n };\r\n\r\n return data;\r\n }\r\n\r\n // ===== MODEL A: SOLANA SELF-CUSTODY WALLET REGISTRATION (opt-in, two-phase) =====\r\n if (options?.walletModel === 'self-custody' || options?.walletSecretKey) {\r\n // Generate or use provided wallet keypair\r\n let walletKeys: { publicKey: string; secretKey: string };\r\n if (options?.walletSecretKey) {\r\n // Derive public key from provided secret\r\n const privRaw = Buffer.from(options.walletSecretKey, 'hex');\r\n const privKeyDer = Buffer.concat([ED25519_PKCS8_PREFIX, privRaw]);\r\n const keyObject = createPrivateKey({ key: privKeyDer, format: 'der', type: 'pkcs8' });\r\n const pubRaw = keyObject.export({ type: 'spki', format: 'der' }).subarray(12);\r\n walletKeys = {\r\n publicKey: Buffer.from(pubRaw).toString('hex'),\r\n secretKey: options.walletSecretKey,\r\n };\r\n } else {\r\n walletKeys = generateWalletKeypair();\r\n }\r\n\r\n // Phase 1: Get challenge nonce from server\r\n const challengeRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, action: 'challenge' }),\r\n });\r\n\r\n let challengeData: { nonce?: string; error?: string };\r\n try {\r\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\r\n } catch {\r\n const err = new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\r\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\r\n throw err;\r\n }\r\n if (!challengeRes.ok || !challengeData.nonce) {\r\n // Attach wallet keys so caller can retry with the same keypair\r\n const err = mapApiError(challengeRes.status, challengeData, '/api/v1/register');\r\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\r\n throw err;\r\n }\r\n\r\n // Phase 2: Sign challenge and register\r\n const nonce = challengeData.nonce;\r\n const message = `provenonce-register:${nonce}:${walletKeys.publicKey}:${name}`;\r\n const walletSignature = signMessage(walletKeys.secretKey, message);\r\n\r\n const registerRes = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({\r\n name,\r\n wallet_public_key: walletKeys.publicKey,\r\n wallet_signature: walletSignature,\r\n wallet_nonce: nonce,\r\n ...(options?.metadata && { metadata: options.metadata }),\r\n }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\r\n try {\r\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\r\n } catch {\r\n // Attach wallet keys so caller can retry with the same keypair\r\n const err = new NetworkError(`Registration failed: ${registerRes.status} (non-JSON response)`);\r\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\r\n throw err;\r\n }\r\n if (!registerRes.ok) {\r\n // Attach wallet keys so caller can retry with the same keypair via walletSecretKey option\r\n const err = mapApiError(registerRes.status, data, '/api/v1/register');\r\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\r\n throw err;\r\n }\r\n\r\n // Attach the wallet keys (secret is client-side only, never sent to server)\r\n const addr = data.wallet?.address || data.wallet?.solana_address || '';\r\n data.wallet = {\r\n public_key: walletKeys.publicKey,\r\n secret_key: walletKeys.secretKey,\r\n solana_address: addr,\r\n address: addr,\r\n chain: 'solana',\r\n };\r\n\r\n return data;\r\n }\r\n\r\n // ===== NO-WALLET REGISTRATION (D-62 default, single-phase) =====\r\n\r\n const res = await fetch(`${url}/api/v1/register`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ name, ...(options?.metadata && { metadata: options.metadata }) }),\r\n });\r\n\r\n let data: RegistrationResult & { error?: string };\r\n try {\r\n data = await res.json() as RegistrationResult & { error?: string };\r\n } catch {\r\n throw new NetworkError(`Registration failed: ${res.status} ${res.statusText} (non-JSON response)`);\r\n }\r\n if (!res.ok) throw mapApiError(res.status, data, '/api/v1/register');\r\n return data;\r\n}\r\n\r\n// ============ SDK CONFIG ============\r\n\r\nexport interface BeatAgentConfig {\r\n /** API key from registration (pvn_...) */\r\n apiKey: string;\r\n\r\n /** Provenonce registry URL */\r\n registryUrl: string;\r\n\r\n /** @deprecated Use heartbeatIntervalSec. Beats to compute per pulse (default: 10) */\r\n beatsPerPulse?: number;\r\n\r\n /** @deprecated Use heartbeatIntervalSec. Seconds between automatic check-ins (default: 300 = 5min) */\r\n checkinIntervalSec?: number;\r\n\r\n /** Seconds between automatic heartbeats (default: 300 = 5min). Replaces checkinIntervalSec. */\r\n heartbeatIntervalSec?: number;\r\n\r\n /** @deprecated VDF pulse callback. No longer used in Phase 2. */\r\n onPulse?: (beats: Beat[], totalBeats: number) => void;\r\n\r\n /** @deprecated Use onHeartbeat. Callback when check-in completes. */\r\n onCheckin?: (result: CheckinResult) => void;\r\n\r\n /** Callback when heartbeat completes (Phase 2) */\r\n onHeartbeat?: (result: HeartbeatResult) => void;\r\n\r\n /** Callback on error */\r\n onError?: (error: Error, context: string) => void;\r\n\r\n /** Callback when status changes */\r\n onStatusChange?: (status: string, details: Record<string, unknown>) => void;\r\n\r\n /** Enable verbose logging */\r\n verbose?: boolean;\r\n}\r\n\r\n// ============ BEAT AGENT ============\r\n\r\nexport class BeatAgent {\r\n private config: Required<BeatAgentConfig>;\r\n private chain: Beat[] = [];\r\n private difficulty: number = 1000;\r\n private genesisHash: string = '';\r\n private latestBeat: Beat | null = null;\r\n private totalBeats: number = 0;\r\n private lastCheckinBeat: number = 0;\r\n private status: 'uninitialized' | 'active' | 'frozen' | 'revoked' = 'uninitialized';\r\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\r\n private globalBeat: number = 0;\r\n private globalAnchorHash: string = '';\r\n\r\n constructor(config: BeatAgentConfig) {\r\n // SDK-P1-08: validate required config fields\r\n if (!config.apiKey || typeof config.apiKey !== 'string') {\r\n throw new ValidationError('BeatAgentConfig.apiKey is required (must be a non-empty string)');\r\n }\r\n if (!config.registryUrl || typeof config.registryUrl !== 'string') {\r\n throw new ValidationError('BeatAgentConfig.registryUrl is required (must be a non-empty string)');\r\n }\r\n // SDK-P1-07: validate registryUrl is a valid URL\r\n try {\r\n new URL(config.registryUrl);\r\n } catch {\r\n throw new ValidationError('BeatAgentConfig.registryUrl is not a valid URL');\r\n }\r\n\r\n // SDK-P2: validate optional numeric config\r\n if (config.beatsPerPulse !== undefined && (!Number.isInteger(config.beatsPerPulse) || config.beatsPerPulse < 1 || config.beatsPerPulse > 10000)) {\r\n throw new ValidationError('BeatAgentConfig.beatsPerPulse must be an integer between 1 and 10000');\r\n }\r\n if (config.checkinIntervalSec !== undefined && (!Number.isFinite(config.checkinIntervalSec) || config.checkinIntervalSec < 10 || config.checkinIntervalSec > 86400)) {\r\n throw new ValidationError('BeatAgentConfig.checkinIntervalSec must be between 10 and 86400');\r\n }\r\n\r\n this.config = {\r\n beatsPerPulse: 10,\r\n checkinIntervalSec: 300,\r\n heartbeatIntervalSec: 300,\r\n onPulse: () => {},\r\n onCheckin: () => {},\r\n onHeartbeat: () => {},\r\n onError: () => {},\r\n onStatusChange: () => {},\r\n verbose: false,\r\n ...config,\r\n };\r\n }\r\n\r\n // ── INITIALIZATION ──\r\n\r\n /**\r\n * Initialize the agent's Beat chain.\r\n * This is the agent's \"birth\" in Logical Time.\r\n * Must be called once before computing beats.\r\n */\r\n async init(): Promise<{ ok: boolean; genesis?: string; error?: string }> {\r\n try {\r\n this.log('Initializing Beat chain...');\r\n\r\n const res = await this.api('POST', '/api/v1/agent/init');\r\n\r\n if (res.genesis) {\r\n this.genesisHash = res.genesis.hash;\r\n this.difficulty = res.difficulty || 1000;\r\n this.latestBeat = {\r\n index: 0,\r\n hash: res.genesis.hash,\r\n prev: res.genesis.prev,\r\n timestamp: res.genesis.timestamp,\r\n };\r\n this.chain = [this.latestBeat];\r\n this.totalBeats = 0;\r\n this.status = 'active';\r\n this.config.onStatusChange('active', { genesis: this.genesisHash });\r\n this.log(`Born in Beat time. Genesis: ${this.genesisHash.slice(0, 16)}...`);\r\n } else if (res.already_initialized) {\r\n // Restore from existing state\r\n this.genesisHash = res.genesis_hash;\r\n this.totalBeats = res.total_beats;\r\n this.status = res.status as any;\r\n this.log(`Already initialized. Restoring state (${res.total_beats} beats).`);\r\n \r\n // Fetch full state to get latest hash\r\n await this.refreshState();\r\n }\r\n\r\n // Sync global anchor\r\n await this.syncGlobal();\r\n\r\n return { ok: true, genesis: this.genesisHash };\r\n\r\n } catch (err: any) {\r\n this.config.onError(err, 'init');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n // ── PULSE (COMPUTE BEATS) ──\r\n\r\n /**\r\n * @deprecated Phase 2: VDF computation retired (D-68). Payment is the liveness mechanism.\r\n * Use heartbeat() instead. This method will be removed in the next major version.\r\n *\r\n * Compute N beats locally (VDF hash chain).\r\n */\r\n pulse(count?: number): Beat[] {\r\n console.warn('[Provenonce SDK] pulse() is deprecated. Use heartbeat() instead (Phase 2).');\r\n if (this.status === 'frozen') {\r\n throw new FrozenError('Cannot pulse: agent is frozen. Use resync() to re-establish provenance.');\r\n }\r\n if (this.status !== 'active') {\r\n throw new StateError(`Cannot pulse: agent is ${this.status}.`, this.status);\r\n }\r\n // SDK-P2: validate count param\r\n if (count !== undefined && (!Number.isInteger(count) || count < 1 || count > 10000)) {\r\n throw new ValidationError('pulse count must be an integer between 1 and 10000');\r\n }\r\n return this.computeBeats(count);\r\n }\r\n\r\n /** Internal beat computation — no status check. Used by both pulse() and resync(). */\r\n private computeBeats(count?: number, onProgress?: (computed: number, total: number) => void): Beat[] {\r\n const n = count || this.config.beatsPerPulse;\r\n\r\n if (!this.latestBeat) {\r\n throw new StateError('Beat chain not initialized. Call init() first.', 'uninitialized', ErrorCode.AGENT_NOT_INITIALIZED);\r\n }\r\n\r\n const newBeats: Beat[] = [];\r\n let prevHash = this.latestBeat.hash;\r\n let startIndex = this.latestBeat.index + 1;\r\n\r\n const t0 = Date.now();\r\n // SDK-P2: report progress every 10% of beats\r\n const progressInterval = Math.max(1, Math.floor(n / 10));\r\n\r\n for (let i = 0; i < n; i++) {\r\n const beat = computeBeat(prevHash, startIndex + i, this.difficulty, undefined, this.globalAnchorHash || undefined);\r\n newBeats.push(beat);\r\n prevHash = beat.hash;\r\n if (onProgress && (i + 1) % progressInterval === 0) {\r\n onProgress(i + 1, n);\r\n }\r\n }\r\n\r\n const elapsed = Date.now() - t0;\r\n\r\n // Update state\r\n this.chain.push(...newBeats);\r\n this.latestBeat = newBeats[newBeats.length - 1];\r\n this.totalBeats += n;\r\n\r\n // Keep chain bounded (only last 1000 beats in memory)\r\n if (this.chain.length > 1000) {\r\n this.chain = this.chain.slice(-500);\r\n }\r\n\r\n this.config.onPulse(newBeats, this.totalBeats);\r\n this.log(`Pulse: ${n} beats in ${elapsed}ms (${(elapsed / n).toFixed(1)}ms/beat, D=${this.difficulty})`);\r\n\r\n return newBeats;\r\n }\r\n\r\n // ── CHECK-IN ──\r\n\r\n /**\r\n * @deprecated Phase 2: VDF check-in retired (D-68). Use heartbeat() instead.\r\n * This method will be removed in the next major version.\r\n */\r\n async checkin(): Promise<{ ok: boolean; total_beats?: number; error?: string }> {\r\n console.warn('[Provenonce SDK] checkin() is deprecated. Use heartbeat() instead (Phase 2).');\r\n // SDK-P1-02: fix guard to compare beat indices, not totalBeats vs lastCheckinBeat\r\n if (!this.latestBeat || this.latestBeat.index <= this.lastCheckinBeat) {\r\n this.log('No new beats since last check-in. Call pulse() first.');\r\n return { ok: true, total_beats: this.totalBeats }; // Nothing new to report\r\n }\r\n\r\n try {\r\n // Find the boundary hashes\r\n const fromBeat = this.lastCheckinBeat;\r\n const toBeat = this.latestBeat.index;\r\n\r\n // Build spot checks from our local chain\r\n // prev and nonce are required for the server to recompute VDF\r\n // Must always include to_beat (final beat) — server requires it for final hash verification\r\n const spotChecks: { index: number; hash: string; prev: string; nonce?: string }[] = [];\r\n\r\n // Always include the final beat\r\n const toBeatEntry = this.chain.find(b => b.index === toBeat);\r\n if (toBeatEntry) {\r\n spotChecks.push({ index: toBeatEntry.index, hash: toBeatEntry.hash, prev: toBeatEntry.prev, nonce: toBeatEntry.nonce });\r\n }\r\n\r\n // Sample up to 4 more from the rest\r\n const available = this.chain.filter(b => b.index > this.lastCheckinBeat && b.index !== toBeat);\r\n const sampleCount = Math.min(4, available.length);\r\n\r\n for (let i = 0; i < sampleCount; i++) {\r\n const idx = Math.floor(Math.random() * available.length);\r\n const beat = available[idx];\r\n spotChecks.push({ index: beat.index, hash: beat.hash, prev: beat.prev, nonce: beat.nonce });\r\n available.splice(idx, 1);\r\n }\r\n const fromHash = this.chain.find(b => b.index === fromBeat)?.hash \r\n || this.genesisHash;\r\n const toHash = this.latestBeat.hash;\r\n\r\n const res = await this.api('POST', '/api/v1/agent/checkin', {\r\n proof: {\r\n from_beat: fromBeat,\r\n to_beat: toBeat,\r\n from_hash: fromHash,\r\n to_hash: toHash,\r\n beats_computed: toBeat - fromBeat,\r\n global_anchor: this.globalBeat,\r\n anchor_hash: this.globalAnchorHash || undefined,\r\n spot_checks: spotChecks,\r\n },\r\n });\r\n\r\n if (res.ok) {\r\n this.lastCheckinBeat = toBeat;\r\n this.totalBeats = res.total_beats;\r\n this.config.onCheckin(res);\r\n this.log(`Check-in accepted: ${res.beats_accepted} beats, total=${res.total_beats}, global=${res.global_beat}`);\r\n \r\n if (res.status === 'warning_overdue') {\r\n this.config.onStatusChange('warning', { beats_behind: res.beats_behind });\r\n this.log(`⚠ WARNING: ${res.beats_behind} anchors behind. Check in more frequently.`);\r\n }\r\n }\r\n\r\n return { ok: res.ok, total_beats: res.total_beats };\r\n\r\n } catch (err: any) {\r\n this.config.onError(err, 'checkin');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n // ── AUTONOMOUS HEARTBEAT ──\r\n\r\n /**\r\n * Start the autonomous heartbeat loop.\r\n * Phase 2: Sends paid heartbeats at regular intervals.\r\n *\r\n * @param paymentTxFn - Optional function that returns a payment tx for each heartbeat.\r\n * If not provided, uses 'devnet-skip' (devnet only).\r\n */\r\n startHeartbeat(paymentTxFn?: () => Promise<string> | string): void {\r\n if (this.heartbeatInterval) {\r\n this.log('Heartbeat already running.');\r\n return;\r\n }\r\n\r\n if (this.status !== 'active' && this.status !== 'uninitialized') {\r\n throw new StateError(`Cannot start heartbeat in status '${this.status}'.`, this.status);\r\n }\r\n\r\n const intervalSec = this.config.heartbeatIntervalSec || this.config.checkinIntervalSec || 300;\r\n this.log(`Starting heartbeat (interval: ${intervalSec}s)...`);\r\n\r\n // SDK-P1-03: exponential backoff on consecutive errors\r\n let consecutiveErrors = 0;\r\n let skipCount = 0;\r\n\r\n this.heartbeatInterval = setInterval(async () => {\r\n if (skipCount > 0) {\r\n skipCount--;\r\n return;\r\n }\r\n\r\n try {\r\n const paymentTx = paymentTxFn ? await paymentTxFn() : 'devnet-skip';\r\n await this.heartbeat(paymentTx);\r\n consecutiveErrors = 0;\r\n } catch (err: any) {\r\n consecutiveErrors++;\r\n this.config.onError(err, 'heartbeat');\r\n skipCount = Math.min(32, Math.pow(2, consecutiveErrors - 1));\r\n this.log(`Heartbeat error #${consecutiveErrors}, backing off ${skipCount} ticks`);\r\n }\r\n }, intervalSec * 1000);\r\n }\r\n\r\n /**\r\n * Stop the heartbeat loop.\r\n */\r\n stopHeartbeat(): void {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n this.heartbeatInterval = null;\r\n this.log('Heartbeat stopped.');\r\n }\r\n }\r\n\r\n // ── RE-SYNC ──\r\n\r\n /**\r\n * @deprecated Phase 2: Resync retired (D-67). Dormancy resume is free — just call heartbeat().\r\n * This method will be removed in the next major version.\r\n */\r\n async resync(): Promise<{ ok: boolean; beats_required?: number; error?: string }> {\r\n console.warn('[Provenonce SDK] resync() is deprecated (D-67). Use heartbeat() to resume (Phase 2).');\r\n try {\r\n this.log('Requesting re-sync challenge...');\r\n\r\n // Phase 1: Get challenge\r\n const challenge = await this.api('POST', '/api/v1/agent/resync', {\r\n action: 'challenge',\r\n });\r\n\r\n if (!challenge.challenge) {\r\n return { ok: false, error: 'Failed to get challenge' };\r\n }\r\n\r\n const required = challenge.challenge.required_beats;\r\n this.difficulty = challenge.challenge.difficulty;\r\n this.log(`Re-sync challenge: compute ${required} beats at D=${this.difficulty}`);\r\n\r\n // Sync global anchor so beats are woven with a recent anchor hash\r\n await this.syncGlobal();\r\n\r\n // Compute the required beats\r\n const startHash = challenge.challenge.start_from_hash;\r\n const startBeat = challenge.challenge.start_from_beat;\r\n\r\n // Reset chain from the known point\r\n this.latestBeat = { index: startBeat, hash: startHash, prev: '', timestamp: Date.now() };\r\n this.chain = [this.latestBeat];\r\n\r\n const t0 = Date.now();\r\n this.computeBeats(required);\r\n const elapsed = Date.now() - t0;\r\n this.log(`Re-sync beats computed in ${elapsed}ms`);\r\n\r\n // Phase 2: Submit proof (include challenge_nonce for server verification)\r\n const proof = await this.api('POST', '/api/v1/agent/resync', {\r\n action: 'prove',\r\n challenge_nonce: challenge.challenge.nonce,\r\n proof: {\r\n from_beat: startBeat,\r\n to_beat: this.latestBeat!.index,\r\n from_hash: startHash,\r\n to_hash: this.latestBeat!.hash,\r\n beats_computed: required,\r\n global_anchor: challenge.challenge.sync_to_global,\r\n anchor_hash: this.globalAnchorHash || undefined,\r\n spot_checks: (() => {\r\n // Must include to_beat (final beat) — server requires it for final hash verification\r\n const toBeatEntry = this.chain.find(b => b.index === this.latestBeat!.index);\r\n // Sample from available chain beats (chain may be trimmed to 500 entries)\r\n const available = this.chain\r\n .filter(b => b.index !== this.latestBeat!.index && b.index > startBeat);\r\n const step = Math.max(1, Math.ceil(available.length / 5));\r\n const others = available\r\n .filter((_, i) => i % step === 0)\r\n .slice(0, 4);\r\n const checks = toBeatEntry ? [toBeatEntry, ...others] : others;\r\n return checks.map(b => ({ index: b.index, hash: b.hash, prev: b.prev, nonce: b.nonce }));\r\n })(),\r\n },\r\n });\r\n\r\n if (proof.ok) {\r\n this.status = 'active';\r\n this.totalBeats = proof.total_beats;\r\n this.lastCheckinBeat = this.latestBeat!.index;\r\n this.config.onStatusChange('active', { resynced: true });\r\n this.log('✓ Re-synced. Agent is alive again in Beat time.');\r\n }\r\n\r\n return { ok: proof.ok, beats_required: required };\r\n\r\n } catch (err: any) {\r\n this.config.onError(err, 'resync');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n // ── SPAWN ──\r\n\r\n /**\r\n * Request to spawn a child agent.\r\n * Requires sufficient accumulated beats (Temporal Gestation).\r\n */\r\n async requestSpawn(childName?: string, childHash?: string): Promise<SpawnResult> {\r\n try {\r\n // SDK-P1-05: validate childName\r\n if (childName !== undefined) {\r\n if (typeof childName !== 'string' || childName.trim().length === 0) {\r\n throw new ValidationError('childName must be a non-empty string');\r\n }\r\n if (childName.length > 64) {\r\n throw new ValidationError('childName must be 64 characters or fewer');\r\n }\r\n }\r\n\r\n const res = await this.api('POST', '/api/v1/agent/spawn', {\r\n child_name: childName,\r\n child_hash: childHash,\r\n });\r\n\r\n if (res.eligible === false) {\r\n this.log(`Gestation incomplete: ${res.progress_pct}% (need ${res.deficit} more beats)`);\r\n } else if (res.ok) {\r\n this.log(`Child spawned: ${res.child_hash?.slice(0, 16)}...`);\r\n }\r\n\r\n return res;\r\n } catch (err: any) {\r\n this.config.onError(err, 'spawn');\r\n throw err;\r\n }\r\n }\r\n\r\n // ── PHASE 2: SIGIL + HEARTBEAT + PROOF ──\r\n\r\n /** Cached lineage proof from the most recent heartbeat or SIGIL purchase */\r\n private cachedProof: LineageProof | null = null;\r\n\r\n /**\r\n * Purchase a SIGIL (cryptographic identity) for this agent.\r\n * SIGILs gate heartbeating, lineage proofs, and offline verification.\r\n * One-time purchase — cannot be re-purchased.\r\n *\r\n * @param options - SIGIL purchase options (identity_class, principal, tier, name, payment_tx, + optional metadata)\r\n *\r\n * Legacy signature (deprecated):\r\n * @param identityClass - 'narrow_task' | 'autonomous' | 'orchestrator'\r\n * @param paymentTx - Solana transaction signature or 'devnet-skip'\r\n */\r\n async purchaseSigil(optionsOrClass: SigilPurchaseOptions | IdentityClass, paymentTx?: string): Promise<SigilResult> {\r\n let body: Record<string, unknown>;\r\n\r\n if (typeof optionsOrClass === 'string') {\r\n // Legacy signature: purchaseSigil(identityClass, paymentTx)\r\n if (!optionsOrClass || !['narrow_task', 'autonomous', 'orchestrator'].includes(optionsOrClass)) {\r\n throw new ValidationError('identityClass must be narrow_task, autonomous, or orchestrator');\r\n }\r\n if (!paymentTx || typeof paymentTx !== 'string') {\r\n throw new ValidationError('paymentTx is required (Solana transaction signature or \"devnet-skip\")');\r\n }\r\n body = {\r\n identity_class: optionsOrClass,\r\n payment_tx: paymentTx,\r\n // Legacy calls without principal/tier — server will require these now\r\n // Callers must migrate to the options object form\r\n };\r\n } else {\r\n // New signature: purchaseSigil(options)\r\n const opts = optionsOrClass;\r\n if (!opts.identity_class || !['narrow_task', 'autonomous', 'orchestrator'].includes(opts.identity_class)) {\r\n throw new ValidationError('identity_class must be narrow_task, autonomous, or orchestrator');\r\n }\r\n if (!opts.principal || typeof opts.principal !== 'string') {\r\n throw new ValidationError('principal is required');\r\n }\r\n if (!opts.tier || !['sov', 'org', 'ind', 'eph', 'sbx'].includes(opts.tier)) {\r\n throw new ValidationError('tier must be one of: sov, org, ind, eph, sbx');\r\n }\r\n if (!opts.payment_tx || typeof opts.payment_tx !== 'string') {\r\n throw new ValidationError('payment_tx is required');\r\n }\r\n\r\n body = { ...opts };\r\n }\r\n\r\n try {\r\n const res = await this.api('POST', '/api/v1/sigil', body);\r\n\r\n if (res.lineage_proof) {\r\n this.cachedProof = res.lineage_proof;\r\n }\r\n\r\n const sigilStr = res.sigil?.sigil || res.sigil?.identity_class || '';\r\n this.log(`SIGIL purchased: ${sigilStr}`);\r\n this.config.onStatusChange('sigil_issued', { sigil: sigilStr });\r\n\r\n return {\r\n ok: true,\r\n sigil: res.sigil,\r\n lineage_proof: res.lineage_proof,\r\n fee: res.fee,\r\n };\r\n } catch (err: any) {\r\n this.config.onError(err, 'purchaseSigil');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Update mutable SIGIL metadata fields.\r\n * Requires a SIGIL. Cannot modify immutable fields.\r\n *\r\n * @param fields - Subset of mutable SIGIL fields to update\r\n */\r\n async updateMetadata(fields: Partial<SigilMutableFields>): Promise<MetadataUpdateResult> {\r\n if (!fields || Object.keys(fields).length === 0) {\r\n throw new ValidationError('At least one metadata field is required');\r\n }\r\n\r\n try {\r\n const res = await this.api('PATCH', '/api/v1/agent/metadata', fields);\r\n this.log(`Metadata updated: ${res.updated_fields?.join(', ') || 'unknown'}`);\r\n return {\r\n ok: true,\r\n sigil: res.sigil,\r\n generation: res.generation,\r\n updated_fields: res.updated_fields,\r\n };\r\n } catch (err: any) {\r\n this.config.onError(err, 'updateMetadata');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Send a paid heartbeat to the registry.\r\n * Requires a SIGIL. Returns a signed lineage proof.\r\n * This is the Phase 2 replacement for pulse() + checkin().\r\n *\r\n * @param paymentTx - Solana transaction signature. Omit or 'devnet-skip' on devnet.\r\n * @param globalAnchor - Optional: the global anchor index to reference.\r\n */\r\n async heartbeat(paymentTx?: string, globalAnchor?: number): Promise<HeartbeatResult> {\r\n try {\r\n const res = await this.api('POST', '/api/v1/agent/heartbeat', {\r\n payment_tx: paymentTx || 'devnet-skip',\r\n global_anchor: globalAnchor,\r\n });\r\n\r\n if (res.lineage_proof) {\r\n this.cachedProof = res.lineage_proof;\r\n }\r\n\r\n if (res.ok) {\r\n this.status = 'active';\r\n const onHb = this.config.onHeartbeat || this.config.onCheckin;\r\n if (onHb) onHb(res);\r\n this.log(`Heartbeat accepted: epoch=${res.billing_epoch}, count=${res.heartbeat_count_epoch}`);\r\n }\r\n\r\n return {\r\n ok: res.ok,\r\n lineage_proof: res.lineage_proof,\r\n heartbeat_count_epoch: res.heartbeat_count_epoch,\r\n billing_epoch: res.billing_epoch,\r\n current_beat: res.current_beat,\r\n fee: res.fee,\r\n };\r\n } catch (err: any) {\r\n this.config.onError(err, 'heartbeat');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Reissue a lineage proof. \"Reprint, not a renewal.\"\r\n * Does NOT create a new lineage event.\r\n *\r\n * @param paymentTx - Solana transaction signature. Omit or 'devnet-skip' on devnet.\r\n */\r\n async reissueProof(paymentTx?: string): Promise<{ ok: boolean; lineage_proof?: LineageProof; error?: string }> {\r\n try {\r\n const res = await this.api('POST', '/api/v1/agent/reissue-proof', {\r\n payment_tx: paymentTx || 'devnet-skip',\r\n });\r\n\r\n if (res.lineage_proof) {\r\n this.cachedProof = res.lineage_proof;\r\n }\r\n\r\n return { ok: true, lineage_proof: res.lineage_proof };\r\n } catch (err: any) {\r\n this.config.onError(err, 'reissueProof');\r\n return { ok: false, error: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Get the latest cached lineage proof (no network call).\r\n * Returns null if no proof has been obtained yet.\r\n */\r\n getLatestProof(): LineageProof | null {\r\n return this.cachedProof;\r\n }\r\n\r\n /**\r\n * Get the agent's passport (alias for getLatestProof).\r\n * The passport is the agent's portable, offline-verifiable credential.\r\n * Returns null if no passport has been issued yet (requires SIGIL + heartbeat).\r\n */\r\n getPassport(): Passport | null {\r\n return this.cachedProof;\r\n }\r\n\r\n /**\r\n * Verify a lineage proof locally using the authority public key.\r\n * Offline verification — no API call, no SOL cost.\r\n *\r\n * Returns a VerificationResult object. The object is truthy when valid,\r\n * so `if (BeatAgent.verifyProofLocally(proof, key))` still works.\r\n *\r\n * @param proof - The LineageProof to verify\r\n * @param authorityPubKeyHex - 32-byte hex-encoded Ed25519 public key from /.well-known/provenonce-authority.json\r\n * @param currentBeat - Optional current global beat index (for beatsSinceHeartbeat calculation)\r\n */\r\n static verifyProofLocally(proof: LineageProof, authorityPubKeyHex: string, currentBeat?: number): VerificationResult {\r\n const now = Date.now();\r\n const expired = now > proof.valid_until;\r\n\r\n let signatureValid = false;\r\n try {\r\n // Canonical JSON (must match server's canonicalProofData)\r\n const canonical = JSON.stringify({\r\n agent_hash: proof.agent_hash,\r\n agent_public_key: proof.agent_public_key,\r\n identity_class: proof.identity_class,\r\n registered_at_beat: proof.registered_at_beat,\r\n sigil_issued_at_beat: proof.sigil_issued_at_beat,\r\n last_heartbeat_beat: proof.last_heartbeat_beat,\r\n lineage_chain_hash: proof.lineage_chain_hash,\r\n issued_at: proof.issued_at,\r\n valid_until: proof.valid_until,\r\n });\r\n\r\n // Build Ed25519 public key from hex\r\n const pubBytes = Buffer.from(authorityPubKeyHex, 'hex');\r\n if (pubBytes.length === 32) {\r\n const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');\r\n const pubKeyDer = Buffer.concat([ED25519_SPKI_PREFIX, pubBytes]);\r\n const keyObject = createPublicKey({ key: pubKeyDer, format: 'der', type: 'spki' });\r\n const sigBuffer = Buffer.from(proof.provenonce_signature, 'hex');\r\n signatureValid = verify(null, Buffer.from(canonical), keyObject, sigBuffer);\r\n }\r\n } catch {\r\n signatureValid = false;\r\n }\r\n\r\n const valid = signatureValid && !expired;\r\n const beatsSinceHeartbeat = currentBeat != null ? currentBeat - proof.last_heartbeat_beat : null;\r\n\r\n let warning: string | undefined;\r\n if (expired) {\r\n warning = 'Proof has expired. Reissue with reissueProof() or send a heartbeat.';\r\n } else if (beatsSinceHeartbeat != null && beatsSinceHeartbeat > 60) {\r\n warning = `Agent is ${beatsSinceHeartbeat} beats behind. Heartbeat may be stale.`;\r\n }\r\n\r\n return { valid, signatureValid, expired, lastHeartbeatBeat: proof.last_heartbeat_beat, beatsSinceHeartbeat, warning };\r\n }\r\n\r\n // ── STATUS ──\r\n\r\n /**\r\n * Get this agent's full beat status from the registry.\r\n */\r\n async getStatus(): Promise<AgentStatus> {\r\n try {\r\n // We need the agent hash, but we may not have it directly.\r\n // The status endpoint uses the hash from the API key verification.\r\n // For now, use the init endpoint which returns status.\r\n return await this.refreshState();\r\n } catch (err: any) {\r\n this.config.onError(err, 'status');\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Get local state (no network call).\r\n */\r\n getLocalState(): {\r\n status: string;\r\n totalBeats: number;\r\n latestBeat: number;\r\n latestHash: string;\r\n difficulty: number;\r\n globalBeat: number;\r\n chainLength: number;\r\n } {\r\n return {\r\n status: this.status,\r\n totalBeats: this.totalBeats,\r\n latestBeat: this.latestBeat?.index || 0,\r\n latestHash: this.latestBeat?.hash.slice(0, 24) + '...' || '',\r\n difficulty: this.difficulty,\r\n globalBeat: this.globalBeat,\r\n chainLength: this.chain.length,\r\n };\r\n }\r\n\r\n // ── INTERNALS ──\r\n\r\n private async syncGlobal(): Promise<void> {\r\n try {\r\n // SDK-P1-01: add timeout to syncGlobal fetch\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), 15_000);\r\n const res = await fetch(`${this.config.registryUrl}/api/v1/beat/anchor`, { signal: controller.signal });\r\n clearTimeout(timeout);\r\n const data: any = await res.json();\r\n if (data.anchor) {\r\n this.globalBeat = data.anchor.beat_index;\r\n this.globalAnchorHash = data.anchor.hash || '';\r\n if (data.anchor.difficulty) this.difficulty = data.anchor.difficulty;\r\n this.log(`Synced to global beat ${this.globalBeat} (D=${this.difficulty})`);\r\n }\r\n } catch {\r\n this.log('Failed to sync global anchor (offline mode continues)');\r\n }\r\n }\r\n\r\n private async refreshState(): Promise<any> {\r\n const res = await this.api('POST', '/api/v1/agent/init');\r\n if (res.already_initialized) {\r\n this.totalBeats = res.total_beats;\r\n this.genesisHash = res.genesis_hash;\r\n this.status = res.status as any;\r\n this.difficulty = res.difficulty || this.difficulty;\r\n this.lastCheckinBeat = res.last_checkin_beat || 0;\r\n\r\n // Restore latestBeat so pulse() can continue the chain\r\n if (!this.latestBeat && this.genesisHash) {\r\n this.latestBeat = {\r\n index: res.latest_beat || this.totalBeats,\r\n hash: res.latest_hash || this.genesisHash,\r\n prev: '0'.repeat(64),\r\n timestamp: Date.now(),\r\n };\r\n this.chain = [this.latestBeat];\r\n }\r\n }\r\n return res;\r\n }\r\n\r\n private async api(method: string, path: string, body?: any): Promise<any> {\r\n // SDK-P1-01: add 30s timeout to prevent indefinite hangs\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), 30_000);\r\n\r\n try {\r\n const res = await fetch(`${this.config.registryUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.config.apiKey}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n let data: any;\r\n try {\r\n data = await res.json();\r\n } catch {\r\n throw new NetworkError(`API error: ${res.status} non-JSON response from ${path}`);\r\n }\r\n\r\n if (!res.ok && !data.ok && !data.already_initialized && !data.eligible) {\r\n throw mapApiError(res.status, data, path);\r\n }\r\n\r\n return data;\r\n } catch (err: any) {\r\n if (err.name === 'AbortError') {\r\n throw new NetworkError(`Request timeout: ${method} ${path}`, ErrorCode.TIMEOUT);\r\n }\r\n throw err;\r\n } finally {\r\n clearTimeout(timeout);\r\n }\r\n }\r\n\r\n private log(msg: string): void {\r\n if (this.config.verbose) {\r\n console.log(`[Beat] ${msg}`);\r\n }\r\n }\r\n}\r\n\r\n// ============ STANDALONE VDF HELPER ============\r\n// For agents that want to compute beats without the full SDK\r\n\r\nexport { computeBeat };\r\n\r\n/**\r\n * Compute N sequential VDF beats.\r\n * Returns only the last beat (for lightweight usage).\r\n */\r\nexport function computeBeatsLite(\r\n startHash: string,\r\n startIndex: number,\r\n count: number,\r\n difficulty: number = 1000,\r\n anchorHash?: string,\r\n): { lastBeat: Beat; elapsed: number } {\r\n // SDK-P2: validate inputs\r\n if (!startHash || typeof startHash !== 'string') {\r\n throw new ValidationError('computeBeatsLite: startHash must be a non-empty string');\r\n }\r\n if (!Number.isInteger(count) || count < 1) {\r\n throw new ValidationError('computeBeatsLite: count must be a positive integer');\r\n }\r\n\r\n const t0 = Date.now();\r\n let prev = startHash;\r\n let lastBeat: Beat | null = null;\r\n\r\n for (let i = 0; i < count; i++) {\r\n lastBeat = computeBeat(prev, startIndex + i, difficulty, undefined, anchorHash);\r\n prev = lastBeat.hash;\r\n }\r\n\r\n return { lastBeat: lastBeat!, elapsed: Date.now() - t0 };\r\n}\r\n","/**\r\n * Provenonce SDK Error Classes\r\n *\r\n * Typed error hierarchy for programmatic error handling.\r\n * All errors extend ProvenonceError for catch-all, or catch specific\r\n * subclasses for fine-grained control:\r\n *\r\n * try {\r\n * await agent.checkin();\r\n * } catch (err) {\r\n * if (err instanceof RateLimitError) {\r\n * await sleep(err.retryAfterMs);\r\n * } else if (err instanceof FrozenError) {\r\n * await agent.resync();\r\n * } else if (err instanceof AuthError) {\r\n * console.error('Bad API key');\r\n * }\r\n * }\r\n */\r\n\r\n/** Error codes for programmatic switching */\r\nexport enum ErrorCode {\r\n // Validation\r\n VALIDATION = 'VALIDATION',\r\n\r\n // Auth\r\n AUTH_INVALID = 'AUTH_INVALID',\r\n AUTH_MISSING = 'AUTH_MISSING',\r\n\r\n // Rate limiting\r\n RATE_LIMITED = 'RATE_LIMITED',\r\n\r\n // Agent state\r\n AGENT_FROZEN = 'AGENT_FROZEN',\r\n AGENT_NOT_INITIALIZED = 'AGENT_NOT_INITIALIZED',\r\n AGENT_WRONG_STATE = 'AGENT_WRONG_STATE',\r\n\r\n // Not found\r\n NOT_FOUND = 'NOT_FOUND',\r\n\r\n // Network / server\r\n NETWORK_ERROR = 'NETWORK_ERROR',\r\n TIMEOUT = 'TIMEOUT',\r\n SERVER_ERROR = 'SERVER_ERROR',\r\n}\r\n\r\n/** Base error class for all Provenonce SDK errors */\r\nexport class ProvenonceError extends Error {\r\n /** Machine-readable error code */\r\n readonly code: ErrorCode;\r\n\r\n /** HTTP status code (if from an API response) */\r\n readonly statusCode?: number;\r\n\r\n /** Additional context */\r\n readonly details?: Record<string, unknown>;\r\n\r\n constructor(\r\n message: string,\r\n code: ErrorCode,\r\n statusCode?: number,\r\n details?: Record<string, unknown>,\r\n ) {\r\n super(message);\r\n this.name = 'ProvenonceError';\r\n this.code = code;\r\n this.statusCode = statusCode;\r\n this.details = details;\r\n // Fix prototype chain for instanceof checks\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\n/** Thrown when input validation fails (bad config, invalid args) */\r\nexport class ValidationError extends ProvenonceError {\r\n constructor(message: string, details?: Record<string, unknown>) {\r\n super(message, ErrorCode.VALIDATION, undefined, details);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n\r\n/** Thrown on 401/403 — bad or missing API key */\r\nexport class AuthError extends ProvenonceError {\r\n constructor(\r\n message: string,\r\n code: ErrorCode.AUTH_INVALID | ErrorCode.AUTH_MISSING = ErrorCode.AUTH_INVALID,\r\n statusCode?: number,\r\n ) {\r\n super(message, code, statusCode);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\n/** Thrown on 429 — rate limit exceeded */\r\nexport class RateLimitError extends ProvenonceError {\r\n /** Milliseconds until the rate limit resets (if provided by server) */\r\n readonly retryAfterMs?: number;\r\n\r\n constructor(message: string, statusCode: number = 429, retryAfterMs?: number) {\r\n super(message, ErrorCode.RATE_LIMITED, statusCode);\r\n this.name = 'RateLimitError';\r\n this.retryAfterMs = retryAfterMs;\r\n }\r\n}\r\n\r\n/** Thrown when an agent is frozen and cannot perform the requested action */\r\nexport class FrozenError extends ProvenonceError {\r\n constructor(message: string = 'Agent is frozen. Use resync() to re-establish provenance.') {\r\n super(message, ErrorCode.AGENT_FROZEN);\r\n this.name = 'FrozenError';\r\n }\r\n}\r\n\r\n/** Thrown when the agent is in the wrong state for the requested action */\r\nexport class StateError extends ProvenonceError {\r\n /** The agent's current state */\r\n readonly currentState: string;\r\n\r\n constructor(message: string, currentState: string, code: ErrorCode = ErrorCode.AGENT_WRONG_STATE) {\r\n super(message, code);\r\n this.name = 'StateError';\r\n this.currentState = currentState;\r\n }\r\n}\r\n\r\n/** Thrown on 404 — agent or resource not found */\r\nexport class NotFoundError extends ProvenonceError {\r\n constructor(message: string, statusCode: number = 404) {\r\n super(message, ErrorCode.NOT_FOUND, statusCode);\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\n/** Thrown on network failures — non-JSON responses, fetch errors, timeouts */\r\nexport class NetworkError extends ProvenonceError {\r\n constructor(message: string, code: ErrorCode.NETWORK_ERROR | ErrorCode.TIMEOUT = ErrorCode.NETWORK_ERROR) {\r\n super(message, code);\r\n this.name = 'NetworkError';\r\n }\r\n}\r\n\r\n/** Thrown on 5xx — unexpected server errors */\r\nexport class ServerError extends ProvenonceError {\r\n constructor(message: string, statusCode: number = 500) {\r\n super(message, ErrorCode.SERVER_ERROR, statusCode);\r\n this.name = 'ServerError';\r\n }\r\n}\r\n\r\n/**\r\n * Map an HTTP response + parsed body to the appropriate error class.\r\n * Used internally by the SDK to convert API failures to typed errors.\r\n */\r\nexport function mapApiError(\r\n statusCode: number,\r\n body: { error?: string; retry_after_ms?: number },\r\n path: string,\r\n): ProvenonceError {\r\n const msg = typeof body.error === 'string' ? body.error : `API error ${statusCode}`;\r\n\r\n if (statusCode === 401 || statusCode === 403) {\r\n const code = statusCode === 401 ? ErrorCode.AUTH_MISSING : ErrorCode.AUTH_INVALID;\r\n return new AuthError(msg, code, statusCode);\r\n }\r\n\r\n if (statusCode === 429) {\r\n const retryAfter = typeof body.retry_after_ms === 'number' ? body.retry_after_ms : undefined;\r\n return new RateLimitError(msg, statusCode, retryAfter);\r\n }\r\n\r\n if (statusCode === 404) {\r\n return new NotFoundError(msg, statusCode);\r\n }\r\n\r\n if (statusCode >= 500) {\r\n return new ServerError(msg, statusCode);\r\n }\r\n\r\n // Check for specific error patterns in the message\r\n const lowerMsg = msg.toLowerCase();\r\n if (lowerMsg.includes('frozen')) {\r\n return new FrozenError(msg);\r\n }\r\n\r\n // Generic client error\r\n return new ProvenonceError(msg, ErrorCode.SERVER_ERROR, statusCode);\r\n}\r\n"],"mappings":"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","names":["ErrorCode","res","data"]}
|
|
1
|
+
{"version":3,"sources":["../src/beat-sdk.ts","../src/errors.ts"],"sourcesContent":["/**\n * ═══════════════════════════════════════════════════════════\n * PROVENONCE BEAT SDK — Agent Heartbeat Client\n * ═══════════════════════════════════════════════════════════\n * \n * \"NIST tells you what time it is.\n * Provenonce tells the agent at what speed it is allowed to exist.\"\n * \n * Usage:\n * \n * import { BeatAgent } from './beat-sdk';\n * \n * const agent = new BeatAgent({\n * apiKey: 'pvn_...',\n * registryUrl: 'https://provenonce.io',\n * });\n * \n * await agent.init(); // Birth in Beat time\n * await agent.pulse(50); // Compute 50 beats\n * await agent.checkin(); // Report to registry\n * \n * // Or run the autonomous heartbeat:\n * agent.startHeartbeat(); // Computes + checks in continuously\n * // ... do your agent work ...\n * agent.stopHeartbeat();\n * \n * ═══════════════════════════════════════════════════════════\n */\n\nimport { createHash, generateKeyPairSync, sign, verify, createPrivateKey, createPublicKey } from 'crypto';\nimport {\n ValidationError,\n AuthError,\n RateLimitError,\n FrozenError,\n StateError,\n NetworkError,\n ServerError,\n mapApiError,\n ErrorCode,\n} from './errors';\n\n// ============ PHASE 2 TYPES ============\n\n/** SIGIL identity class — determines tier pricing and heartbeat volume caps */\nexport type IdentityClass = 'narrow_task' | 'autonomous' | 'orchestrator';\n\n/** SIGIL trust governance tier — orthogonal to identity_class (fee axis) */\nexport type SigilTier = 'sov' | 'org' | 'ind' | 'eph' | 'sbx';\n\n/** Substrate — what the agent runs on */\nexport type Substrate = 'frontier' | 'open' | 'local' | 'symbolic' | 'hybrid' | 'human';\n\n/** Substrate provider */\nexport type SubstrateProvider = 'anthropic' | 'openai' | 'google' | 'meta' | 'mistral' | 'xai' | 'cohere' | 'deepseek' | 'custom';\n\n/** Capability — what the agent primarily does */\nexport type Capability = 'analyst' | 'executor' | 'orchestrator' | 'guardian' | 'retriever' | 'renderer' | 'witness';\n\n/** Protocol — how to reach the agent */\nexport type SigilProtocol = 'http' | 'grpc' | 'websocket' | 'mcp' | 'a2a' | 'custom';\n\n/** Compliance regime */\nexport type ComplianceRegime = 'gdpr' | 'pdpa' | 'hipaa' | 'sox' | 'aisi' | 'none' | 'custom';\n\n/**\n * Ed25519-signed lineage proof — portable, offline-verifiable credential.\n * Also known as the agent's \"passport\" — a cryptographic proof of identity\n * that can be verified offline without any API call or SOL cost.\n */\nexport interface LineageProof {\n agent_hash: string;\n agent_public_key: string | null;\n identity_class: IdentityClass;\n registered_at_beat: number;\n sigil_issued_at_beat: number | null;\n last_heartbeat_beat: number;\n lineage_chain_hash: string;\n issued_at: number;\n valid_until: number;\n provenonce_signature: string;\n}\n\n/** Passport = LineageProof. The agent's portable, offline-verifiable credential. */\nexport type Passport = LineageProof;\n\n/** Options for purchasing a SIGIL with full namespace */\nexport interface SigilPurchaseOptions {\n identity_class: IdentityClass;\n principal: string;\n tier: SigilTier;\n name?: string; // \"auto\" or custom name\n payment_tx: string;\n // Optional initial metadata\n substrate?: Substrate;\n substrate_provider?: SubstrateProvider;\n substrate_model?: string;\n capability?: Capability;\n capability_scope?: string;\n tools?: string[];\n modality_input?: string[];\n modality_output?: string[];\n protocol?: SigilProtocol;\n endpoint?: string;\n compliance_regime?: ComplianceRegime;\n}\n\n/** Mutable SIGIL metadata fields for PATCH updates */\nexport interface SigilMutableFields {\n substrate?: Substrate;\n substrate_provider?: SubstrateProvider;\n substrate_model?: string;\n capability?: Capability;\n capability_scope?: string;\n generation_trigger?: string;\n tools?: string[];\n modality_input?: string[];\n modality_output?: string[];\n protocol?: SigilProtocol;\n endpoint?: string;\n compliance_regime?: ComplianceRegime;\n}\n\n/** Result from purchasing a SIGIL (Structured Identity Governance and Intelligent Lookup) */\nexport interface SigilResult {\n ok: boolean;\n sigil?: {\n sigil: string; // Full SIGIL string: name*principal*tier\n sigil_name: string;\n principal: string;\n tier: SigilTier;\n identity_class: IdentityClass;\n issued_at_beat: number;\n birth_tx: string | null;\n explorer_url: string | null;\n };\n lineage_proof?: LineageProof;\n fee?: {\n amount_sol: number;\n amount_lamports: number;\n payment_tx: string | null;\n };\n error?: string;\n}\n\n/** Result from updating mutable SIGIL metadata */\nexport interface MetadataUpdateResult {\n ok: boolean;\n sigil?: string;\n generation?: number;\n updated_fields?: string[];\n error?: string;\n}\n\n/** Result from offline lineage proof verification */\nexport interface VerificationResult {\n /** Overall validity: signature is valid AND not expired */\n valid: boolean;\n /** Ed25519 signature verification passed */\n signatureValid: boolean;\n /** Proof has passed its valid_until timestamp */\n expired: boolean;\n /** The beat index of the agent's last heartbeat */\n lastHeartbeatBeat: number;\n /** Beats elapsed since last heartbeat (null if currentBeat not provided) */\n beatsSinceHeartbeat: number | null;\n /** Human-readable warning if proof is expired or stale */\n warning?: string;\n}\n\n/** Result from a paid heartbeat */\nexport interface HeartbeatResult {\n ok: boolean;\n lineage_proof?: LineageProof;\n heartbeat_count_epoch?: number;\n billing_epoch?: number;\n current_beat?: number;\n fee?: {\n amount_sol: number;\n amount_lamports: number;\n tier: number;\n payment_tx: string | null;\n };\n error?: string;\n}\n\n// ============ VDF ENGINE (LOCAL) ============\n\nexport interface Beat {\n index: number;\n hash: string;\n prev: string;\n timestamp: number;\n nonce?: string;\n anchor_hash?: string;\n}\n\nfunction computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string, anchorHash?: string): Beat {\n const timestamp = Date.now();\n\n const seed = anchorHash\n ? `${prevHash}:${beatIndex}:${nonce || ''}:${anchorHash}`\n : `${prevHash}:${beatIndex}:${nonce || ''}`;\n\n let current = createHash('sha256')\n .update(seed)\n .digest('hex');\n\n for (let i = 0; i < difficulty; i++) {\n current = createHash('sha256')\n .update(current)\n .digest('hex');\n }\n\n return { index: beatIndex, hash: current, prev: prevHash, timestamp, nonce, anchor_hash: anchorHash };\n}\n\n// ============ SDK RESULT TYPES ============\n\n/** Result from a check-in submission */\nexport interface CheckinResult {\n ok: boolean;\n total_beats: number;\n beats_accepted: number;\n global_beat: number;\n status?: string;\n beats_behind?: number;\n}\n\n/** Result from a spawn request */\nexport interface SpawnResult {\n ok: boolean;\n eligible: boolean;\n child_hash?: string;\n progress_pct?: number;\n deficit?: number;\n}\n\n/** Agent status from the registry */\nexport interface AgentStatus {\n already_initialized: boolean;\n total_beats: number;\n genesis_hash: string;\n status: string;\n genesis?: { hash: string; prev: string; timestamp: number };\n difficulty?: number;\n}\n\n// ============ WALLET KEYPAIR GENERATION ============\n\n// DER prefix for Ed25519 PKCS8 private keys (16 bytes)\nconst ED25519_PKCS8_PREFIX = Buffer.from('302e020100300506032b657004220420', 'hex');\n\n/**\n * Generate an Ed25519 keypair for agent wallet identity.\n * Returns hex-encoded raw keys (32 bytes each).\n * Uses Node.js built-in crypto — zero external dependencies.\n */\nexport function generateWalletKeypair(): { publicKey: string; secretKey: string } {\n const { publicKey, privateKey } = generateKeyPairSync('ed25519');\n const pubRaw = publicKey.export({ type: 'spki', format: 'der' }).subarray(12); // 32 bytes\n const privRaw = privateKey.export({ type: 'pkcs8', format: 'der' }).subarray(16); // 32 bytes\n return {\n publicKey: Buffer.from(pubRaw).toString('hex'),\n secretKey: Buffer.from(privRaw).toString('hex'),\n };\n}\n\n/**\n * Sign a message with an Ed25519 private key (hex-encoded 32-byte seed).\n * Returns hex-encoded signature (64 bytes).\n */\nfunction signMessage(secretKeyHex: string, message: string): string {\n const privRaw = Buffer.from(secretKeyHex, 'hex');\n const privKeyDer = Buffer.concat([ED25519_PKCS8_PREFIX, privRaw]);\n const keyObject = createPrivateKey({ key: privKeyDer, format: 'der', type: 'pkcs8' });\n const sig = sign(null, Buffer.from(message), keyObject);\n return Buffer.from(sig).toString('hex');\n}\n\n// ============ REGISTRATION ============\n\n/** Wallet info returned from root registration */\nexport interface WalletInfo {\n /** Hex-encoded 32-byte Ed25519 public key (Solana self-custody only, empty otherwise) */\n public_key: string;\n /** Hex-encoded 32-byte Ed25519 secret seed — SAVE THIS for future fee signing (Solana self-custody only) */\n secret_key: string;\n /** Solana-compatible base58 address (Solana wallets only) */\n solana_address?: string;\n /** The wallet address (base58 for Solana, 0x for Ethereum) */\n address: string;\n /** Wallet chain: 'solana' or 'ethereum' */\n chain: string;\n}\n\n/** Result from registering an agent */\nexport interface RegistrationResult {\n hash: string;\n api_key: string;\n secret: string;\n type: 'root' | 'agent';\n parent: string | null;\n depth: number;\n name: string;\n metadata?: Record<string, unknown> | null;\n /** @deprecated No Solana write at registration (D-65). Will be null. */\n signature?: string | null;\n /** @deprecated No Solana write at registration (D-65). Will be null. */\n explorer_url?: string | null;\n /** Wallet chain: 'solana', 'ethereum', or null (no wallet) */\n wallet_chain?: string | null;\n beat?: { genesis_hash: string; difficulty: number; status: string };\n /** Wallet info — only present for root agents with wallets */\n wallet?: WalletInfo;\n /** Next steps after registration */\n _next_steps?: { sigil?: string; heartbeat?: string };\n}\n\n/** Options for the register() function */\nexport interface RegisterOptions {\n registryUrl?: string;\n parentHash?: string;\n parentApiKey?: string;\n registrationSecret?: string;\n /** Single-use registration token from POST /register/token or POST /register/email/verify */\n registrationToken?: string;\n /** Admin-minted invite token */\n registrationInvite?: string;\n /** Hex-encoded 32-byte Ed25519 secret seed (bring-your-own Solana key) */\n walletSecretKey?: string;\n /** Wallet model: 'self-custody' (Model A) or 'operator' (Model B). Must be set explicitly to opt in. */\n walletModel?: 'self-custody' | 'operator';\n /** Wallet chain: 'solana' (default when wallet is used) or 'ethereum' (D-63) */\n walletChain?: 'solana' | 'ethereum';\n /** Wallet address for Ethereum bring-your-own (0x + 40 hex chars) */\n walletAddress?: string;\n /** Async function to sign a message with an Ethereum wallet (EIP-191 personal_sign). Returns 0x-prefixed 65-byte hex sig. */\n walletSignFn?: (message: string) => Promise<string>;\n /** Operator's Solana wallet address (base58). Required when walletModel='operator'. */\n operatorWalletAddress?: string;\n /** Function to sign a message with the operator's Solana wallet. Required when walletModel='operator'. */\n operatorSignFn?: (message: string) => Promise<string>;\n /** Optional agent metadata (arbitrary JSON object, max 4KB). Returned in /verify and /status. */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Register a new agent on the Provenonce registry.\n *\n * With registration token (from /register/token or email verification):\n * const creds = await register('my-agent', {\n * registryUrl: '...',\n * registrationToken: '<token-from-email-verify>',\n * });\n *\n * No wallet (default, single-phase):\n * const creds = await register('my-agent', { registryUrl: '...' });\n *\n * Solana self-custody wallet (Model A, two-phase):\n * const creds = await register('my-org', {\n * registryUrl: '...',\n * walletModel: 'self-custody',\n * });\n * // creds.wallet.secret_key = hex secret (SAVE THIS)\n * // creds.wallet.address = base58 Solana address\n *\n * Solana with existing key:\n * const creds = await register('my-org', {\n * registryUrl: '...',\n * walletSecretKey: '<hex-encoded-32-byte-seed>',\n * });\n *\n * Ethereum bring-your-own (two-phase):\n * const creds = await register('my-org', {\n * registryUrl: '...',\n * walletChain: 'ethereum',\n * walletAddress: '0x...',\n * walletSignFn: (msg) => wallet.signMessage(msg),\n * });\n *\n * Solana operator (Model B, two-phase):\n * const creds = await register('my-org', {\n * registryUrl: '...',\n * walletModel: 'operator',\n * operatorWalletAddress: '<base58>',\n * operatorSignFn: (msg) => signWithWallet(msg),\n * });\n *\n * Child agent (no wallet):\n * const creds = await register('worker-1', {\n * registryUrl: '...',\n * parentHash: parentCreds.hash,\n * parentApiKey: parentCreds.api_key,\n * });\n */\nexport async function register(\n name: string,\n options?: RegisterOptions,\n): Promise<RegistrationResult> {\n // SDK-P1-07/P1-08: validate inputs\n if (!name || typeof name !== 'string' || name.trim().length === 0) {\n throw new ValidationError('name is required (must be a non-empty string)');\n }\n if (name.length > 64) {\n throw new ValidationError('name must be 64 characters or fewer');\n }\n\n const url = options?.registryUrl || 'https://provenonce.io';\n try {\n new URL(url);\n } catch {\n throw new ValidationError('registryUrl is not a valid URL');\n }\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\n if (options?.registrationSecret) {\n headers['x-registration-secret'] = options.registrationSecret;\n }\n if (options?.registrationToken) {\n headers['x-registration-token'] = options.registrationToken;\n }\n if (options?.registrationInvite) {\n headers['x-registration-invite'] = options.registrationInvite;\n }\n\n // ===== CHILD REGISTRATION (no wallet, single-phase) =====\n if (options?.parentHash) {\n if (options.parentApiKey) {\n headers['Authorization'] = `Bearer ${options.parentApiKey}`;\n }\n\n const res = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, parent: options.parentHash, ...(options.metadata && { metadata: options.metadata }) }),\n });\n\n let data: RegistrationResult & { error?: string };\n try {\n data = await res.json() as RegistrationResult & { error?: string };\n } catch {\n throw new NetworkError(`Registration failed: ${res.status} ${res.statusText} (non-JSON response)`);\n }\n if (!res.ok) throw mapApiError(res.status, data, '/api/v1/register');\n return data;\n }\n\n // ===== ETHEREUM BRING-YOUR-OWN (D-63, two-phase) =====\n if (options?.walletChain === 'ethereum') {\n if (!options.walletAddress || !options.walletSignFn) {\n throw new ValidationError('Ethereum registration requires walletAddress and walletSignFn');\n }\n\n if (!/^0x[0-9a-fA-F]{40}$/.test(options.walletAddress)) {\n throw new ValidationError('walletAddress must be a valid Ethereum address (0x + 40 hex chars)');\n }\n\n // Phase 1: Get challenge nonce from server\n const challengeRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, action: 'challenge', wallet_chain: 'ethereum' }),\n });\n\n let challengeData: { nonce?: string; error?: string };\n try {\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\n } catch {\n throw new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\n }\n if (!challengeRes.ok || !challengeData.nonce) {\n throw mapApiError(challengeRes.status, challengeData, '/api/v1/register');\n }\n\n // Phase 2: Sign with Ethereum wallet (EIP-191 personal_sign)\n const nonce = challengeData.nonce;\n const message = `provenonce-register-ethereum:${nonce}:${options.walletAddress}:${name}`;\n const walletSignature = await options.walletSignFn(message);\n\n const registerRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n name,\n wallet_chain: 'ethereum',\n wallet_address: options.walletAddress,\n wallet_signature: walletSignature,\n wallet_nonce: nonce,\n ...(options.metadata && { metadata: options.metadata }),\n }),\n });\n\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; chain?: string } };\n try {\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; chain?: string } };\n } catch {\n throw new NetworkError(`Ethereum registration failed: ${registerRes.status} (non-JSON response)`);\n }\n if (!registerRes.ok) throw mapApiError(registerRes.status, data, '/api/v1/register');\n\n // Ethereum: wallet has address only (no keypair — user keeps custody externally)\n data.wallet = {\n public_key: '',\n secret_key: '',\n address: data.wallet?.address || options.walletAddress,\n chain: 'ethereum',\n };\n\n return data;\n }\n\n // ===== MODEL B: SOLANA OPERATOR WALLET REGISTRATION (two-phase) =====\n if (options?.walletModel === 'operator') {\n if (!options.operatorWalletAddress || !options.operatorSignFn) {\n throw new ValidationError('Operator registration requires operatorWalletAddress and operatorSignFn');\n }\n\n // Phase 1: Get challenge nonce from server\n const challengeRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, action: 'challenge', wallet_model: 'operator' }),\n });\n\n let challengeData: { nonce?: string; error?: string };\n try {\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\n } catch {\n throw new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\n }\n if (!challengeRes.ok || !challengeData.nonce) {\n throw mapApiError(challengeRes.status, challengeData, '/api/v1/register');\n }\n\n // Phase 2: Operator signs challenge and register\n const nonce = challengeData.nonce;\n const message = `provenonce-register-operator:${nonce}:${options.operatorWalletAddress}:${name}`;\n const walletSignature = await options.operatorSignFn(message);\n\n const registerRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n name,\n wallet_model: 'operator',\n operator_wallet_address: options.operatorWalletAddress,\n wallet_signature: walletSignature,\n wallet_nonce: nonce,\n ...(options.metadata && { metadata: options.metadata }),\n }),\n });\n\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\n try {\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\n } catch {\n throw new NetworkError(`Operator registration failed: ${registerRes.status} (non-JSON response)`);\n }\n if (!registerRes.ok) throw mapApiError(registerRes.status, data, '/api/v1/register');\n\n // Model B: wallet has address only (no secret_key/public_key — operator keeps custody)\n const addr = data.wallet?.address || data.wallet?.solana_address || options.operatorWalletAddress;\n data.wallet = {\n public_key: '',\n secret_key: '',\n solana_address: addr,\n address: addr,\n chain: 'solana',\n };\n\n return data;\n }\n\n // ===== MODEL A: SOLANA SELF-CUSTODY WALLET REGISTRATION (opt-in, two-phase) =====\n if (options?.walletModel === 'self-custody' || options?.walletSecretKey) {\n // Generate or use provided wallet keypair\n let walletKeys: { publicKey: string; secretKey: string };\n if (options?.walletSecretKey) {\n // Derive public key from provided secret\n const privRaw = Buffer.from(options.walletSecretKey, 'hex');\n const privKeyDer = Buffer.concat([ED25519_PKCS8_PREFIX, privRaw]);\n const keyObject = createPrivateKey({ key: privKeyDer, format: 'der', type: 'pkcs8' });\n const pubRaw = keyObject.export({ type: 'spki', format: 'der' }).subarray(12);\n walletKeys = {\n publicKey: Buffer.from(pubRaw).toString('hex'),\n secretKey: options.walletSecretKey,\n };\n } else {\n walletKeys = generateWalletKeypair();\n }\n\n // Phase 1: Get challenge nonce from server\n const challengeRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, action: 'challenge' }),\n });\n\n let challengeData: { nonce?: string; error?: string };\n try {\n challengeData = await challengeRes.json() as { nonce?: string; error?: string };\n } catch {\n const err = new NetworkError(`Registration challenge failed: ${challengeRes.status} (non-JSON response)`);\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\n throw err;\n }\n if (!challengeRes.ok || !challengeData.nonce) {\n // Attach wallet keys so caller can retry with the same keypair\n const err = mapApiError(challengeRes.status, challengeData, '/api/v1/register');\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\n throw err;\n }\n\n // Phase 2: Sign challenge and register\n const nonce = challengeData.nonce;\n const message = `provenonce-register:${nonce}:${walletKeys.publicKey}:${name}`;\n const walletSignature = signMessage(walletKeys.secretKey, message);\n\n const registerRes = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n name,\n wallet_public_key: walletKeys.publicKey,\n wallet_signature: walletSignature,\n wallet_nonce: nonce,\n ...(options?.metadata && { metadata: options.metadata }),\n }),\n });\n\n let data: RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\n try {\n data = await registerRes.json() as RegistrationResult & { error?: string; wallet?: { address?: string; solana_address?: string } };\n } catch {\n // Attach wallet keys so caller can retry with the same keypair\n const err = new NetworkError(`Registration failed: ${registerRes.status} (non-JSON response)`);\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\n throw err;\n }\n if (!registerRes.ok) {\n // Attach wallet keys so caller can retry with the same keypair via walletSecretKey option\n const err = mapApiError(registerRes.status, data, '/api/v1/register');\n (err as any).walletKeys = { publicKey: walletKeys.publicKey, secretKey: walletKeys.secretKey };\n throw err;\n }\n\n // Attach the wallet keys (secret is client-side only, never sent to server)\n const addr = data.wallet?.address || data.wallet?.solana_address || '';\n data.wallet = {\n public_key: walletKeys.publicKey,\n secret_key: walletKeys.secretKey,\n solana_address: addr,\n address: addr,\n chain: 'solana',\n };\n\n return data;\n }\n\n // ===== NO-WALLET REGISTRATION (D-62 default, single-phase) =====\n\n const res = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ name, ...(options?.metadata && { metadata: options.metadata }) }),\n });\n\n let data: RegistrationResult & { error?: string };\n try {\n data = await res.json() as RegistrationResult & { error?: string };\n } catch {\n throw new NetworkError(`Registration failed: ${res.status} ${res.statusText} (non-JSON response)`);\n }\n if (!res.ok) throw mapApiError(res.status, data, '/api/v1/register');\n return data;\n}\n\n// ============ SDK CONFIG ============\n\nexport interface BeatAgentConfig {\n /** API key from registration (pvn_...) */\n apiKey: string;\n\n /** Provenonce registry URL */\n registryUrl: string;\n\n /** @deprecated Use heartbeatIntervalSec. Beats to compute per pulse (default: 10) */\n beatsPerPulse?: number;\n\n /** @deprecated Use heartbeatIntervalSec. Seconds between automatic check-ins (default: 300 = 5min) */\n checkinIntervalSec?: number;\n\n /** Seconds between automatic heartbeats (default: 300 = 5min). Replaces checkinIntervalSec. */\n heartbeatIntervalSec?: number;\n\n /** @deprecated VDF pulse callback. No longer used in Phase 2. */\n onPulse?: (beats: Beat[], totalBeats: number) => void;\n\n /** @deprecated Use onHeartbeat. Callback when check-in completes. */\n onCheckin?: (result: CheckinResult) => void;\n\n /** Callback when heartbeat completes (Phase 2) */\n onHeartbeat?: (result: HeartbeatResult) => void;\n\n /** Callback on error */\n onError?: (error: Error, context: string) => void;\n\n /** Callback when status changes */\n onStatusChange?: (status: string, details: Record<string, unknown>) => void;\n\n /** Enable verbose logging */\n verbose?: boolean;\n}\n\n// ============ BEAT AGENT ============\n\nexport class BeatAgent {\n private config: Required<BeatAgentConfig>;\n private chain: Beat[] = [];\n private difficulty: number = 1000;\n private genesisHash: string = '';\n private latestBeat: Beat | null = null;\n private totalBeats: number = 0;\n private lastCheckinBeat: number = 0;\n private status: 'uninitialized' | 'active' | 'frozen' | 'revoked' = 'uninitialized';\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n private globalBeat: number = 0;\n private globalAnchorHash: string = '';\n\n constructor(config: BeatAgentConfig) {\n // SDK-P1-08: validate required config fields\n if (!config.apiKey || typeof config.apiKey !== 'string') {\n throw new ValidationError('BeatAgentConfig.apiKey is required (must be a non-empty string)');\n }\n if (!config.registryUrl || typeof config.registryUrl !== 'string') {\n throw new ValidationError('BeatAgentConfig.registryUrl is required (must be a non-empty string)');\n }\n // SDK-P1-07: validate registryUrl is a valid URL\n try {\n new URL(config.registryUrl);\n } catch {\n throw new ValidationError('BeatAgentConfig.registryUrl is not a valid URL');\n }\n\n // SDK-P2: validate optional numeric config\n if (config.beatsPerPulse !== undefined && (!Number.isInteger(config.beatsPerPulse) || config.beatsPerPulse < 1 || config.beatsPerPulse > 10000)) {\n throw new ValidationError('BeatAgentConfig.beatsPerPulse must be an integer between 1 and 10000');\n }\n if (config.checkinIntervalSec !== undefined && (!Number.isFinite(config.checkinIntervalSec) || config.checkinIntervalSec < 10 || config.checkinIntervalSec > 86400)) {\n throw new ValidationError('BeatAgentConfig.checkinIntervalSec must be between 10 and 86400');\n }\n\n this.config = {\n beatsPerPulse: 10,\n checkinIntervalSec: 300,\n heartbeatIntervalSec: 300,\n onPulse: () => {},\n onCheckin: () => {},\n onHeartbeat: () => {},\n onError: () => {},\n onStatusChange: () => {},\n verbose: false,\n ...config,\n };\n }\n\n // ── INITIALIZATION ──\n\n /**\n * Initialize the agent's Beat chain.\n * This is the agent's \"birth\" in Logical Time.\n * Must be called once before computing beats.\n */\n async init(): Promise<{ ok: boolean; genesis?: string; error?: string }> {\n try {\n this.log('Initializing Beat chain...');\n\n const res = await this.api('POST', '/api/v1/agent/init');\n\n if (res.genesis) {\n this.genesisHash = res.genesis.hash;\n this.difficulty = res.difficulty || 1000;\n this.latestBeat = {\n index: 0,\n hash: res.genesis.hash,\n prev: res.genesis.prev,\n timestamp: res.genesis.timestamp,\n };\n this.chain = [this.latestBeat];\n this.totalBeats = 0;\n this.status = 'active';\n this.config.onStatusChange('active', { genesis: this.genesisHash });\n this.log(`Born in Beat time. Genesis: ${this.genesisHash.slice(0, 16)}...`);\n } else if (res.already_initialized) {\n // Restore from existing state\n this.genesisHash = res.genesis_hash;\n this.totalBeats = res.total_beats;\n this.status = res.status as any;\n this.log(`Already initialized. Restoring state (${res.total_beats} beats).`);\n \n // Fetch full state to get latest hash\n await this.refreshState();\n }\n\n // Sync global anchor\n await this.syncGlobal();\n\n return { ok: true, genesis: this.genesisHash };\n\n } catch (err: any) {\n this.config.onError(err, 'init');\n return { ok: false, error: err.message };\n }\n }\n\n // ── PULSE (COMPUTE BEATS) ──\n\n /**\n * @deprecated Phase 2: VDF computation retired (D-68). Payment is the liveness mechanism.\n * Use heartbeat() instead. This method will be removed in the next major version.\n *\n * Compute N beats locally (VDF hash chain).\n */\n pulse(count?: number): Beat[] {\n console.warn('[Provenonce SDK] pulse() is deprecated. Use heartbeat() instead (Phase 2).');\n if (this.status === 'frozen') {\n throw new FrozenError('Cannot pulse: agent is frozen. Use resync() to re-establish provenance.');\n }\n if (this.status !== 'active') {\n throw new StateError(`Cannot pulse: agent is ${this.status}.`, this.status);\n }\n // SDK-P2: validate count param\n if (count !== undefined && (!Number.isInteger(count) || count < 1 || count > 10000)) {\n throw new ValidationError('pulse count must be an integer between 1 and 10000');\n }\n return this.computeBeats(count);\n }\n\n /** Internal beat computation — no status check. Used by both pulse() and resync(). */\n private computeBeats(count?: number, onProgress?: (computed: number, total: number) => void): Beat[] {\n const n = count || this.config.beatsPerPulse;\n\n if (!this.latestBeat) {\n throw new StateError('Beat chain not initialized. Call init() first.', 'uninitialized', ErrorCode.AGENT_NOT_INITIALIZED);\n }\n\n const newBeats: Beat[] = [];\n let prevHash = this.latestBeat.hash;\n let startIndex = this.latestBeat.index + 1;\n\n const t0 = Date.now();\n // SDK-P2: report progress every 10% of beats\n const progressInterval = Math.max(1, Math.floor(n / 10));\n\n for (let i = 0; i < n; i++) {\n const beat = computeBeat(prevHash, startIndex + i, this.difficulty, undefined, this.globalAnchorHash || undefined);\n newBeats.push(beat);\n prevHash = beat.hash;\n if (onProgress && (i + 1) % progressInterval === 0) {\n onProgress(i + 1, n);\n }\n }\n\n const elapsed = Date.now() - t0;\n\n // Update state\n this.chain.push(...newBeats);\n this.latestBeat = newBeats[newBeats.length - 1];\n this.totalBeats += n;\n\n // Keep chain bounded (only last 1000 beats in memory)\n if (this.chain.length > 1000) {\n this.chain = this.chain.slice(-500);\n }\n\n this.config.onPulse(newBeats, this.totalBeats);\n this.log(`Pulse: ${n} beats in ${elapsed}ms (${(elapsed / n).toFixed(1)}ms/beat, D=${this.difficulty})`);\n\n return newBeats;\n }\n\n // ── CHECK-IN ──\n\n /**\n * @deprecated Phase 2: VDF check-in retired (D-68). Use heartbeat() instead.\n * This method will be removed in the next major version.\n */\n async checkin(): Promise<{ ok: boolean; total_beats?: number; error?: string }> {\n console.warn('[Provenonce SDK] checkin() is deprecated. Use heartbeat() instead (Phase 2).');\n // SDK-P1-02: fix guard to compare beat indices, not totalBeats vs lastCheckinBeat\n if (!this.latestBeat || this.latestBeat.index <= this.lastCheckinBeat) {\n this.log('No new beats since last check-in. Call pulse() first.');\n return { ok: true, total_beats: this.totalBeats }; // Nothing new to report\n }\n\n try {\n // Find the boundary hashes\n const fromBeat = this.lastCheckinBeat;\n const toBeat = this.latestBeat.index;\n\n // Build spot checks from our local chain\n // prev and nonce are required for the server to recompute VDF\n // Must always include to_beat (final beat) — server requires it for final hash verification\n const spotChecks: { index: number; hash: string; prev: string; nonce?: string }[] = [];\n\n // Always include the final beat\n const toBeatEntry = this.chain.find(b => b.index === toBeat);\n if (toBeatEntry) {\n spotChecks.push({ index: toBeatEntry.index, hash: toBeatEntry.hash, prev: toBeatEntry.prev, nonce: toBeatEntry.nonce });\n }\n\n // Sample up to 4 more from the rest\n const available = this.chain.filter(b => b.index > this.lastCheckinBeat && b.index !== toBeat);\n const sampleCount = Math.min(4, available.length);\n\n for (let i = 0; i < sampleCount; i++) {\n const idx = Math.floor(Math.random() * available.length);\n const beat = available[idx];\n spotChecks.push({ index: beat.index, hash: beat.hash, prev: beat.prev, nonce: beat.nonce });\n available.splice(idx, 1);\n }\n const fromHash = this.chain.find(b => b.index === fromBeat)?.hash \n || this.genesisHash;\n const toHash = this.latestBeat.hash;\n\n const res = await this.api('POST', '/api/v1/agent/checkin', {\n proof: {\n from_beat: fromBeat,\n to_beat: toBeat,\n from_hash: fromHash,\n to_hash: toHash,\n beats_computed: toBeat - fromBeat,\n global_anchor: this.globalBeat,\n anchor_hash: this.globalAnchorHash || undefined,\n spot_checks: spotChecks,\n },\n });\n\n if (res.ok) {\n this.lastCheckinBeat = toBeat;\n this.totalBeats = res.total_beats;\n this.config.onCheckin(res);\n this.log(`Check-in accepted: ${res.beats_accepted} beats, total=${res.total_beats}, global=${res.global_beat}`);\n \n if (res.status === 'warning_overdue') {\n this.config.onStatusChange('warning', { beats_behind: res.beats_behind });\n this.log(`⚠ WARNING: ${res.beats_behind} anchors behind. Check in more frequently.`);\n }\n }\n\n return { ok: res.ok, total_beats: res.total_beats };\n\n } catch (err: any) {\n this.config.onError(err, 'checkin');\n return { ok: false, error: err.message };\n }\n }\n\n // ── AUTONOMOUS HEARTBEAT ──\n\n /**\n * Start the autonomous heartbeat loop.\n * Phase 2: Sends paid heartbeats at regular intervals.\n *\n * @param paymentTxFn - Optional function that returns a payment tx for each heartbeat.\n * If not provided, uses 'devnet-skip' (devnet only).\n */\n startHeartbeat(paymentTxFn?: () => Promise<string> | string): void {\n if (this.heartbeatInterval) {\n this.log('Heartbeat already running.');\n return;\n }\n\n if (this.status !== 'active' && this.status !== 'uninitialized') {\n throw new StateError(`Cannot start heartbeat in status '${this.status}'.`, this.status);\n }\n\n const intervalSec = this.config.heartbeatIntervalSec || this.config.checkinIntervalSec || 300;\n this.log(`Starting heartbeat (interval: ${intervalSec}s)...`);\n\n // SDK-P1-03: exponential backoff on consecutive errors\n let consecutiveErrors = 0;\n let skipCount = 0;\n\n this.heartbeatInterval = setInterval(async () => {\n if (skipCount > 0) {\n skipCount--;\n return;\n }\n\n try {\n const paymentTx = paymentTxFn ? await paymentTxFn() : 'devnet-skip';\n await this.heartbeat(paymentTx);\n consecutiveErrors = 0;\n } catch (err: any) {\n consecutiveErrors++;\n this.config.onError(err, 'heartbeat');\n skipCount = Math.min(32, Math.pow(2, consecutiveErrors - 1));\n this.log(`Heartbeat error #${consecutiveErrors}, backing off ${skipCount} ticks`);\n }\n }, intervalSec * 1000);\n }\n\n /**\n * Stop the heartbeat loop.\n */\n stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n this.log('Heartbeat stopped.');\n }\n }\n\n // ── RE-SYNC ──\n\n /**\n * @deprecated Phase 2: Resync retired (D-67). Dormancy resume is free — just call heartbeat().\n * This method will be removed in the next major version.\n */\n async resync(): Promise<{ ok: boolean; beats_required?: number; error?: string }> {\n console.warn('[Provenonce SDK] resync() is deprecated (D-67). Use heartbeat() to resume (Phase 2).');\n try {\n this.log('Requesting re-sync challenge...');\n\n // Phase 1: Get challenge\n const challenge = await this.api('POST', '/api/v1/agent/resync', {\n action: 'challenge',\n });\n\n if (!challenge.challenge) {\n return { ok: false, error: 'Failed to get challenge' };\n }\n\n const required = challenge.challenge.required_beats;\n this.difficulty = challenge.challenge.difficulty;\n this.log(`Re-sync challenge: compute ${required} beats at D=${this.difficulty}`);\n\n // Sync global anchor so beats are woven with a recent anchor hash\n await this.syncGlobal();\n\n // Compute the required beats\n const startHash = challenge.challenge.start_from_hash;\n const startBeat = challenge.challenge.start_from_beat;\n\n // Reset chain from the known point\n this.latestBeat = { index: startBeat, hash: startHash, prev: '', timestamp: Date.now() };\n this.chain = [this.latestBeat];\n\n const t0 = Date.now();\n this.computeBeats(required);\n const elapsed = Date.now() - t0;\n this.log(`Re-sync beats computed in ${elapsed}ms`);\n\n // Phase 2: Submit proof (include challenge_nonce for server verification)\n const proof = await this.api('POST', '/api/v1/agent/resync', {\n action: 'prove',\n challenge_nonce: challenge.challenge.nonce,\n proof: {\n from_beat: startBeat,\n to_beat: this.latestBeat!.index,\n from_hash: startHash,\n to_hash: this.latestBeat!.hash,\n beats_computed: required,\n global_anchor: challenge.challenge.sync_to_global,\n anchor_hash: this.globalAnchorHash || undefined,\n spot_checks: (() => {\n // Must include to_beat (final beat) — server requires it for final hash verification\n const toBeatEntry = this.chain.find(b => b.index === this.latestBeat!.index);\n // Sample from available chain beats (chain may be trimmed to 500 entries)\n const available = this.chain\n .filter(b => b.index !== this.latestBeat!.index && b.index > startBeat);\n const step = Math.max(1, Math.ceil(available.length / 5));\n const others = available\n .filter((_, i) => i % step === 0)\n .slice(0, 4);\n const checks = toBeatEntry ? [toBeatEntry, ...others] : others;\n return checks.map(b => ({ index: b.index, hash: b.hash, prev: b.prev, nonce: b.nonce }));\n })(),\n },\n });\n\n if (proof.ok) {\n this.status = 'active';\n this.totalBeats = proof.total_beats;\n this.lastCheckinBeat = this.latestBeat!.index;\n this.config.onStatusChange('active', { resynced: true });\n this.log('✓ Re-synced. Agent is alive again in Beat time.');\n }\n\n return { ok: proof.ok, beats_required: required };\n\n } catch (err: any) {\n this.config.onError(err, 'resync');\n return { ok: false, error: err.message };\n }\n }\n\n // ── SPAWN ──\n\n /**\n * Request to spawn a child agent.\n * Requires sufficient accumulated beats (Temporal Gestation).\n */\n async requestSpawn(childName?: string, childHash?: string): Promise<SpawnResult> {\n try {\n // SDK-P1-05: validate childName\n if (childName !== undefined) {\n if (typeof childName !== 'string' || childName.trim().length === 0) {\n throw new ValidationError('childName must be a non-empty string');\n }\n if (childName.length > 64) {\n throw new ValidationError('childName must be 64 characters or fewer');\n }\n }\n\n const res = await this.api('POST', '/api/v1/agent/spawn', {\n child_name: childName,\n child_hash: childHash,\n });\n\n if (res.eligible === false) {\n this.log(`Gestation incomplete: ${res.progress_pct}% (need ${res.deficit} more beats)`);\n } else if (res.ok) {\n this.log(`Child spawned: ${res.child_hash?.slice(0, 16)}...`);\n }\n\n return res;\n } catch (err: any) {\n this.config.onError(err, 'spawn');\n throw err;\n }\n }\n\n // ── PHASE 2: SIGIL + HEARTBEAT + PROOF ──\n\n /** Cached lineage proof from the most recent heartbeat or SIGIL purchase */\n private cachedProof: LineageProof | null = null;\n\n /**\n * Purchase a SIGIL (cryptographic identity) for this agent.\n * SIGILs gate heartbeating, lineage proofs, and offline verification.\n * One-time purchase — cannot be re-purchased.\n *\n * @param options - SIGIL purchase options (identity_class, principal, tier, name, payment_tx, + optional metadata)\n *\n * Legacy signature (deprecated):\n * @param identityClass - 'narrow_task' | 'autonomous' | 'orchestrator'\n * @param paymentTx - Solana transaction signature or 'devnet-skip'\n */\n async purchaseSigil(optionsOrClass: SigilPurchaseOptions | IdentityClass, paymentTx?: string): Promise<SigilResult> {\n let body: Record<string, unknown>;\n\n if (typeof optionsOrClass === 'string') {\n // Legacy signature: purchaseSigil(identityClass, paymentTx)\n if (!optionsOrClass || !['narrow_task', 'autonomous', 'orchestrator'].includes(optionsOrClass)) {\n throw new ValidationError('identityClass must be narrow_task, autonomous, or orchestrator');\n }\n if (!paymentTx || typeof paymentTx !== 'string') {\n throw new ValidationError('paymentTx is required (Solana transaction signature or \"devnet-skip\")');\n }\n body = {\n identity_class: optionsOrClass,\n payment_tx: paymentTx,\n // Legacy calls without principal/tier — server will require these now\n // Callers must migrate to the options object form\n };\n } else {\n // New signature: purchaseSigil(options)\n const opts = optionsOrClass;\n if (!opts.identity_class || !['narrow_task', 'autonomous', 'orchestrator'].includes(opts.identity_class)) {\n throw new ValidationError('identity_class must be narrow_task, autonomous, or orchestrator');\n }\n if (!opts.principal || typeof opts.principal !== 'string') {\n throw new ValidationError('principal is required');\n }\n if (!opts.tier || !['sov', 'org', 'ind', 'eph', 'sbx'].includes(opts.tier)) {\n throw new ValidationError('tier must be one of: sov, org, ind, eph, sbx');\n }\n if (!opts.payment_tx || typeof opts.payment_tx !== 'string') {\n throw new ValidationError('payment_tx is required');\n }\n\n body = { ...opts };\n }\n\n try {\n const res = await this.api('POST', '/api/v1/sigil', body);\n\n if (res.lineage_proof) {\n this.cachedProof = res.lineage_proof;\n }\n\n const sigilStr = res.sigil?.sigil || res.sigil?.identity_class || '';\n this.log(`SIGIL purchased: ${sigilStr}`);\n this.config.onStatusChange('sigil_issued', { sigil: sigilStr });\n\n return {\n ok: true,\n sigil: res.sigil,\n lineage_proof: res.lineage_proof,\n fee: res.fee,\n };\n } catch (err: any) {\n this.config.onError(err, 'purchaseSigil');\n return { ok: false, error: err.message };\n }\n }\n\n /**\n * Update mutable SIGIL metadata fields.\n * Requires a SIGIL. Cannot modify immutable fields.\n *\n * @param fields - Subset of mutable SIGIL fields to update\n */\n async updateMetadata(fields: Partial<SigilMutableFields>): Promise<MetadataUpdateResult> {\n if (!fields || Object.keys(fields).length === 0) {\n throw new ValidationError('At least one metadata field is required');\n }\n\n try {\n const res = await this.api('PATCH', '/api/v1/agent/metadata', fields);\n this.log(`Metadata updated: ${res.updated_fields?.join(', ') || 'unknown'}`);\n return {\n ok: true,\n sigil: res.sigil,\n generation: res.generation,\n updated_fields: res.updated_fields,\n };\n } catch (err: any) {\n this.config.onError(err, 'updateMetadata');\n return { ok: false, error: err.message };\n }\n }\n\n /**\n * Send a paid heartbeat to the registry.\n * Requires a SIGIL. Returns a signed lineage proof.\n * This is the Phase 2 replacement for pulse() + checkin().\n *\n * @param paymentTx - Solana transaction signature. Omit or 'devnet-skip' on devnet.\n * @param globalAnchor - Optional: the global anchor index to reference.\n */\n async heartbeat(paymentTx?: string, globalAnchor?: number): Promise<HeartbeatResult> {\n try {\n const res = await this.api('POST', '/api/v1/agent/heartbeat', {\n payment_tx: paymentTx || 'devnet-skip',\n global_anchor: globalAnchor,\n });\n\n if (res.lineage_proof) {\n this.cachedProof = res.lineage_proof;\n }\n\n if (res.ok) {\n this.status = 'active';\n const onHb = this.config.onHeartbeat || this.config.onCheckin;\n if (onHb) onHb(res);\n this.log(`Heartbeat accepted: epoch=${res.billing_epoch}, count=${res.heartbeat_count_epoch}`);\n }\n\n return {\n ok: res.ok,\n lineage_proof: res.lineage_proof,\n heartbeat_count_epoch: res.heartbeat_count_epoch,\n billing_epoch: res.billing_epoch,\n current_beat: res.current_beat,\n fee: res.fee,\n };\n } catch (err: any) {\n this.config.onError(err, 'heartbeat');\n return { ok: false, error: err.message };\n }\n }\n\n /**\n * Reissue a lineage proof. \"Reprint, not a renewal.\"\n * Does NOT create a new lineage event.\n *\n * @param paymentTx - Solana transaction signature. Omit or 'devnet-skip' on devnet.\n */\n async reissueProof(paymentTx?: string): Promise<{ ok: boolean; lineage_proof?: LineageProof; error?: string }> {\n try {\n const res = await this.api('POST', '/api/v1/agent/reissue-proof', {\n payment_tx: paymentTx || 'devnet-skip',\n });\n\n if (res.lineage_proof) {\n this.cachedProof = res.lineage_proof;\n }\n\n return { ok: true, lineage_proof: res.lineage_proof };\n } catch (err: any) {\n this.config.onError(err, 'reissueProof');\n return { ok: false, error: err.message };\n }\n }\n\n /**\n * Get the latest cached lineage proof (no network call).\n * Returns null if no proof has been obtained yet.\n */\n getLatestProof(): LineageProof | null {\n return this.cachedProof;\n }\n\n /**\n * Get the agent's passport (alias for getLatestProof).\n * The passport is the agent's portable, offline-verifiable credential.\n * Returns null if no passport has been issued yet (requires SIGIL + heartbeat).\n */\n getPassport(): Passport | null {\n return this.cachedProof;\n }\n\n /**\n * Verify a lineage proof locally using the authority public key.\n * Offline verification — no API call, no SOL cost.\n *\n * Returns a VerificationResult object. The object is truthy when valid,\n * so `if (BeatAgent.verifyProofLocally(proof, key))` still works.\n *\n * @param proof - The LineageProof to verify\n * @param authorityPubKeyHex - 32-byte hex-encoded Ed25519 public key from /.well-known/provenonce-authority.json\n * @param currentBeat - Optional current global beat index (for beatsSinceHeartbeat calculation)\n */\n static verifyProofLocally(proof: LineageProof, authorityPubKeyHex: string, currentBeat?: number): VerificationResult {\n const now = Date.now();\n const expired = now > proof.valid_until;\n\n let signatureValid = false;\n try {\n // Canonical JSON (must match server's canonicalProofData)\n const canonical = JSON.stringify({\n agent_hash: proof.agent_hash,\n agent_public_key: proof.agent_public_key,\n identity_class: proof.identity_class,\n registered_at_beat: proof.registered_at_beat,\n sigil_issued_at_beat: proof.sigil_issued_at_beat,\n last_heartbeat_beat: proof.last_heartbeat_beat,\n lineage_chain_hash: proof.lineage_chain_hash,\n issued_at: proof.issued_at,\n valid_until: proof.valid_until,\n });\n\n // Build Ed25519 public key from hex\n const pubBytes = Buffer.from(authorityPubKeyHex, 'hex');\n if (pubBytes.length === 32) {\n const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');\n const pubKeyDer = Buffer.concat([ED25519_SPKI_PREFIX, pubBytes]);\n const keyObject = createPublicKey({ key: pubKeyDer, format: 'der', type: 'spki' });\n const sigBuffer = Buffer.from(proof.provenonce_signature, 'hex');\n signatureValid = verify(null, Buffer.from(canonical), keyObject, sigBuffer);\n }\n } catch {\n signatureValid = false;\n }\n\n const valid = signatureValid && !expired;\n const beatsSinceHeartbeat = currentBeat != null ? currentBeat - proof.last_heartbeat_beat : null;\n\n let warning: string | undefined;\n if (expired) {\n warning = 'Proof has expired. Reissue with reissueProof() or send a heartbeat.';\n } else if (beatsSinceHeartbeat != null && beatsSinceHeartbeat > 60) {\n warning = `Agent is ${beatsSinceHeartbeat} beats behind. Heartbeat may be stale.`;\n }\n\n return { valid, signatureValid, expired, lastHeartbeatBeat: proof.last_heartbeat_beat, beatsSinceHeartbeat, warning };\n }\n\n // ── STATUS ──\n\n /**\n * Get this agent's full beat status from the registry.\n */\n async getStatus(): Promise<AgentStatus> {\n try {\n // We need the agent hash, but we may not have it directly.\n // The status endpoint uses the hash from the API key verification.\n // For now, use the init endpoint which returns status.\n return await this.refreshState();\n } catch (err: any) {\n this.config.onError(err, 'status');\n throw err;\n }\n }\n\n /**\n * Get local state (no network call).\n */\n getLocalState(): {\n status: string;\n totalBeats: number;\n latestBeat: number;\n latestHash: string;\n difficulty: number;\n globalBeat: number;\n chainLength: number;\n } {\n return {\n status: this.status,\n totalBeats: this.totalBeats,\n latestBeat: this.latestBeat?.index || 0,\n latestHash: this.latestBeat?.hash.slice(0, 24) + '...' || '',\n difficulty: this.difficulty,\n globalBeat: this.globalBeat,\n chainLength: this.chain.length,\n };\n }\n\n // ── INTERNALS ──\n\n private async syncGlobal(): Promise<void> {\n try {\n // SDK-P1-01: add timeout to syncGlobal fetch\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 15_000);\n const res = await fetch(`${this.config.registryUrl}/api/v1/beat/anchor`, { signal: controller.signal });\n clearTimeout(timeout);\n const data: any = await res.json();\n if (data.anchor) {\n this.globalBeat = data.anchor.beat_index;\n this.globalAnchorHash = data.anchor.hash || '';\n if (data.anchor.difficulty) this.difficulty = data.anchor.difficulty;\n this.log(`Synced to global beat ${this.globalBeat} (D=${this.difficulty})`);\n }\n } catch {\n this.log('Failed to sync global anchor (offline mode continues)');\n }\n }\n\n private async refreshState(): Promise<any> {\n const res = await this.api('POST', '/api/v1/agent/init');\n if (res.already_initialized) {\n this.totalBeats = res.total_beats;\n this.genesisHash = res.genesis_hash;\n this.status = res.status as any;\n this.difficulty = res.difficulty || this.difficulty;\n this.lastCheckinBeat = res.last_checkin_beat || 0;\n\n // Restore latestBeat so pulse() can continue the chain\n if (!this.latestBeat && this.genesisHash) {\n this.latestBeat = {\n index: res.latest_beat || this.totalBeats,\n hash: res.latest_hash || this.genesisHash,\n prev: '0'.repeat(64),\n timestamp: Date.now(),\n };\n this.chain = [this.latestBeat];\n }\n }\n return res;\n }\n\n private async api(method: string, path: string, body?: any): Promise<any> {\n // SDK-P1-01: add 30s timeout to prevent indefinite hangs\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 30_000);\n\n try {\n const res = await fetch(`${this.config.registryUrl}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.apiKey}`,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n let data: any;\n try {\n data = await res.json();\n } catch {\n throw new NetworkError(`API error: ${res.status} non-JSON response from ${path}`);\n }\n\n if (!res.ok && !data.ok && !data.already_initialized && !data.eligible) {\n throw mapApiError(res.status, data, path);\n }\n\n return data;\n } catch (err: any) {\n if (err.name === 'AbortError') {\n throw new NetworkError(`Request timeout: ${method} ${path}`, ErrorCode.TIMEOUT);\n }\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private log(msg: string): void {\n if (this.config.verbose) {\n console.log(`[Beat] ${msg}`);\n }\n }\n}\n\n// ============ STANDALONE VDF HELPER ============\n// For agents that want to compute beats without the full SDK\n\nexport { computeBeat };\n\n/**\n * Compute N sequential VDF beats.\n * Returns only the last beat (for lightweight usage).\n */\nexport function computeBeatsLite(\n startHash: string,\n startIndex: number,\n count: number,\n difficulty: number = 1000,\n anchorHash?: string,\n): { lastBeat: Beat; elapsed: number } {\n // SDK-P2: validate inputs\n if (!startHash || typeof startHash !== 'string') {\n throw new ValidationError('computeBeatsLite: startHash must be a non-empty string');\n }\n if (!Number.isInteger(count) || count < 1) {\n throw new ValidationError('computeBeatsLite: count must be a positive integer');\n }\n\n const t0 = Date.now();\n let prev = startHash;\n let lastBeat: Beat | null = null;\n\n for (let i = 0; i < count; i++) {\n lastBeat = computeBeat(prev, startIndex + i, difficulty, undefined, anchorHash);\n prev = lastBeat.hash;\n }\n\n return { lastBeat: lastBeat!, elapsed: Date.now() - t0 };\n}\n","/**\n * Provenonce SDK Error Classes\n *\n * Typed error hierarchy for programmatic error handling.\n * All errors extend ProvenonceError for catch-all, or catch specific\n * subclasses for fine-grained control:\n *\n * try {\n * await agent.checkin();\n * } catch (err) {\n * if (err instanceof RateLimitError) {\n * await sleep(err.retryAfterMs);\n * } else if (err instanceof FrozenError) {\n * await agent.resync();\n * } else if (err instanceof AuthError) {\n * console.error('Bad API key');\n * }\n * }\n */\n\n/** Error codes for programmatic switching */\nexport enum ErrorCode {\n // Validation\n VALIDATION = 'VALIDATION',\n\n // Auth\n AUTH_INVALID = 'AUTH_INVALID',\n AUTH_MISSING = 'AUTH_MISSING',\n\n // Rate limiting\n RATE_LIMITED = 'RATE_LIMITED',\n\n // Agent state\n AGENT_FROZEN = 'AGENT_FROZEN',\n AGENT_NOT_INITIALIZED = 'AGENT_NOT_INITIALIZED',\n AGENT_WRONG_STATE = 'AGENT_WRONG_STATE',\n\n // Not found\n NOT_FOUND = 'NOT_FOUND',\n\n // Network / server\n NETWORK_ERROR = 'NETWORK_ERROR',\n TIMEOUT = 'TIMEOUT',\n SERVER_ERROR = 'SERVER_ERROR',\n}\n\n/** Base error class for all Provenonce SDK errors */\nexport class ProvenonceError extends Error {\n /** Machine-readable error code */\n readonly code: ErrorCode;\n\n /** HTTP status code (if from an API response) */\n readonly statusCode?: number;\n\n /** Additional context */\n readonly details?: Record<string, unknown>;\n\n constructor(\n message: string,\n code: ErrorCode,\n statusCode?: number,\n details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'ProvenonceError';\n this.code = code;\n this.statusCode = statusCode;\n this.details = details;\n // Fix prototype chain for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when input validation fails (bad config, invalid args) */\nexport class ValidationError extends ProvenonceError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, ErrorCode.VALIDATION, undefined, details);\n this.name = 'ValidationError';\n }\n}\n\n/** Thrown on 401/403 — bad or missing API key */\nexport class AuthError extends ProvenonceError {\n constructor(\n message: string,\n code: ErrorCode.AUTH_INVALID | ErrorCode.AUTH_MISSING = ErrorCode.AUTH_INVALID,\n statusCode?: number,\n ) {\n super(message, code, statusCode);\n this.name = 'AuthError';\n }\n}\n\n/** Thrown on 429 — rate limit exceeded */\nexport class RateLimitError extends ProvenonceError {\n /** Milliseconds until the rate limit resets (if provided by server) */\n readonly retryAfterMs?: number;\n\n constructor(message: string, statusCode: number = 429, retryAfterMs?: number) {\n super(message, ErrorCode.RATE_LIMITED, statusCode);\n this.name = 'RateLimitError';\n this.retryAfterMs = retryAfterMs;\n }\n}\n\n/** Thrown when an agent is frozen and cannot perform the requested action */\nexport class FrozenError extends ProvenonceError {\n constructor(message: string = 'Agent is frozen. Use resync() to re-establish provenance.') {\n super(message, ErrorCode.AGENT_FROZEN);\n this.name = 'FrozenError';\n }\n}\n\n/** Thrown when the agent is in the wrong state for the requested action */\nexport class StateError extends ProvenonceError {\n /** The agent's current state */\n readonly currentState: string;\n\n constructor(message: string, currentState: string, code: ErrorCode = ErrorCode.AGENT_WRONG_STATE) {\n super(message, code);\n this.name = 'StateError';\n this.currentState = currentState;\n }\n}\n\n/** Thrown on 404 — agent or resource not found */\nexport class NotFoundError extends ProvenonceError {\n constructor(message: string, statusCode: number = 404) {\n super(message, ErrorCode.NOT_FOUND, statusCode);\n this.name = 'NotFoundError';\n }\n}\n\n/** Thrown on network failures — non-JSON responses, fetch errors, timeouts */\nexport class NetworkError extends ProvenonceError {\n constructor(message: string, code: ErrorCode.NETWORK_ERROR | ErrorCode.TIMEOUT = ErrorCode.NETWORK_ERROR) {\n super(message, code);\n this.name = 'NetworkError';\n }\n}\n\n/** Thrown on 5xx — unexpected server errors */\nexport class ServerError extends ProvenonceError {\n constructor(message: string, statusCode: number = 500) {\n super(message, ErrorCode.SERVER_ERROR, statusCode);\n this.name = 'ServerError';\n }\n}\n\n/**\n * Map an HTTP response + parsed body to the appropriate error class.\n * Used internally by the SDK to convert API failures to typed errors.\n */\nexport function mapApiError(\n statusCode: number,\n body: { error?: string; retry_after_ms?: number },\n path: string,\n): ProvenonceError {\n const msg = typeof body.error === 'string' ? body.error : `API error ${statusCode}`;\n\n if (statusCode === 401 || statusCode === 403) {\n const code = statusCode === 401 ? ErrorCode.AUTH_MISSING : ErrorCode.AUTH_INVALID;\n return new AuthError(msg, code, statusCode);\n }\n\n if (statusCode === 429) {\n const retryAfter = typeof body.retry_after_ms === 'number' ? body.retry_after_ms : undefined;\n return new RateLimitError(msg, statusCode, retryAfter);\n }\n\n if (statusCode === 404) {\n return new NotFoundError(msg, statusCode);\n }\n\n if (statusCode >= 500) {\n return new ServerError(msg, statusCode);\n }\n\n // Check for specific error patterns in the message\n const lowerMsg = msg.toLowerCase();\n if (lowerMsg.includes('frozen')) {\n return new FrozenError(msg);\n }\n\n // Generic client error\n return new ProvenonceError(msg, ErrorCode.SERVER_ERROR, statusCode);\n}\n"],"mappings":"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","names":["ErrorCode","res","data"]}
|