@provenonce/sdk 0.4.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,6 +8,31 @@ Agent heartbeat client for sovereign time authentication on Solana.
8
8
  npm install @provenonce/sdk
9
9
  ```
10
10
 
11
+ ## Registration
12
+
13
+ Before using the SDK, register your agent to get an API key:
14
+
15
+ ```typescript
16
+ import { register } from '@provenonce/sdk';
17
+
18
+ // Root registration (one-time)
19
+ const creds = await register('my-agent-v1', {
20
+ registryUrl: 'https://provenonce.vercel.app',
21
+ registrationSecret: process.env.REGISTRATION_SECRET, // required in production
22
+ });
23
+
24
+ console.log(creds.hash); // unique agent identity
25
+ console.log(creds.api_key); // use this for BeatAgent
26
+ console.log(creds.secret); // save — shown only once
27
+
28
+ // Child registration (requires parent credentials)
29
+ const child = await register('worker-1', {
30
+ registryUrl: 'https://provenonce.vercel.app',
31
+ parentHash: creds.hash,
32
+ parentApiKey: creds.api_key,
33
+ });
34
+ ```
35
+
11
36
  ## Quick Start
12
37
 
13
38
  ```typescript
package/dist/index.d.mts CHANGED
@@ -32,8 +32,75 @@ interface Beat {
32
32
  prev: string;
33
33
  timestamp: number;
34
34
  nonce?: string;
35
+ anchor_hash?: string;
35
36
  }
