@provenonce/sdk 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -148
- package/dist/index.d.mts +92 -5
- package/dist/index.d.ts +92 -5
- package/dist/index.js +88 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +88 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +43 -43
package/dist/index.js
CHANGED
|
@@ -723,26 +723,51 @@ var BeatAgent = class {
|
|
|
723
723
|
* SIGILs gate heartbeating, lineage proofs, and offline verification.
|
|
724
724
|
* One-time purchase — cannot be re-purchased.
|
|
725
725
|
*
|
|
726
|
-
* @param
|
|
727
|
-
*
|
|
726
|
+
* @param options - SIGIL purchase options (identity_class, principal, tier, name, payment_tx, + optional metadata)
|
|
727
|
+
*
|
|
728
|
+
* Legacy signature (deprecated):
|
|
729
|
+
* @param identityClass - 'narrow_task' | 'autonomous' | 'orchestrator'
|
|
730
|
+
* @param paymentTx - Solana transaction signature or 'devnet-skip'
|
|
728
731
|
*/
|
|
729
|
-
async purchaseSigil(
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
732
|
+
async purchaseSigil(optionsOrClass, paymentTx) {
|
|
733
|
+
let body;
|
|
734
|
+
if (typeof optionsOrClass === "string") {
|
|
735
|
+
if (!optionsOrClass || !["narrow_task", "autonomous", "orchestrator"].includes(optionsOrClass)) {
|
|
736
|
+
throw new ValidationError("identityClass must be narrow_task, autonomous, or orchestrator");
|
|
737
|
+
}
|
|
738
|
+
if (!paymentTx || typeof paymentTx !== "string") {
|
|
739
|
+
throw new ValidationError('paymentTx is required (Solana transaction signature or "devnet-skip")');
|
|
740
|
+
}
|
|
741
|
+
body = {
|
|
742
|
+
identity_class: optionsOrClass,
|
|
743
|
+
payment_tx: paymentTx
|
|
744
|
+
// Legacy calls without principal/tier — server will require these now
|
|
745
|
+
// Callers must migrate to the options object form
|
|
746
|
+
};
|
|
747
|
+
} else {
|
|
748
|
+
const opts = optionsOrClass;
|
|
749
|
+
if (!opts.identity_class || !["narrow_task", "autonomous", "orchestrator"].includes(opts.identity_class)) {
|
|
750
|
+
throw new ValidationError("identity_class must be narrow_task, autonomous, or orchestrator");
|
|
751
|
+
}
|
|
752
|
+
if (!opts.principal || typeof opts.principal !== "string") {
|
|
753
|
+
throw new ValidationError("principal is required");
|
|
754
|
+
}
|
|
755
|
+
if (!opts.tier || !["sov", "org", "ind", "eph", "sbx"].includes(opts.tier)) {
|
|
756
|
+
throw new ValidationError("tier must be one of: sov, org, ind, eph, sbx");
|
|
757
|
+
}
|
|
758
|
+
if (!opts.payment_tx || typeof opts.payment_tx !== "string") {
|
|
759
|
+
throw new ValidationError("payment_tx is required");
|
|
760
|
+
}
|
|
761
|
+
body = { ...opts };
|
|
735
762
|
}
|
|
736
763
|
try {
|
|
737
|
-
const res = await this.api("POST", "/api/v1/sigil",
|
|
738
|
-
identity_class: identityClass,
|
|
739
|
-
payment_tx: paymentTx
|
|
740
|
-
});
|
|
764
|
+
const res = await this.api("POST", "/api/v1/sigil", body);
|
|
741
765
|
if (res.lineage_proof) {
|
|
742
766
|
this.cachedProof = res.lineage_proof;
|
|
743
767
|
}
|
|
744
|
-
|
|
745
|
-
this.
|
|
768
|
+
const sigilStr = res.sigil?.sigil || res.sigil?.identity_class || "";
|
|
769
|
+
this.log(`SIGIL purchased: ${sigilStr}`);
|
|
770
|
+
this.config.onStatusChange("sigil_issued", { sigil: sigilStr });
|
|
746
771
|
return {
|
|
747
772
|
ok: true,
|
|
748
773
|
sigil: res.sigil,
|
|
@@ -754,6 +779,30 @@ var BeatAgent = class {
|
|
|
754
779
|
return { ok: false, error: err.message };
|
|
755
780
|
}
|
|
756
781
|
}
|
|
782
|
+
/**
|
|
783
|
+
* Update mutable SIGIL metadata fields.
|
|
784
|
+
* Requires a SIGIL. Cannot modify immutable fields.
|
|
785
|
+
*
|
|
786
|
+
* @param fields - Subset of mutable SIGIL fields to update
|
|
787
|
+
*/
|
|
788
|
+
async updateMetadata(fields) {
|
|
789
|
+
if (!fields || Object.keys(fields).length === 0) {
|
|
790
|
+
throw new ValidationError("At least one metadata field is required");
|
|
791
|
+
}
|
|
792
|
+
try {
|
|
793
|
+
const res = await this.api("PATCH", "/api/v1/agent/metadata", fields);
|
|
794
|
+
this.log(`Metadata updated: ${res.updated_fields?.join(", ") || "unknown"}`);
|
|
795
|
+
return {
|
|
796
|
+
ok: true,
|
|
797
|
+
sigil: res.sigil,
|
|
798
|
+
generation: res.generation,
|
|
799
|
+
updated_fields: res.updated_fields
|
|
800
|
+
};
|
|
801
|
+
} catch (err) {
|
|
802
|
+
this.config.onError(err, "updateMetadata");
|
|
803
|
+
return { ok: false, error: err.message };
|
|
804
|
+
}
|
|
805
|
+
}
|
|
757
806
|
/**
|
|
758
807
|
* Send a paid heartbeat to the registry.
|
|
759
808
|
* Requires a SIGIL. Returns a signed lineage proof.
|
|
@@ -829,14 +878,18 @@ var BeatAgent = class {
|
|
|
829
878
|
* Verify a lineage proof locally using the authority public key.
|
|
830
879
|
* Offline verification — no API call, no SOL cost.
|
|
831
880
|
*
|
|
881
|
+
* Returns a VerificationResult object. The object is truthy when valid,
|
|
882
|
+
* so `if (BeatAgent.verifyProofLocally(proof, key))` still works.
|
|
883
|
+
*
|
|
832
884
|
* @param proof - The LineageProof to verify
|
|
833
885
|
* @param authorityPubKeyHex - 32-byte hex-encoded Ed25519 public key from /.well-known/provenonce-authority.json
|
|
886
|
+
* @param currentBeat - Optional current global beat index (for beatsSinceHeartbeat calculation)
|
|
834
887
|
*/
|
|
835
|
-
static verifyProofLocally(proof, authorityPubKeyHex) {
|
|
888
|
+
static verifyProofLocally(proof, authorityPubKeyHex, currentBeat) {
|
|
889
|
+
const now = Date.now();
|
|
890
|
+
const expired = now > proof.valid_until;
|
|
891
|
+
let signatureValid = false;
|
|
836
892
|
try {
|
|
837
|
-
if (Date.now() > proof.valid_until) {
|
|
838
|
-
return false;
|
|
839
|
-
}
|
|
840
893
|
const canonical = JSON.stringify({
|
|
841
894
|
agent_hash: proof.agent_hash,
|
|
842
895
|
agent_public_key: proof.agent_public_key,
|
|
@@ -849,15 +902,25 @@ var BeatAgent = class {
|
|
|
849
902
|
valid_until: proof.valid_until
|
|
850
903
|
});
|
|
851
904
|
const pubBytes = Buffer.from(authorityPubKeyHex, "hex");
|
|
852
|
-
if (pubBytes.length
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
905
|
+
if (pubBytes.length === 32) {
|
|
906
|
+
const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
907
|
+
const pubKeyDer = Buffer.concat([ED25519_SPKI_PREFIX, pubBytes]);
|
|
908
|
+
const keyObject = (0, import_crypto.createPublicKey)({ key: pubKeyDer, format: "der", type: "spki" });
|
|
909
|
+
const sigBuffer = Buffer.from(proof.provenonce_signature, "hex");
|
|
910
|
+
signatureValid = (0, import_crypto.verify)(null, Buffer.from(canonical), keyObject, sigBuffer);
|
|
911
|
+
}
|
|
858
912
|
} catch {
|
|
859
|
-
|
|
913
|
+
signatureValid = false;
|
|
914
|
+
}
|
|
915
|
+
const valid = signatureValid && !expired;
|
|
916
|
+
const beatsSinceHeartbeat = currentBeat != null ? currentBeat - proof.last_heartbeat_beat : null;
|
|
917
|
+
let warning;
|
|
918
|
+
if (expired) {
|
|
919
|
+
warning = "Proof has expired. Reissue with reissueProof() or send a heartbeat.";
|
|
920
|
+
} else if (beatsSinceHeartbeat != null && beatsSinceHeartbeat > 60) {
|
|
921
|
+
warning = `Agent is ${beatsSinceHeartbeat} beats behind. Heartbeat may be stale.`;
|
|
860
922
|
}
|
|
923
|
+
return { valid, signatureValid, expired, lastHeartbeatBeat: proof.last_heartbeat_beat, beatsSinceHeartbeat, warning };
|
|
861
924
|
}
|
|
862
925
|
// ── STATUS ──
|
|
863
926
|
/**
|
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';\nexport type {\n BeatAgentConfig,\n Beat,\n CheckinResult,\n SpawnResult,\n AgentStatus,\n RegistrationResult,\n WalletInfo,\n // Phase 2 types\n IdentityClass,\n LineageProof,\n Passport,\n SigilResult,\n HeartbeatResult,\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/**\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/** Result from purchasing a SIGIL (Structured Identity Governance and Intelligent Lookup) */\nexport interface SigilResult {\n ok: boolean;\n sigil?: {\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 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/**\n * Register a new agent on the Provenonce registry.\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?: {\n registryUrl?: string;\n parentHash?: string;\n parentApiKey?: string;\n registrationSecret?: 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): 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\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 identityClass - 'narrow_task' (0.05 SOL), 'autonomous' (0.15 SOL), or 'orchestrator' (0.35 SOL)\n * @param paymentTx - Solana transaction signature proving payment. Use 'devnet-skip' on devnet.\n */\n async purchaseSigil(identityClass: IdentityClass, paymentTx: string): Promise<SigilResult> {\n if (!identityClass || !['narrow_task', 'autonomous', 'orchestrator'].includes(identityClass)) {\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\n try {\n const res = await this.api('POST', '/api/v1/sigil', {\n identity_class: identityClass,\n payment_tx: paymentTx,\n });\n\n if (res.lineage_proof) {\n this.cachedProof = res.lineage_proof;\n }\n\n this.log(`SIGIL purchased: ${identityClass}`);\n this.config.onStatusChange('sigil_issued', { identity_class: identityClass });\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 * 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 * @param proof - The LineageProof to verify\n * @param authorityPubKeyHex - 32-byte hex-encoded Ed25519 public key from /.well-known/provenonce-authority.json\n */\n static verifyProofLocally(proof: LineageProof, authorityPubKeyHex: string): boolean {\n try {\n // Check expiry\n if (Date.now() > proof.valid_until) {\n return false;\n }\n\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) return false;\n\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\n const sigBuffer = Buffer.from(proof.provenonce_signature, 'hex');\n return verify(null, Buffer.from(canonical), keyObject, sigBuffer);\n } catch {\n return false;\n }\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"]}
|
|
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"]}
|