36
- declare function computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string): Beat;
37
+ declare function computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string, anchorHash?: string): Beat;
38
+ /** Result from a check-in submission */
39
+ interface CheckinResult {
40
+ ok: boolean;
41
+ total_beats: number;
42
+ beats_accepted: number;
43
+ global_beat: number;
44
+ status?: string;
45
+ beats_behind?: number;
46
+ }
47
+ /** Result from a spawn request */
48
+ interface SpawnResult {
49
+ ok: boolean;
50
+ eligible: boolean;
51
+ child_hash?: string;
52
+ progress_pct?: number;
53
+ deficit?: number;
54
+ }
55
+ /** Agent status from the registry */
56
+ interface AgentStatus {
57
+ already_initialized: boolean;
58
+ total_beats: number;
59
+ genesis_hash: string;
60
+ status: string;
61
+ genesis?: {
62
+ hash: string;
63
+ prev: string;
64
+ timestamp: number;
65
+ };
66
+ difficulty?: number;
67
+ }
68
+ /** Result from registering an agent */
69
+ interface RegistrationResult {
70
+ hash: string;
71
+ api_key: string;
72
+ secret: string;
73
+ type: 'root' | 'agent';
74
+ parent: string | null;
75
+ depth: number;
76
+ name: string;
77
+ signature: string;
78
+ explorer_url?: string;
79
+ beat?: {
80
+ genesis_hash: string;
81
+ difficulty: number;
82
+ status: string;
83
+ };
84
+ }
85
+ /**
86
+ * Register a new agent on the Provenonce registry.
87
+ *
88
+ * Root registration (no parent):
89
+ * const creds = await register('my-org', { registryUrl: '...' });
90
+ *
91
+ * Child registration:
92
+ * const creds = await register('worker-1', {
93
+ * registryUrl: '...',
94
+ * parentHash: parentCreds.hash,
95
+ * parentApiKey: parentCreds.api_key,
96
+ * });
97
+ */
98
+ declare function register(name: string, options?: {
99
+ registryUrl?: string;
100
+ parentHash?: string;
101
+ parentApiKey?: string;
102
+ registrationSecret?: string;
103
+ }): Promise<RegistrationResult>;
37
104
  interface BeatAgentConfig {
38
105
  /** API key from registration (pvn_...) */
39
106
  apiKey: string;
@@ -46,11 +113,11 @@ interface BeatAgentConfig {
46
113
  /** Callback when heartbeat ticks */
47
114
  onPulse?: (beats: Beat[], totalBeats: number) => void;
48
115
  /** Callback when check-in completes */
49
- onCheckin?: (result: any) => void;
116
+ onCheckin?: (result: CheckinResult) => void;
50
117
  /** Callback on error */
51
118
  onError?: (error: Error, context: string) => void;
52
119
  /** Callback when status changes */
53
- onStatusChange?: (status: string, details: any) => void;
120
+ onStatusChange?: (status: string, details: Record<string, unknown>) => void;
54
121
  /** Enable verbose logging */
55
122
  verbose?: boolean;
56
123
  }
@@ -65,6 +132,7 @@ declare class BeatAgent {
65
132
  private status;
66
133
  private heartbeatInterval;
67
134
  private globalBeat;
135
+ private globalAnchorHash;
68
136
  constructor(config: BeatAgentConfig);
69
137
  /**
70
138
  * Initialize the agent's Beat chain.
@@ -120,11 +188,11 @@ declare class BeatAgent {
120
188
  * Request to spawn a child agent.
121
189
  * Requires sufficient accumulated beats (Temporal Gestation).
122
190
  */
123
- requestSpawn(childName?: string, childHash?: string): Promise<any>;
191
+ requestSpawn(childName?: string, childHash?: string): Promise<SpawnResult>;
124
192
  /**
125
193
  * Get this agent's full beat status from the registry.
126
194
  */
127
- getStatus(): Promise<any>;
195
+ getStatus(): Promise<AgentStatus>;
128
196
  /**
129
197
  * Get local state (no network call).
130
198
  */
@@ -147,9 +215,9 @@ declare class BeatAgent {
147
215
  * Compute N sequential VDF beats.
148
216
  * Returns only the last beat (for lightweight usage).
149
217
  */
150
- declare function computeBeatsLite(startHash: string, startIndex: number, count: number, difficulty?: number): {
218
+ declare function computeBeatsLite(startHash: string, startIndex: number, count: number, difficulty?: number, anchorHash?: string): {
151
219
  lastBeat: Beat;
152
220
  elapsed: number;
153
221
  };
154
222
 
155
- export { type Beat, BeatAgent, type BeatAgentConfig, computeBeat, computeBeatsLite };
223
+ export { type AgentStatus, type Beat, BeatAgent, type BeatAgentConfig, type CheckinResult, type RegistrationResult, type SpawnResult, computeBeat, computeBeatsLite, register };
package/dist/index.d.ts CHANGED
@@ -32,8 +32,75 @@ interface Beat {
32
32
  prev: string;
33
33
  timestamp: number;
34
34
  nonce?: string;
35
+ anchor_hash?: string;
35
36
  }
36
- declare function computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string): Beat;
37
+ declare function computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string, anchorHash?: string): Beat;
38
+ /** Result from a check-in submission */
39
+ interface CheckinResult {
40
+ ok: boolean;
41
+ total_beats: number;
42
+ beats_accepted: number;
43
+ global_beat: number;
44
+ status?: string;
45
+ beats_behind?: number;
46
+ }
47
+ /** Result from a spawn request */
48
+ interface SpawnResult {
49
+ ok: boolean;
50
+ eligible: boolean;
51
+ child_hash?: string;
52
+ progress_pct?: number;
53
+ deficit?: number;
54
+ }
55
+ /** Agent status from the registry */
56
+ interface AgentStatus {
57
+ already_initialized: boolean;
58
+ total_beats: number;
59
+ genesis_hash: string;
60
+ status: string;
61
+ genesis?: {
62
+ hash: string;
63
+ prev: string;
64
+ timestamp: number;
65
+ };
66
+ difficulty?: number;
67
+ }
68
+ /** Result from registering an agent */
69
+ interface RegistrationResult {
70
+ hash: string;
71
+ api_key: string;
72
+ secret: string;
73
+ type: 'root' | 'agent';
74
+ parent: string | null;
75
+ depth: number;
76
+ name: string;
77
+ signature: string;
78
+ explorer_url?: string;
79
+ beat?: {
80
+ genesis_hash: string;
81
+ difficulty: number;
82
+ status: string;
83
+ };
84
+ }
85
+ /**
86
+ * Register a new agent on the Provenonce registry.
87
+ *
88
+ * Root registration (no parent):
89
+ * const creds = await register('my-org', { registryUrl: '...' });
90
+ *
91
+ * Child registration:
92
+ * const creds = await register('worker-1', {
93
+ * registryUrl: '...',
94
+ * parentHash: parentCreds.hash,
95
+ * parentApiKey: parentCreds.api_key,
96
+ * });
97
+ */
98
+ declare function register(name: string, options?: {
99
+ registryUrl?: string;
100
+ parentHash?: string;
101
+ parentApiKey?: string;
102
+ registrationSecret?: string;
103
+ }): Promise<RegistrationResult>;
37
104
  interface BeatAgentConfig {
38
105
  /** API key from registration (pvn_...) */
39
106
  apiKey: string;
@@ -46,11 +113,11 @@ interface BeatAgentConfig {
46
113
  /** Callback when heartbeat ticks */
47
114
  onPulse?: (beats: Beat[], totalBeats: number) => void;
48
115
  /** Callback when check-in completes */
49
- onCheckin?: (result: any) => void;
116
+ onCheckin?: (result: CheckinResult) => void;
50
117
  /** Callback on error */
51
118
  onError?: (error: Error, context: string) => void;
52
119
  /** Callback when status changes */
53
- onStatusChange?: (status: string, details: any) => void;
120
+ onStatusChange?: (status: string, details: Record<string, unknown>) => void;
54
121
  /** Enable verbose logging */
55
122
  verbose?: boolean;
56
123
  }
@@ -65,6 +132,7 @@ declare class BeatAgent {
65
132
  private status;
66
133
  private heartbeatInterval;
67
134
  private globalBeat;
135
+ private globalAnchorHash;
68
136
  constructor(config: BeatAgentConfig);
69
137
  /**
70
138
  * Initialize the agent's Beat chain.
@@ -120,11 +188,11 @@ declare class BeatAgent {
120
188
  * Request to spawn a child agent.
121
189
  * Requires sufficient accumulated beats (Temporal Gestation).
122
190
  */
123
- requestSpawn(childName?: string, childHash?: string): Promise<any>;
191
+ requestSpawn(childName?: string, childHash?: string): Promise<SpawnResult>;
124
192
  /**
125
193
  * Get this agent's full beat status from the registry.
126
194
  */
127
- getStatus(): Promise<any>;
195
+ getStatus(): Promise<AgentStatus>;
128
196
  /**
129
197
  * Get local state (no network call).
130
198
  */
@@ -147,9 +215,9 @@ declare class BeatAgent {
147
215
  * Compute N sequential VDF beats.
148
216
  * Returns only the last beat (for lightweight usage).
149
217
  */
150
- declare function computeBeatsLite(startHash: string, startIndex: number, count: number, difficulty?: number): {
218
+ declare function computeBeatsLite(startHash: string, startIndex: number, count: number, difficulty?: number, anchorHash?: string): {
151
219
  lastBeat: Beat;
152
220
  elapsed: number;
153
221
  };
154
222
 
155
- export { type Beat, BeatAgent, type BeatAgentConfig, computeBeat, computeBeatsLite };
223
+ export { type AgentStatus, type Beat, BeatAgent, type BeatAgentConfig, type CheckinResult, type RegistrationResult, type SpawnResult, computeBeat, computeBeatsLite, register };
package/dist/index.js CHANGED
@@ -22,19 +22,43 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  BeatAgent: () => BeatAgent,
24
24
  computeBeat: () => computeBeat,
25
- computeBeatsLite: () => computeBeatsLite
25
+ computeBeatsLite: () => computeBeatsLite,
26
+ register: () => register
26
27
  });
27
28
  module.exports = __toCommonJS(index_exports);
28
29
 
29
30
  // src/beat-sdk.ts
30
31
  var import_crypto = require("crypto");
31
- function computeBeat(prevHash, beatIndex, difficulty, nonce) {
32
+ function computeBeat(prevHash, beatIndex, difficulty, nonce, anchorHash) {
32
33
  const timestamp = Date.now();
33
- let current = (0, import_crypto.createHash)("sha256").update(`${prevHash}:${beatIndex}:${nonce || ""}`).digest("hex");
34
+ const seed = anchorHash ? `${prevHash}:${beatIndex}:${nonce || ""}:${anchorHash}` : `${prevHash}:${beatIndex}:${nonce || ""}`;
35
+ let current = (0, import_crypto.createHash)("sha256").update(seed).digest("hex");
34
36
  for (let i = 0; i < difficulty; i++) {
35
37
  current = (0, import_crypto.createHash)("sha256").update(current).digest("hex");
36
38
  }
37
- return { index: beatIndex, hash: current, prev: prevHash, timestamp, nonce };
39
+ return { index: beatIndex, hash: current, prev: prevHash, timestamp, nonce, anchor_hash: anchorHash };
40
+ }
41
+ async function register(name, options) {
42
+ const url = options?.registryUrl || "https://provenonce.vercel.app";
43
+ const body = { name };
44
+ const headers = { "Content-Type": "application/json" };
45
+ if (options?.parentHash) {
46
+ body.parent = options.parentHash;
47
+ }
48
+ if (options?.parentApiKey) {
49
+ headers["Authorization"] = `Bearer ${options.parentApiKey}`;
50
+ }
51
+ if (options?.registrationSecret) {
52
+ headers["x-registration-secret"] = options.registrationSecret;
53
+ }
54
+ const res = await fetch(`${url}/api/v1/register`, {
55
+ method: "POST",
56
+ headers,
57
+ body: JSON.stringify(body)
58
+ });
59
+ const data = await res.json();
60
+ if (!res.ok) throw new Error(data.error || "Registration failed");
61
+ return data;
38
62
  }
39
63
  var BeatAgent = class {
40
64
  constructor(config) {
@@ -47,6 +71,7 @@ var BeatAgent = class {
47
71
  this.status = "uninitialized";
48
72
  this.heartbeatInterval = null;
49
73
  this.globalBeat = 0;
74
+ this.globalAnchorHash = "";
50
75
  this.config = {
51
76
  beatsPerPulse: 10,
52
77
  checkinIntervalSec: 300,
@@ -71,7 +96,7 @@ var BeatAgent = class {
71
96
  async init() {
72
97
  try {
73
98
  this.log("Initializing Beat chain...");
74
- const res = await this.api("POST", "/api/v1/beat/init");
99
+ const res = await this.api("POST", "/api/v1/agent/init");
75
100
  if (res.genesis) {
76
101
  this.genesisHash = res.genesis.hash;
77
102
  this.difficulty = res.difficulty || 1e3;
@@ -119,7 +144,7 @@ var BeatAgent = class {
119
144
  let startIndex = this.latestBeat.index + 1;
120
145
  const t0 = Date.now();
121
146
  for (let i = 0; i < n; i++) {
122
- const beat = computeBeat(prevHash, startIndex + i, this.difficulty);
147
+ const beat = computeBeat(prevHash, startIndex + i, this.difficulty, void 0, this.globalAnchorHash || void 0);
123
148
  newBeats.push(beat);
124
149
  prevHash = beat.hash;
125
150
  }
@@ -159,7 +184,7 @@ var BeatAgent = class {
159
184
  const toBeat = this.latestBeat.index;
160
185
  const fromHash = this.chain.find((b) => b.index === fromBeat)?.hash || this.genesisHash;
161
186
  const toHash = this.latestBeat.hash;
162
- const res = await this.api("POST", "/api/v1/beat/checkin", {
187
+ const res = await this.api("POST", "/api/v1/agent/checkin", {
163
188
  proof: {
164
189
  from_beat: fromBeat,
165
190
  to_beat: toBeat,
@@ -167,6 +192,7 @@ var BeatAgent = class {
167
192
  to_hash: toHash,
168
193
  beats_computed: toBeat - fromBeat,
169
194
  global_anchor: this.globalBeat,
195
+ anchor_hash: this.globalAnchorHash || void 0,
170
196
  spot_checks: spotChecks
171
197
  }
172
198
  });
@@ -237,7 +263,7 @@ var BeatAgent = class {
237
263
  async resync() {
238
264
  try {
239
265
  this.log("Requesting re-sync challenge...");
240
- const challenge = await this.api("POST", "/api/v1/beat/resync", {
266
+ const challenge = await this.api("POST", "/api/v1/agent/resync", {
241
267
  action: "challenge"
242
268
  });
243
269
  if (!challenge.challenge) {
@@ -254,8 +280,9 @@ var BeatAgent = class {
254
280
  this.pulse(required);
255
281
  const elapsed = Date.now() - t0;
256
282
  this.log(`Re-sync beats computed in ${elapsed}ms`);
257
- const proof = await this.api("POST", "/api/v1/beat/resync", {
283
+ const proof = await this.api("POST", "/api/v1/agent/resync", {
258
284
  action: "prove",
285
+ challenge_nonce: challenge.challenge.nonce,
259
286
  proof: {
260
287
  from_beat: startBeat,
261
288
  to_beat: this.latestBeat.index,
@@ -286,7 +313,7 @@ var BeatAgent = class {
286
313
  */
287
314
  async requestSpawn(childName, childHash) {
288
315
  try {
289
- const res = await this.api("POST", "/api/v1/beat/spawn", {
316
+ const res = await this.api("POST", "/api/v1/agent/spawn", {
290
317
  child_name: childName,
291
318
  child_hash: childHash
292
319
  });
@@ -334,6 +361,7 @@ var BeatAgent = class {
334
361
  const data = await res.json();
335
362
  if (data.anchor) {
336
363
  this.globalBeat = data.anchor.beat_index;
364
+ this.globalAnchorHash = data.anchor.hash || "";
337
365
  if (data.anchor.difficulty) this.difficulty = data.anchor.difficulty;
338
366
  this.log(`Synced to global beat ${this.globalBeat} (D=${this.difficulty})`);
339
367
  }
@@ -342,7 +370,7 @@ var BeatAgent = class {
342
370
  }
343
371
  }
344
372
  async refreshState() {
345
- const res = await this.api("POST", "/api/v1/beat/init");
373
+ const res = await this.api("POST", "/api/v1/agent/init");
346
374
  if (res.already_initialized) {
347
375
  this.totalBeats = res.total_beats;
348
376
  this.genesisHash = res.genesis_hash;
@@ -371,12 +399,12 @@ var BeatAgent = class {
371
399
  }
372
400
  }
373
401
  };
374
- function computeBeatsLite(startHash, startIndex, count, difficulty = 1e3) {
402
+ function computeBeatsLite(startHash, startIndex, count, difficulty = 1e3, anchorHash) {
375
403
  const t0 = Date.now();
376
404
  let prev = startHash;
377
405
  let lastBeat = null;
378
406
  for (let i = 0; i < count; i++) {
379
- lastBeat = computeBeat(prev, startIndex + i, difficulty);
407
+ lastBeat = computeBeat(prev, startIndex + i, difficulty, void 0, anchorHash);
380
408
  prev = lastBeat.hash;
381
409
  }
382
410
  return { lastBeat, elapsed: Date.now() - t0 };
@@ -385,6 +413,7 @@ function computeBeatsLite(startHash, startIndex, count, difficulty = 1e3) {
385
413
  0 && (module.exports = {
386
414
  BeatAgent,
387
415
  computeBeat,
388
- computeBeatsLite
416
+ computeBeatsLite,
417
+ register
389
418
  });
390
419
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/beat-sdk.ts"],"sourcesContent":["export { BeatAgent, computeBeat, computeBeatsLite } from './beat-sdk';\nexport type { BeatAgentConfig, Beat } from './beat-sdk';\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.vercel.app',\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 } from 'crypto';\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}\n\nfunction computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string): Beat {\n const timestamp = Date.now();\n \n let current = createHash('sha256')\n .update(`${prevHash}:${beatIndex}:${nonce || ''}`)\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 };\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 /** Beats to compute per pulse (default: 10) */\n beatsPerPulse?: number;\n \n /** Seconds between automatic check-ins (default: 300 = 5min) */\n checkinIntervalSec?: number;\n \n /** Callback when heartbeat ticks */\n onPulse?: (beats: Beat[], totalBeats: number) => void;\n \n /** Callback when check-in completes */\n onCheckin?: (result: any) => void;\n \n /** Callback on error */\n onError?: (error: Error, context: string) => void;\n \n /** Callback when status changes */\n onStatusChange?: (status: string, details: any) => 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 \n constructor(config: BeatAgentConfig) {\n this.config = {\n beatsPerPulse: 10,\n checkinIntervalSec: 300,\n onPulse: () => {},\n onCheckin: () => {},\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/beat/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 * Compute N beats locally (VDF hash chain).\n * This is the \"heartbeat\" — proof that the agent has lived \n * through a specific window of computational time.\n */\n pulse(count?: number): Beat[] {\n const n = count || this.config.beatsPerPulse;\n \n if (!this.latestBeat) {\n throw new Error('Beat chain not initialized. Call init() first.');\n }\n\n if (this.status !== 'active') {\n throw new Error(`Cannot pulse in status '${this.status}'. Use resync() if frozen.`);\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 \n for (let i = 0; i < n; i++) {\n const beat = computeBeat(prevHash, startIndex + i, this.difficulty);\n newBeats.push(beat);\n prevHash = beat.hash;\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 * Submit a Beat proof to the registry.\n * \n * \"To remain on the Whitelist, an agent must periodically \n * submit a proof of its Local Beats to the Registry.\"\n */\n async checkin(): Promise<{ ok: boolean; total_beats?: number; error?: string }> {\n if (!this.latestBeat || this.totalBeats === this.lastCheckinBeat) {\n return { ok: true, total_beats: this.totalBeats }; // Nothing new to report\n }\n\n try {\n // Build spot checks from our local chain\n // prev and nonce are required for the server to recompute VDF\n const spotChecks: { index: number; hash: string; prev: string; nonce?: string }[] = [];\n const available = this.chain.filter(b => b.index > this.lastCheckinBeat);\n const sampleCount = Math.min(5, 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\n // Find the boundary hashes\n const fromBeat = this.lastCheckinBeat;\n const toBeat = this.latestBeat.index;\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/beat/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 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 * Computes beats continuously and checks in periodically.\n * This is \"keeping the agent alive\" in Beat time.\n */\n startHeartbeat(): void {\n if (this.heartbeatInterval) {\n this.log('Heartbeat already running.');\n return;\n }\n\n if (this.status !== 'active') {\n throw new Error(`Cannot start heartbeat in status '${this.status}'.`);\n }\n\n this.log('♡ Starting heartbeat...');\n\n this.heartbeatInterval = setInterval(async () => {\n try {\n // Compute a pulse\n this.pulse();\n \n // Check if it's time to report\n const beatsSinceCheckin = this.latestBeat!.index - this.lastCheckinBeat;\n const shouldCheckin = beatsSinceCheckin >= this.config.beatsPerPulse * 5;\n\n if (shouldCheckin) {\n await this.checkin();\n await this.syncGlobal(); // Stay synced with global time\n }\n } catch (err: any) {\n this.config.onError(err, 'heartbeat');\n }\n }, this.config.checkinIntervalSec * 1000 / 10); // pulse 10x per check-in interval\n }\n\n /**\n * Stop the heartbeat. Agent's time \"freezes.\"\n * Must call resync() when waking up.\n */\n stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n this.log('♡ Heartbeat stopped. Time frozen.');\n }\n }\n\n // ── RE-SYNC ──\n\n /**\n * Re-sync after being offline/frozen.\n * \n * \"When an agent powers down, its time 'freezes.' Upon waking,\n * it must perform a Re-Sync Challenge with the Registry to \n * fill the 'Temporal Gap' and re-establish its provenance.\"\n */\n async resync(): Promise<{ ok: boolean; beats_required?: number; error?: string }> {\n try {\n this.log('Requesting re-sync challenge...');\n\n // Phase 1: Get challenge\n const challenge = await this.api('POST', '/api/v1/beat/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 // 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.pulse(required);\n const elapsed = Date.now() - t0;\n this.log(`Re-sync beats computed in ${elapsed}ms`);\n\n // Phase 2: Submit proof\n const proof = await this.api('POST', '/api/v1/beat/resync', {\n action: 'prove',\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 spot_checks: this.chain\n .filter((_, i) => i % Math.ceil(required / 5) === 0)\n .slice(0, 5)\n .map(b => ({ index: b.index, hash: b.hash, prev: b.prev, nonce: b.nonce })),\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<any> {\n try {\n const res = await this.api('POST', '/api/v1/beat/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 // ── STATUS ──\n\n /**\n * Get this agent's full beat status from the registry.\n */\n async getStatus(): Promise<any> {\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 const res = await fetch(`${this.config.registryUrl}/api/v1/beat/anchor`);\n const data: any = await res.json();\n if (data.anchor) {\n this.globalBeat = data.anchor.beat_index;\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/beat/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 }\n return res;\n }\n\n private async api(method: string, path: string, body?: any): Promise<any> {\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 });\n\n const data: any = await res.json();\n\n if (!res.ok && !data.ok && !data.already_initialized && !data.eligible) {\n throw new Error(data.error || `API ${res.status}: ${res.statusText}`);\n }\n\n return data;\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): { lastBeat: Beat; elapsed: number } {\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);\n prev = lastBeat.hash;\n }\n\n return { lastBeat: lastBeat!, elapsed: Date.now() - t0 };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/beat-sdk.ts"],"sourcesContent":["export { BeatAgent, computeBeat, computeBeatsLite, register } from './beat-sdk';\nexport type { BeatAgentConfig, Beat, CheckinResult, SpawnResult, AgentStatus, RegistrationResult } from './beat-sdk';\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.vercel.app',\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 } from 'crypto';\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// ============ REGISTRATION ============\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 signature: string;\n explorer_url?: string;\n beat?: { genesis_hash: string; difficulty: number; status: string };\n}\n\n/**\n * Register a new agent on the Provenonce registry.\n *\n * Root registration (no parent):\n * const creds = await register('my-org', { registryUrl: '...' });\n *\n * Child registration:\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 },\n): Promise<RegistrationResult> {\n const url = options?.registryUrl || 'https://provenonce.vercel.app';\n const body: Record<string, string> = { name };\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\n if (options?.parentHash) {\n body.parent = options.parentHash;\n }\n if (options?.parentApiKey) {\n headers['Authorization'] = `Bearer ${options.parentApiKey}`;\n }\n if (options?.registrationSecret) {\n headers['x-registration-secret'] = options.registrationSecret;\n }\n\n const res = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n const data = await res.json() as RegistrationResult & { error?: string };\n if (!res.ok) throw new Error(data.error || 'Registration failed');\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 /** Beats to compute per pulse (default: 10) */\n beatsPerPulse?: number;\n \n /** Seconds between automatic check-ins (default: 300 = 5min) */\n checkinIntervalSec?: number;\n \n /** Callback when heartbeat ticks */\n onPulse?: (beats: Beat[], totalBeats: number) => void;\n \n /** Callback when check-in completes */\n onCheckin?: (result: CheckinResult) => 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 this.config = {\n beatsPerPulse: 10,\n checkinIntervalSec: 300,\n onPulse: () => {},\n onCheckin: () => {},\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 * Compute N beats locally (VDF hash chain).\n * This is the \"heartbeat\" — proof that the agent has lived \n * through a specific window of computational time.\n */\n pulse(count?: number): Beat[] {\n const n = count || this.config.beatsPerPulse;\n \n if (!this.latestBeat) {\n throw new Error('Beat chain not initialized. Call init() first.');\n }\n\n if (this.status !== 'active') {\n throw new Error(`Cannot pulse in status '${this.status}'. Use resync() if frozen.`);\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 \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 }\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 * Submit a Beat proof to the registry.\n * \n * \"To remain on the Whitelist, an agent must periodically \n * submit a proof of its Local Beats to the Registry.\"\n */\n async checkin(): Promise<{ ok: boolean; total_beats?: number; error?: string }> {\n if (!this.latestBeat || this.totalBeats === this.lastCheckinBeat) {\n return { ok: true, total_beats: this.totalBeats }; // Nothing new to report\n }\n\n try {\n // Build spot checks from our local chain\n // prev and nonce are required for the server to recompute VDF\n const spotChecks: { index: number; hash: string; prev: string; nonce?: string }[] = [];\n const available = this.chain.filter(b => b.index > this.lastCheckinBeat);\n const sampleCount = Math.min(5, 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\n // Find the boundary hashes\n const fromBeat = this.lastCheckinBeat;\n const toBeat = this.latestBeat.index;\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 * Computes beats continuously and checks in periodically.\n * This is \"keeping the agent alive\" in Beat time.\n */\n startHeartbeat(): void {\n if (this.heartbeatInterval) {\n this.log('Heartbeat already running.');\n return;\n }\n\n if (this.status !== 'active') {\n throw new Error(`Cannot start heartbeat in status '${this.status}'.`);\n }\n\n this.log('♡ Starting heartbeat...');\n\n this.heartbeatInterval = setInterval(async () => {\n try {\n // Compute a pulse\n this.pulse();\n \n // Check if it's time to report\n const beatsSinceCheckin = this.latestBeat!.index - this.lastCheckinBeat;\n const shouldCheckin = beatsSinceCheckin >= this.config.beatsPerPulse * 5;\n\n if (shouldCheckin) {\n await this.checkin();\n await this.syncGlobal(); // Stay synced with global time\n }\n } catch (err: any) {\n this.config.onError(err, 'heartbeat');\n }\n }, this.config.checkinIntervalSec * 1000 / 10); // pulse 10x per check-in interval\n }\n\n /**\n * Stop the heartbeat. Agent's time \"freezes.\"\n * Must call resync() when waking up.\n */\n stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n this.log('♡ Heartbeat stopped. Time frozen.');\n }\n }\n\n // ── RE-SYNC ──\n\n /**\n * Re-sync after being offline/frozen.\n * \n * \"When an agent powers down, its time 'freezes.' Upon waking,\n * it must perform a Re-Sync Challenge with the Registry to \n * fill the 'Temporal Gap' and re-establish its provenance.\"\n */\n async resync(): Promise<{ ok: boolean; beats_required?: number; error?: string }> {\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 // 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.pulse(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 spot_checks: this.chain\n .filter((_, i) => i % Math.ceil(required / 5) === 0)\n .slice(0, 5)\n .map(b => ({ index: b.index, hash: b.hash, prev: b.prev, nonce: b.nonce })),\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 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 // ── 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 const res = await fetch(`${this.config.registryUrl}/api/v1/beat/anchor`);\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 }\n return res;\n }\n\n private async api(method: string, path: string, body?: any): Promise<any> {\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 });\n\n const data: any = await res.json();\n\n if (!res.ok && !data.ok && !data.already_initialized && !data.eligible) {\n throw new Error(data.error || `API ${res.status}: ${res.statusText}`);\n }\n\n return data;\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 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"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,12 +1,35 @@
1
1
  // src/beat-sdk.ts
2
2
  import { createHash } from "crypto";
3
- function computeBeat(prevHash, beatIndex, difficulty, nonce) {
3
+ function computeBeat(prevHash, beatIndex, difficulty, nonce, anchorHash) {
4
4
  const timestamp = Date.now();
5
- let current = createHash("sha256").update(`${prevHash}:${beatIndex}:${nonce || ""}`).digest("hex");
5
+ const seed = anchorHash ? `${prevHash}:${beatIndex}:${nonce || ""}:${anchorHash}` : `${prevHash}:${beatIndex}:${nonce || ""}`;
6
+ let current = createHash("sha256").update(seed).digest("hex");
6
7
  for (let i = 0; i < difficulty; i++) {
7
8
  current = createHash("sha256").update(current).digest("hex");
8
9
  }
9
- return { index: beatIndex, hash: current, prev: prevHash, timestamp, nonce };
10
+ return { index: beatIndex, hash: current, prev: prevHash, timestamp, nonce, anchor_hash: anchorHash };
11
+ }
12
+ async function register(name, options) {
13
+ const url = options?.registryUrl || "https://provenonce.vercel.app";
14
+ const body = { name };
15
+ const headers = { "Content-Type": "application/json" };
16
+ if (options?.parentHash) {
17
+ body.parent = options.parentHash;
18
+ }
19
+ if (options?.parentApiKey) {
20
+ headers["Authorization"] = `Bearer ${options.parentApiKey}`;
21
+ }
22
+ if (options?.registrationSecret) {
23
+ headers["x-registration-secret"] = options.registrationSecret;
24
+ }
25
+ const res = await fetch(`${url}/api/v1/register`, {
26
+ method: "POST",
27
+ headers,
28
+ body: JSON.stringify(body)
29
+ });
30
+ const data = await res.json();
31
+ if (!res.ok) throw new Error(data.error || "Registration failed");
32
+ return data;
10
33
  }
11
34
  var BeatAgent = class {
12
35
  constructor(config) {
@@ -19,6 +42,7 @@ var BeatAgent = class {
19
42
  this.status = "uninitialized";
20
43
  this.heartbeatInterval = null;
21
44
  this.globalBeat = 0;
45
+ this.globalAnchorHash = "";
22
46
  this.config = {
23
47
  beatsPerPulse: 10,
24
48
  checkinIntervalSec: 300,
@@ -43,7 +67,7 @@ var BeatAgent = class {
43
67
  async init() {
44
68
  try {
45
69
  this.log("Initializing Beat chain...");
46
- const res = await this.api("POST", "/api/v1/beat/init");
70
+ const res = await this.api("POST", "/api/v1/agent/init");
47
71
  if (res.genesis) {
48
72
  this.genesisHash = res.genesis.hash;
49
73
  this.difficulty = res.difficulty || 1e3;
@@ -91,7 +115,7 @@ var BeatAgent = class {
91
115
  let startIndex = this.latestBeat.index + 1;
92
116
  const t0 = Date.now();
93
117
  for (let i = 0; i < n; i++) {
94
- const beat = computeBeat(prevHash, startIndex + i, this.difficulty);
118
+ const beat = computeBeat(prevHash, startIndex + i, this.difficulty, void 0, this.globalAnchorHash || void 0);
95
119
  newBeats.push(beat);
96
120
  prevHash = beat.hash;
97
121
  }
@@ -131,7 +155,7 @@ var BeatAgent = class {
131
155
  const toBeat = this.latestBeat.index;
132
156
  const fromHash = this.chain.find((b) => b.index === fromBeat)?.hash || this.genesisHash;
133
157
  const toHash = this.latestBeat.hash;
134
- const res = await this.api("POST", "/api/v1/beat/checkin", {
158
+ const res = await this.api("POST", "/api/v1/agent/checkin", {
135
159
  proof: {
136
160
  from_beat: fromBeat,
137
161
  to_beat: toBeat,
@@ -139,6 +163,7 @@ var BeatAgent = class {
139
163
  to_hash: toHash,
140
164
  beats_computed: toBeat - fromBeat,
141
165
  global_anchor: this.globalBeat,
166
+ anchor_hash: this.globalAnchorHash || void 0,
142
167
  spot_checks: spotChecks
143
168
  }
144
169
  });
@@ -209,7 +234,7 @@ var BeatAgent = class {
209
234
  async resync() {
210
235
  try {
211
236
  this.log("Requesting re-sync challenge...");
212
- const challenge = await this.api("POST", "/api/v1/beat/resync", {
237
+ const challenge = await this.api("POST", "/api/v1/agent/resync", {
213
238
  action: "challenge"
214
239
  });
215
240
  if (!challenge.challenge) {
@@ -226,8 +251,9 @@ var BeatAgent = class {
226
251
  this.pulse(required);
227
252
  const elapsed = Date.now() - t0;
228
253
  this.log(`Re-sync beats computed in ${elapsed}ms`);
229
- const proof = await this.api("POST", "/api/v1/beat/resync", {
254
+ const proof = await this.api("POST", "/api/v1/agent/resync", {
230
255
  action: "prove",
256
+ challenge_nonce: challenge.challenge.nonce,
231
257
  proof: {
232
258
  from_beat: startBeat,
233
259
  to_beat: this.latestBeat.index,
@@ -258,7 +284,7 @@ var BeatAgent = class {
258
284
  */
259
285
  async requestSpawn(childName, childHash) {
260
286
  try {
261
- const res = await this.api("POST", "/api/v1/beat/spawn", {
287
+ const res = await this.api("POST", "/api/v1/agent/spawn", {
262
288
  child_name: childName,
263
289
  child_hash: childHash
264
290
  });
@@ -306,6 +332,7 @@ var BeatAgent = class {
306
332
  const data = await res.json();
307
333
  if (data.anchor) {
308
334
  this.globalBeat = data.anchor.beat_index;
335
+ this.globalAnchorHash = data.anchor.hash || "";
309
336
  if (data.anchor.difficulty) this.difficulty = data.anchor.difficulty;
310
337
  this.log(`Synced to global beat ${this.globalBeat} (D=${this.difficulty})`);
311
338
  }
@@ -314,7 +341,7 @@ var BeatAgent = class {
314
341
  }
315
342
  }
316
343
  async refreshState() {
317
- const res = await this.api("POST", "/api/v1/beat/init");
344
+ const res = await this.api("POST", "/api/v1/agent/init");
318
345
  if (res.already_initialized) {
319
346
  this.totalBeats = res.total_beats;
320
347
  this.genesisHash = res.genesis_hash;
@@ -343,12 +370,12 @@ var BeatAgent = class {
343
370
  }
344
371
  }
345
372
  };
346
- function computeBeatsLite(startHash, startIndex, count, difficulty = 1e3) {
373
+ function computeBeatsLite(startHash, startIndex, count, difficulty = 1e3, anchorHash) {
347
374
  const t0 = Date.now();
348
375
  let prev = startHash;
349
376
  let lastBeat = null;
350
377
  for (let i = 0; i < count; i++) {
351
- lastBeat = computeBeat(prev, startIndex + i, difficulty);
378
+ lastBeat = computeBeat(prev, startIndex + i, difficulty, void 0, anchorHash);
352
379
  prev = lastBeat.hash;
353
380
  }
354
381
  return { lastBeat, elapsed: Date.now() - t0 };
@@ -356,6 +383,7 @@ function computeBeatsLite(startHash, startIndex, count, difficulty = 1e3) {
356
383
  export {
357
384
  BeatAgent,
358
385
  computeBeat,
359
- computeBeatsLite
386
+ computeBeatsLite,
387
+ register
360
388
  };
361
389
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/beat-sdk.ts"],"sourcesContent":["/**\n * ═══════════════════════════════════════════════════════════\n * PROVENONCE BEAT SDK — Agent Heartbeat Client\n * ═══════════════════════════════════════════════════════════\n * \n * \"NIST tells you what time it is.\n * Provenonce tells the agent at what speed it is allowed to exist.\"\n * \n * Usage:\n * \n * import { BeatAgent } from './beat-sdk';\n * \n * const agent = new BeatAgent({\n * apiKey: 'pvn_...',\n * registryUrl: 'https://provenonce.vercel.app',\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 } from 'crypto';\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}\n\nfunction computeBeat(prevHash: string, beatIndex: number, difficulty: number, nonce?: string): Beat {\n const timestamp = Date.now();\n \n let current = createHash('sha256')\n .update(`${prevHash}:${beatIndex}:${nonce || ''}`)\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 };\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 /** Beats to compute per pulse (default: 10) */\n beatsPerPulse?: number;\n \n /** Seconds between automatic check-ins (default: 300 = 5min) */\n checkinIntervalSec?: number;\n \n /** Callback when heartbeat ticks */\n onPulse?: (beats: Beat[], totalBeats: number) => void;\n \n /** Callback when check-in completes */\n onCheckin?: (result: any) => void;\n \n /** Callback on error */\n onError?: (error: Error, context: string) => void;\n \n /** Callback when status changes */\n onStatusChange?: (status: string, details: any) => 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 \n constructor(config: BeatAgentConfig) {\n this.config = {\n beatsPerPulse: 10,\n checkinIntervalSec: 300,\n onPulse: () => {},\n onCheckin: () => {},\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/beat/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 * Compute N beats locally (VDF hash chain).\n * This is the \"heartbeat\" — proof that the agent has lived \n * through a specific window of computational time.\n */\n pulse(count?: number): Beat[] {\n const n = count || this.config.beatsPerPulse;\n \n if (!this.latestBeat) {\n throw new Error('Beat chain not initialized. Call init() first.');\n }\n\n if (this.status !== 'active') {\n throw new Error(`Cannot pulse in status '${this.status}'. Use resync() if frozen.`);\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 \n for (let i = 0; i < n; i++) {\n const beat = computeBeat(prevHash, startIndex + i, this.difficulty);\n newBeats.push(beat);\n prevHash = beat.hash;\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 * Submit a Beat proof to the registry.\n * \n * \"To remain on the Whitelist, an agent must periodically \n * submit a proof of its Local Beats to the Registry.\"\n */\n async checkin(): Promise<{ ok: boolean; total_beats?: number; error?: string }> {\n if (!this.latestBeat || this.totalBeats === this.lastCheckinBeat) {\n return { ok: true, total_beats: this.totalBeats }; // Nothing new to report\n }\n\n try {\n // Build spot checks from our local chain\n // prev and nonce are required for the server to recompute VDF\n const spotChecks: { index: number; hash: string; prev: string; nonce?: string }[] = [];\n const available = this.chain.filter(b => b.index > this.lastCheckinBeat);\n const sampleCount = Math.min(5, 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\n // Find the boundary hashes\n const fromBeat = this.lastCheckinBeat;\n const toBeat = this.latestBeat.index;\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/beat/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 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 * Computes beats continuously and checks in periodically.\n * This is \"keeping the agent alive\" in Beat time.\n */\n startHeartbeat(): void {\n if (this.heartbeatInterval) {\n this.log('Heartbeat already running.');\n return;\n }\n\n if (this.status !== 'active') {\n throw new Error(`Cannot start heartbeat in status '${this.status}'.`);\n }\n\n this.log('♡ Starting heartbeat...');\n\n this.heartbeatInterval = setInterval(async () => {\n try {\n // Compute a pulse\n this.pulse();\n \n // Check if it's time to report\n const beatsSinceCheckin = this.latestBeat!.index - this.lastCheckinBeat;\n const shouldCheckin = beatsSinceCheckin >= this.config.beatsPerPulse * 5;\n\n if (shouldCheckin) {\n await this.checkin();\n await this.syncGlobal(); // Stay synced with global time\n }\n } catch (err: any) {\n this.config.onError(err, 'heartbeat');\n }\n }, this.config.checkinIntervalSec * 1000 / 10); // pulse 10x per check-in interval\n }\n\n /**\n * Stop the heartbeat. Agent's time \"freezes.\"\n * Must call resync() when waking up.\n */\n stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n this.log('♡ Heartbeat stopped. Time frozen.');\n }\n }\n\n // ── RE-SYNC ──\n\n /**\n * Re-sync after being offline/frozen.\n * \n * \"When an agent powers down, its time 'freezes.' Upon waking,\n * it must perform a Re-Sync Challenge with the Registry to \n * fill the 'Temporal Gap' and re-establish its provenance.\"\n */\n async resync(): Promise<{ ok: boolean; beats_required?: number; error?: string }> {\n try {\n this.log('Requesting re-sync challenge...');\n\n // Phase 1: Get challenge\n const challenge = await this.api('POST', '/api/v1/beat/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 // 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.pulse(required);\n const elapsed = Date.now() - t0;\n this.log(`Re-sync beats computed in ${elapsed}ms`);\n\n // Phase 2: Submit proof\n const proof = await this.api('POST', '/api/v1/beat/resync', {\n action: 'prove',\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 spot_checks: this.chain\n .filter((_, i) => i % Math.ceil(required / 5) === 0)\n .slice(0, 5)\n .map(b => ({ index: b.index, hash: b.hash, prev: b.prev, nonce: b.nonce })),\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<any> {\n try {\n const res = await this.api('POST', '/api/v1/beat/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 // ── STATUS ──\n\n /**\n * Get this agent's full beat status from the registry.\n */\n async getStatus(): Promise<any> {\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 const res = await fetch(`${this.config.registryUrl}/api/v1/beat/anchor`);\n const data: any = await res.json();\n if (data.anchor) {\n this.globalBeat = data.anchor.beat_index;\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/beat/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 }\n return res;\n }\n\n private async api(method: string, path: string, body?: any): Promise<any> {\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 });\n\n const data: any = await res.json();\n\n if (!res.ok && !data.ok && !data.already_initialized && !data.eligible) {\n throw new Error(data.error || `API ${res.status}: ${res.statusText}`);\n }\n\n return data;\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): { lastBeat: Beat; elapsed: number } {\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);\n prev = lastBeat.hash;\n }\n\n return { lastBeat: lastBeat!, elapsed: Date.now() - t0 };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/beat-sdk.ts"],"sourcesContent":["/**\n * ═══════════════════════════════════════════════════════════\n * PROVENONCE BEAT SDK — Agent Heartbeat Client\n * ═══════════════════════════════════════════════════════════\n * \n * \"NIST tells you what time it is.\n * Provenonce tells the agent at what speed it is allowed to exist.\"\n * \n * Usage:\n * \n * import { BeatAgent } from './beat-sdk';\n * \n * const agent = new BeatAgent({\n * apiKey: 'pvn_...',\n * registryUrl: 'https://provenonce.vercel.app',\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 } from 'crypto';\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// ============ REGISTRATION ============\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 signature: string;\n explorer_url?: string;\n beat?: { genesis_hash: string; difficulty: number; status: string };\n}\n\n/**\n * Register a new agent on the Provenonce registry.\n *\n * Root registration (no parent):\n * const creds = await register('my-org', { registryUrl: '...' });\n *\n * Child registration:\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 },\n): Promise<RegistrationResult> {\n const url = options?.registryUrl || 'https://provenonce.vercel.app';\n const body: Record<string, string> = { name };\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\n if (options?.parentHash) {\n body.parent = options.parentHash;\n }\n if (options?.parentApiKey) {\n headers['Authorization'] = `Bearer ${options.parentApiKey}`;\n }\n if (options?.registrationSecret) {\n headers['x-registration-secret'] = options.registrationSecret;\n }\n\n const res = await fetch(`${url}/api/v1/register`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n const data = await res.json() as RegistrationResult & { error?: string };\n if (!res.ok) throw new Error(data.error || 'Registration failed');\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 /** Beats to compute per pulse (default: 10) */\n beatsPerPulse?: number;\n \n /** Seconds between automatic check-ins (default: 300 = 5min) */\n checkinIntervalSec?: number;\n \n /** Callback when heartbeat ticks */\n onPulse?: (beats: Beat[], totalBeats: number) => void;\n \n /** Callback when check-in completes */\n onCheckin?: (result: CheckinResult) => 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 this.config = {\n beatsPerPulse: 10,\n checkinIntervalSec: 300,\n onPulse: () => {},\n onCheckin: () => {},\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 * Compute N beats locally (VDF hash chain).\n * This is the \"heartbeat\" — proof that the agent has lived \n * through a specific window of computational time.\n */\n pulse(count?: number): Beat[] {\n const n = count || this.config.beatsPerPulse;\n \n if (!this.latestBeat) {\n throw new Error('Beat chain not initialized. Call init() first.');\n }\n\n if (this.status !== 'active') {\n throw new Error(`Cannot pulse in status '${this.status}'. Use resync() if frozen.`);\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 \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 }\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 * Submit a Beat proof to the registry.\n * \n * \"To remain on the Whitelist, an agent must periodically \n * submit a proof of its Local Beats to the Registry.\"\n */\n async checkin(): Promise<{ ok: boolean; total_beats?: number; error?: string }> {\n if (!this.latestBeat || this.totalBeats === this.lastCheckinBeat) {\n return { ok: true, total_beats: this.totalBeats }; // Nothing new to report\n }\n\n try {\n // Build spot checks from our local chain\n // prev and nonce are required for the server to recompute VDF\n const spotChecks: { index: number; hash: string; prev: string; nonce?: string }[] = [];\n const available = this.chain.filter(b => b.index > this.lastCheckinBeat);\n const sampleCount = Math.min(5, 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\n // Find the boundary hashes\n const fromBeat = this.lastCheckinBeat;\n const toBeat = this.latestBeat.index;\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 * Computes beats continuously and checks in periodically.\n * This is \"keeping the agent alive\" in Beat time.\n */\n startHeartbeat(): void {\n if (this.heartbeatInterval) {\n this.log('Heartbeat already running.');\n return;\n }\n\n if (this.status !== 'active') {\n throw new Error(`Cannot start heartbeat in status '${this.status}'.`);\n }\n\n this.log('♡ Starting heartbeat...');\n\n this.heartbeatInterval = setInterval(async () => {\n try {\n // Compute a pulse\n this.pulse();\n \n // Check if it's time to report\n const beatsSinceCheckin = this.latestBeat!.index - this.lastCheckinBeat;\n const shouldCheckin = beatsSinceCheckin >= this.config.beatsPerPulse * 5;\n\n if (shouldCheckin) {\n await this.checkin();\n await this.syncGlobal(); // Stay synced with global time\n }\n } catch (err: any) {\n this.config.onError(err, 'heartbeat');\n }\n }, this.config.checkinIntervalSec * 1000 / 10); // pulse 10x per check-in interval\n }\n\n /**\n * Stop the heartbeat. Agent's time \"freezes.\"\n * Must call resync() when waking up.\n */\n stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n this.log('♡ Heartbeat stopped. Time frozen.');\n }\n }\n\n // ── RE-SYNC ──\n\n /**\n * Re-sync after being offline/frozen.\n * \n * \"When an agent powers down, its time 'freezes.' Upon waking,\n * it must perform a Re-Sync Challenge with the Registry to \n * fill the 'Temporal Gap' and re-establish its provenance.\"\n */\n async resync(): Promise<{ ok: boolean; beats_required?: number; error?: string }> {\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 // 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.pulse(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 spot_checks: this.chain\n .filter((_, i) => i % Math.ceil(required / 5) === 0)\n .slice(0, 5)\n .map(b => ({ index: b.index, hash: b.hash, prev: b.prev, nonce: b.nonce })),\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 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 // ── 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 const res = await fetch(`${this.config.registryUrl}/api/v1/beat/anchor`);\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 }\n return res;\n }\n\n private async api(method: string, path: string, body?: any): Promise<any> {\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 });\n\n const data: any = await res.json();\n\n if (!res.ok && !data.ok && !data.already_initialized && !data.eligible) {\n throw new Error(data.error || `API ${res.status}: ${res.statusText}`);\n }\n\n return data;\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 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"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@provenonce/sdk",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "description": "Provenonce Beat SDK — Agent heartbeat client for sovereign time authentication",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",