@feltdb/core 0.5.7 → 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.
Files changed (48) hide show
  1. package/dist/cli/commands.js +68 -1
  2. package/dist/cli/workspace-integration.js +96 -0
  3. package/dist/create/cli.js +1 -1
  4. package/dist/create/create.js +21 -0
  5. package/dist/create/package-versions.js +1 -1
  6. package/dist/create/server-source/Cargo.lock +10 -0
  7. package/dist/create/server-source/crates/feltdb-server/Cargo.toml +1 -0
  8. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +5 -1
  9. package/dist/create/server-source/crates/feltdb-server/src/authenticated_principal.rs +273 -0
  10. package/dist/create/server-source/crates/feltdb-server/src/certification_harness.rs +528 -0
  11. package/dist/create/server-source/crates/feltdb-server/src/delegation_token.rs +472 -0
  12. package/dist/create/server-source/crates/feltdb-server/src/durable_operations.rs +992 -0
  13. package/dist/create/server-source/crates/feltdb-server/src/lib.rs +9 -0
  14. package/dist/create/server-source/crates/feltdb-server/src/main.rs +157 -9
  15. package/dist/create/server-source/crates/feltdb-server/src/managed_diagnostics.rs +413 -0
  16. package/dist/create/server-source/crates/feltdb-server/src/membership_policy.rs +488 -0
  17. package/dist/create/server-source/crates/feltdb-server/src/snapshot_cursor.rs +378 -0
  18. package/dist/create/server-source/crates/feltdb-server/src/tenancy.rs +49 -0
  19. package/dist/create/server-source/crates/feltdb-server/src/tenant_policies.rs +525 -0
  20. package/dist/create/server-source/crates/feltdb-server/src/transaction_recovery.rs +461 -0
  21. package/dist/create/template/dot-feltdb-README.md +58 -0
  22. package/dist/create/workspace-initialization.js +77 -0
  23. package/dist/index.d.ts +6 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +6 -0
  26. package/dist/studio-app/assets/{feltdb_wasm-h9mxesnH.js → feltdb_wasm-B4wq4mqp.js} +1 -1
  27. package/dist/studio-app/assets/feltdb_wasm_bg-Ceyi7l21.wasm +0 -0
  28. package/dist/studio-app/assets/{index-B_EMnTaE.js → index-LQmvJSq6.js} +2 -2
  29. package/dist/studio-app/index.html +1 -1
  30. package/dist/telemetry.js +1 -1
  31. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  32. package/dist/workspace/development-node.d.ts +42 -0
  33. package/dist/workspace/development-node.d.ts.map +1 -0
  34. package/dist/workspace/development-node.js +208 -0
  35. package/dist/workspace/index.d.ts +20 -0
  36. package/dist/workspace/index.d.ts.map +1 -0
  37. package/dist/workspace/index.js +16 -0
  38. package/dist/workspace/workspace-connection.d.ts +174 -0
  39. package/dist/workspace/workspace-connection.d.ts.map +1 -0
  40. package/dist/workspace/workspace-connection.js +290 -0
  41. package/dist/workspace/workspace-identity.d.ts +13 -0
  42. package/dist/workspace/workspace-identity.d.ts.map +1 -0
  43. package/dist/workspace/workspace-identity.js +70 -0
  44. package/dist/workspace/workspace-types.d.ts +82 -0
  45. package/dist/workspace/workspace-types.d.ts.map +1 -0
  46. package/dist/workspace/workspace-types.js +7 -0
  47. package/package.json +5 -1
  48. package/dist/studio-app/assets/feltdb_wasm_bg-B8U4A1n1.wasm +0 -0
@@ -0,0 +1,461 @@
1
+ use serde::{Deserialize, Serialize};
2
+ use sha2::{Digest, Sha256};
3
+ use std::collections::HashMap;
4
+ use std::sync::{Arc, RwLock};
5
+ use std::time::{SystemTime, UNIX_EPOCH};
6
+
7
+ /// Transaction status for idempotency and recovery.
8
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9
+ #[serde(rename_all = "lowercase")]
10
+ pub enum TransactionStatus {
11
+ /// Transaction status is unknown (may be in-flight or lost).
12
+ Unknown,
13
+ /// Transaction successfully committed.
14
+ Committed,
15
+ /// Transaction was rejected (validation failure).
16
+ Rejected,
17
+ /// Transaction conflicted (concurrent write or version mismatch).
18
+ Conflicted,
19
+ }
20
+
21
+ /// Record of a transaction for idempotency and recovery.
22
+ #[derive(Debug, Clone, Serialize, Deserialize)]
23
+ pub struct TransactionRecord {
24
+ /// Unique transaction ID.
25
+ pub transaction_id: String,
26
+
27
+ /// Current status of the transaction.
28
+ pub status: TransactionStatus,
29
+
30
+ /// Hash of the payload for idempotency checking.
31
+ /// Same ID + same payload = retry is safe
32
+ /// Same ID + different payload = conflict
33
+ pub payload_hash: String,
34
+
35
+ /// State version after transaction (if committed).
36
+ pub state_version: u64,
37
+
38
+ /// When this transaction was recorded.
39
+ pub recorded_at: u64,
40
+
41
+ /// When the transaction was committed (if successful).
42
+ pub committed_at: Option<u64>,
43
+
44
+ /// Reason for rejection or conflict (if applicable).
45
+ pub error: Option<String>,
46
+ }
47
+
48
+ /// Request to check transaction status.
49
+ #[derive(Debug, Clone, Serialize, Deserialize)]
50
+ pub struct TransactionStatusRequest {
51
+ pub transaction_id: String,
52
+ pub payload_hash: Option<String>,
53
+ }
54
+
55
+ /// Response with transaction status.
56
+ #[derive(Debug, Clone, Serialize, Deserialize)]
57
+ pub struct TransactionStatusResponse {
58
+ pub transaction_id: String,
59
+ pub status: TransactionStatus,
60
+ pub payload_hash: String,
61
+ pub state_version: u64,
62
+ pub committed_at: Option<u64>,
63
+ pub error: Option<String>,
64
+ }
65
+
66
+ /// Recoverable transaction store.
67
+ #[derive(Clone)]
68
+ pub struct TransactionRecoveryStore {
69
+ records: Arc<RwLock<HashMap<String, TransactionRecord>>>,
70
+ }
71
+
72
+ impl TransactionRecoveryStore {
73
+ /// Creates a new recovery store.
74
+ pub fn new() -> Self {
75
+ Self {
76
+ records: Arc::new(RwLock::new(HashMap::new())),
77
+ }
78
+ }
79
+
80
+ /// Records a transaction being processed.
81
+ pub fn record_unknown(
82
+ &self,
83
+ transaction_id: String,
84
+ payload_hash: String,
85
+ ) -> Result<(), String> {
86
+ let mut records = self
87
+ .records
88
+ .write()
89
+ .map_err(|_| "store lock poisoned".to_string())?;
90
+
91
+ let id = transaction_id.clone();
92
+ records.insert(
93
+ transaction_id,
94
+ TransactionRecord {
95
+ transaction_id: id,
96
+ status: TransactionStatus::Unknown,
97
+ payload_hash,
98
+ state_version: 0,
99
+ recorded_at: now(),
100
+ committed_at: None,
101
+ error: None,
102
+ },
103
+ );
104
+
105
+ Ok(())
106
+ }
107
+
108
+ /// Records a successful commit.
109
+ pub fn record_committed(
110
+ &self,
111
+ transaction_id: String,
112
+ payload_hash: String,
113
+ state_version: u64,
114
+ ) -> Result<(), String> {
115
+ let mut records = self
116
+ .records
117
+ .write()
118
+ .map_err(|_| "store lock poisoned".to_string())?;
119
+
120
+ let txn_id = transaction_id.clone();
121
+ records.insert(
122
+ txn_id.clone(),
123
+ TransactionRecord {
124
+ transaction_id: txn_id,
125
+ status: TransactionStatus::Committed,
126
+ payload_hash,
127
+ state_version,
128
+ recorded_at: now(),
129
+ committed_at: Some(now()),
130
+ error: None,
131
+ },
132
+ );
133
+
134
+ Ok(())
135
+ }
136
+
137
+ /// Records a rejection.
138
+ pub fn record_rejected(
139
+ &self,
140
+ transaction_id: String,
141
+ payload_hash: String,
142
+ error: String,
143
+ ) -> Result<(), String> {
144
+ let mut records = self
145
+ .records
146
+ .write()
147
+ .map_err(|_| "store lock poisoned".to_string())?;
148
+
149
+ let id = transaction_id.clone();
150
+ records.insert(
151
+ id.clone(),
152
+ TransactionRecord {
153
+ transaction_id: id,
154
+ status: TransactionStatus::Rejected,
155
+ payload_hash,
156
+ state_version: 0,
157
+ recorded_at: now(),
158
+ committed_at: None,
159
+ error: Some(error),
160
+ },
161
+ );
162
+
163
+ Ok(())
164
+ }
165
+
166
+ /// Records a conflict.
167
+ pub fn record_conflicted(
168
+ &self,
169
+ transaction_id: String,
170
+ payload_hash: String,
171
+ error: String,
172
+ ) -> Result<(), String> {
173
+ let mut records = self
174
+ .records
175
+ .write()
176
+ .map_err(|_| "store lock poisoned".to_string())?;
177
+
178
+ let id = transaction_id.clone();
179
+ records.insert(
180
+ id.clone(),
181
+ TransactionRecord {
182
+ transaction_id: id,
183
+ status: TransactionStatus::Conflicted,
184
+ payload_hash,
185
+ state_version: 0,
186
+ recorded_at: now(),
187
+ committed_at: None,
188
+ error: Some(error),
189
+ },
190
+ );
191
+
192
+ Ok(())
193
+ }
194
+
195
+ /// Gets transaction status.
196
+ pub fn get_status(&self, transaction_id: &str) -> Result<TransactionStatusResponse, String> {
197
+ let records = self
198
+ .records
199
+ .read()
200
+ .map_err(|_| "store lock poisoned".to_string())?;
201
+
202
+ let record = records
203
+ .get(transaction_id)
204
+ .ok_or(format!("transaction not found: {}", transaction_id))?;
205
+
206
+ Ok(TransactionStatusResponse {
207
+ transaction_id: record.transaction_id.clone(),
208
+ status: record.status,
209
+ payload_hash: record.payload_hash.clone(),
210
+ state_version: record.state_version,
211
+ committed_at: record.committed_at,
212
+ error: record.error.clone(),
213
+ })
214
+ }
215
+
216
+ /// Checks if a retry is safe (idempotent).
217
+ pub fn is_retry_safe(&self, transaction_id: &str, payload_hash: &str) -> Result<bool, String> {
218
+ let records = self
219
+ .records
220
+ .read()
221
+ .map_err(|_| "store lock poisoned".to_string())?;
222
+
223
+ let record = records.get(transaction_id);
224
+
225
+ match record {
226
+ None => Ok(true), // Unknown transaction - safe to retry
227
+ Some(r) => {
228
+ // Same payload = safe to retry
229
+ if r.payload_hash == payload_hash {
230
+ Ok(r.status == TransactionStatus::Committed || r.status == TransactionStatus::Unknown)
231
+ } else {
232
+ // Different payload = conflict
233
+ Ok(false)
234
+ }
235
+ }
236
+ }
237
+ }
238
+
239
+ /// Clears old transaction records (for cleanup).
240
+ pub fn cleanup_before(&self, cutoff_time: u64) -> Result<usize, String> {
241
+ let mut records = self
242
+ .records
243
+ .write()
244
+ .map_err(|_| "store lock poisoned".to_string())?;
245
+
246
+ let before_len = records.len();
247
+ records.retain(|_, r| r.recorded_at >= cutoff_time);
248
+ let after_len = records.len();
249
+
250
+ Ok(before_len - after_len)
251
+ }
252
+ }
253
+
254
+ impl Default for TransactionRecoveryStore {
255
+ fn default() -> Self {
256
+ Self::new()
257
+ }
258
+ }
259
+
260
+ /// Computes payload hash for transaction idempotency.
261
+ pub fn compute_payload_hash(payload: &[u8]) -> String {
262
+ let mut hasher = Sha256::new();
263
+ hasher.update(payload);
264
+ format!("{:x}", hasher.finalize())
265
+ }
266
+
267
+ fn now() -> u64 {
268
+ SystemTime::now()
269
+ .duration_since(UNIX_EPOCH)
270
+ .unwrap_or_default()
271
+ .as_secs()
272
+ }
273
+
274
+ #[cfg(test)]
275
+ mod tests {
276
+ use super::*;
277
+
278
+ fn test_payload_hash() -> String {
279
+ compute_payload_hash(b"test payload")
280
+ }
281
+
282
+ #[test]
283
+ fn record_and_retrieve_committed_transaction() {
284
+ let store = TransactionRecoveryStore::new();
285
+
286
+ store
287
+ .record_committed("txn_123".into(), test_payload_hash(), 42)
288
+ .expect("record failed");
289
+
290
+ let status = store.get_status("txn_123").expect("get failed");
291
+ assert_eq!(status.status, TransactionStatus::Committed);
292
+ assert_eq!(status.state_version, 42);
293
+ }
294
+
295
+ #[test]
296
+ fn unknown_transaction_not_found() {
297
+ let store = TransactionRecoveryStore::new();
298
+
299
+ let result = store.get_status("txn_unknown");
300
+ assert!(result.is_err());
301
+ }
302
+
303
+ #[test]
304
+ fn same_payload_is_safe_to_retry() {
305
+ let store = TransactionRecoveryStore::new();
306
+ let hash = test_payload_hash();
307
+
308
+ store
309
+ .record_committed("txn_123".into(), hash.clone(), 42)
310
+ .expect("record failed");
311
+
312
+ let is_safe = store.is_retry_safe("txn_123", &hash).expect("check failed");
313
+ assert!(is_safe);
314
+ }
315
+
316
+ #[test]
317
+ fn different_payload_is_conflict() {
318
+ let store = TransactionRecoveryStore::new();
319
+ let hash1 = test_payload_hash();
320
+ let hash2 = compute_payload_hash(b"different payload");
321
+
322
+ store
323
+ .record_committed("txn_123".into(), hash1, 42)
324
+ .expect("record failed");
325
+
326
+ let is_safe = store.is_retry_safe("txn_123", &hash2).expect("check failed");
327
+ assert!(!is_safe);
328
+ }
329
+
330
+ #[test]
331
+ fn unknown_transaction_is_safe_to_retry() {
332
+ let store = TransactionRecoveryStore::new();
333
+ let hash = test_payload_hash();
334
+
335
+ let is_safe = store.is_retry_safe("txn_unknown", &hash).expect("check failed");
336
+ assert!(is_safe);
337
+ }
338
+
339
+ #[test]
340
+ fn rejected_transaction_with_same_payload_is_not_safe() {
341
+ let store = TransactionRecoveryStore::new();
342
+ let hash = test_payload_hash();
343
+
344
+ store
345
+ .record_rejected("txn_123".into(), hash.clone(), "validation error".into())
346
+ .expect("record failed");
347
+
348
+ let is_safe = store.is_retry_safe("txn_123", &hash).expect("check failed");
349
+ assert!(!is_safe);
350
+ }
351
+
352
+ #[test]
353
+ fn conflicted_transaction_with_same_payload_is_not_safe() {
354
+ let store = TransactionRecoveryStore::new();
355
+ let hash = test_payload_hash();
356
+
357
+ store
358
+ .record_conflicted("txn_123".into(), hash.clone(), "version mismatch".into())
359
+ .expect("record failed");
360
+
361
+ let is_safe = store.is_retry_safe("txn_123", &hash).expect("check failed");
362
+ assert!(!is_safe);
363
+ }
364
+
365
+ #[test]
366
+ fn record_unknown_transaction() {
367
+ let store = TransactionRecoveryStore::new();
368
+ let hash = test_payload_hash();
369
+
370
+ store
371
+ .record_unknown("txn_123".into(), hash)
372
+ .expect("record failed");
373
+
374
+ let status = store.get_status("txn_123").expect("get failed");
375
+ assert_eq!(status.status, TransactionStatus::Unknown);
376
+ }
377
+
378
+ #[test]
379
+ fn record_rejected_transaction() {
380
+ let store = TransactionRecoveryStore::new();
381
+ let hash = test_payload_hash();
382
+
383
+ store
384
+ .record_rejected(
385
+ "txn_123".into(),
386
+ hash,
387
+ "required field missing".into(),
388
+ )
389
+ .expect("record failed");
390
+
391
+ let status = store.get_status("txn_123").expect("get failed");
392
+ assert_eq!(status.status, TransactionStatus::Rejected);
393
+ assert!(status.error.is_some());
394
+ }
395
+
396
+ #[test]
397
+ fn record_conflicted_transaction() {
398
+ let store = TransactionRecoveryStore::new();
399
+ let hash = test_payload_hash();
400
+
401
+ store
402
+ .record_conflicted("txn_123".into(), hash, "concurrent write".into())
403
+ .expect("record failed");
404
+
405
+ let status = store.get_status("txn_123").expect("get failed");
406
+ assert_eq!(status.status, TransactionStatus::Conflicted);
407
+ }
408
+
409
+ #[test]
410
+ fn cleanup_removes_old_records() {
411
+ let store = TransactionRecoveryStore::new();
412
+ let hash = test_payload_hash();
413
+ let old_time = now() - 86400; // 1 day ago
414
+
415
+ store
416
+ .record_committed("txn_old".into(), hash.clone(), 1)
417
+ .expect("record failed");
418
+
419
+ // Manually insert an old record (normally would be done by recovery mechanism)
420
+ {
421
+ let mut records = store.records.write().unwrap();
422
+ if let Some(r) = records.get_mut("txn_old") {
423
+ r.recorded_at = old_time;
424
+ }
425
+ }
426
+
427
+ let cutoff = now() - 3600; // 1 hour ago
428
+ let deleted = store.cleanup_before(cutoff).expect("cleanup failed");
429
+ assert_eq!(deleted, 1);
430
+
431
+ // Old record should be gone
432
+ assert!(store.get_status("txn_old").is_err());
433
+ }
434
+
435
+ #[test]
436
+ fn payload_hash_is_deterministic() {
437
+ let hash1 = compute_payload_hash(b"test payload");
438
+ let hash2 = compute_payload_hash(b"test payload");
439
+ assert_eq!(hash1, hash2);
440
+
441
+ let hash3 = compute_payload_hash(b"different");
442
+ assert_ne!(hash1, hash3);
443
+ }
444
+
445
+ #[test]
446
+ fn transaction_record_includes_timestamps() {
447
+ let store = TransactionRecoveryStore::new();
448
+ let hash = test_payload_hash();
449
+
450
+ let before = now();
451
+ store
452
+ .record_committed("txn_123".into(), hash, 42)
453
+ .expect("record failed");
454
+ let after = now();
455
+
456
+ let status = store.get_status("txn_123").expect("get failed");
457
+ assert!(status.committed_at.is_some());
458
+ let committed = status.committed_at.unwrap();
459
+ assert!(committed >= before && committed <= after + 1);
460
+ }
461
+ }
@@ -0,0 +1,58 @@
1
+ # FeltDB Development Workspace
2
+
3
+ This directory contains the development workspace configuration for your FeltDB project.
4
+
5
+ ## workspace.json
6
+
7
+ **Purpose:** Durable pairing identity for your project's development workspace.
8
+
9
+ **Contents:**
10
+ - `workspaceId` — Unique identifier for this workspace (format: `ws_*`)
11
+ - `projectId` — Your project name
12
+ - `version` — Configuration version
13
+
14
+ **Usage:**
15
+ - Committed to version control (this is your project's identity)
16
+ - Used by CLI, IDE, agents, and browser extensions to discover the workspace
17
+ - DO NOT edit manually unless you know what you're doing
18
+
19
+ **Discovery:**
20
+ When any FeltDB tool (VS Code, Claude agent, CLI, browser extension) opens your project, it reads this file to automatically connect to the correct workspace.
21
+
22
+ ## Runtime Files (not committed)
23
+
24
+ - `pairing.json` — Short-lived pairing token for browser discovery (gitignored)
25
+ - `state.json` — Local workspace state (gitignored)
26
+ - `*.log` — Development logs (gitignored)
27
+
28
+ ## Commands
29
+
30
+ ```bash
31
+ # Check workspace status
32
+ npm run feltdb:status
33
+
34
+ # Or use the CLI directly
35
+ feltdb workspace status
36
+
37
+ # Launch development environment (includes workspace authority)
38
+ npm run dev
39
+ ```
40
+
41
+ ## Development Workspace Architecture
42
+
43
+ ```
44
+ Your Project
45
+
46
+ .feltdb/workspace.json (pairing identity)
47
+
48
+ feltdb dev (workspace authority)
49
+
50
+ Browser, IDE, Agent clients
51
+ ```
52
+
53
+ All tools automatically discover your workspace using `workspace.json` and connect to the local development environment started by `npm run dev`.
54
+
55
+ ## Learn More
56
+
57
+ - [Development Workspaces Documentation](https://github.com/rkendel1/feltdb/blob/main/packages/core/docs/development-workspaces.md)
58
+ - [FeltDB Documentation](https://github.com/rkendel1/feltdb)
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Workspace Initialization
3
+ *
4
+ * Initializes a FeltDB Development Workspace for newly created projects.
5
+ * This is the bootstrap mechanism that enables all FeltDB-aware tools
6
+ * to discover and connect to the same workspace.
7
+ */
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ /**
11
+ * Generate a unique workspace ID
12
+ * Format: ws_<projectId>_<timestamp>_<random>
13
+ */
14
+ export function generateWorkspaceId(projectId) {
15
+ const timestamp = Date.now();
16
+ const random = Math.random().toString(36).substring(2, 9);
17
+ return `ws_${projectId}_${timestamp}_${random}`;
18
+ }
19
+ /**
20
+ * Initialize development workspace for a new project
21
+ *
22
+ * Creates .feltdb/workspace.json with the workspace discovery information.
23
+ * This file is committed to the repository and used by all development tools
24
+ * (CLI, IDE, agents, browser extensions) to discover and connect to the
25
+ * same workspace.
26
+ */
27
+ export function initializeWorkspace(projectDir, projectId) {
28
+ const feltdbDir = path.join(projectDir, '.feltdb');
29
+ // Ensure .feltdb directory exists
30
+ if (!fs.existsSync(feltdbDir)) {
31
+ fs.mkdirSync(feltdbDir, { recursive: true });
32
+ }
33
+ // Create workspace discovery
34
+ const workspaceId = generateWorkspaceId(projectId);
35
+ const discovery = {
36
+ workspaceId,
37
+ projectId,
38
+ version: 1,
39
+ };
40
+ // Write workspace.json
41
+ const workspacePath = path.join(feltdbDir, 'workspace.json');
42
+ fs.writeFileSync(workspacePath, JSON.stringify(discovery, null, 2) + '\n');
43
+ return discovery;
44
+ }
45
+ /**
46
+ * Create .gitignore entry for workspace runtime files
47
+ *
48
+ * The .feltdb/workspace.json is committed (pairing identity).
49
+ * But runtime files like pairing tokens should not be committed.
50
+ */
51
+ export function appendWorkspaceGitignore(projectDir) {
52
+ const gitignorePath = path.join(projectDir, '.gitignore');
53
+ const workspaceGitignoreEntries = [
54
+ '',
55
+ '# FeltDB Development Workspace',
56
+ '.feltdb/pairing.json',
57
+ '.feltdb/state.json',
58
+ '.feltdb/*.log',
59
+ '',
60
+ ].join('\n');
61
+ if (fs.existsSync(gitignorePath)) {
62
+ const existing = fs.readFileSync(gitignorePath, 'utf-8');
63
+ if (!existing.includes('.feltdb/pairing.json')) {
64
+ fs.appendFileSync(gitignorePath, workspaceGitignoreEntries);
65
+ }
66
+ }
67
+ else {
68
+ const content = [
69
+ 'node_modules/',
70
+ 'dist/',
71
+ 'build/',
72
+ '.env.local',
73
+ workspaceGitignoreEntries,
74
+ ].join('\n');
75
+ fs.writeFileSync(gitignorePath, content);
76
+ }
77
+ }
package/dist/index.d.ts CHANGED
@@ -65,4 +65,10 @@ export type { TelemetryEvent, TelemetryEventType } from './telemetry.js';
65
65
  * Observability and inspection APIs
66
66
  */
67
67
  export type { ProvenanceGraph, ProvenanceNode, ProvenanceEdge, ProvenanceEdgeType, RuntimeDiagnostics, } from './db.js';
68
+ /**
69
+ * Development Workspace APIs
70
+ *
71
+ * Shared development state for coordinating Browser, IDE, and Agent clients.
72
+ */
73
+ export * from './workspace/index.js';
68
74
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EACL,eAAe,EACf,KAAK,OAAO,EACZ,KAAK,SAAS,IAAI,iBAAiB,EACnC,KAAK,QAAQ,IAAI,gBAAgB,GAClC,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AAEnC;;GAEG;AACH,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACnE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzE;;GAEG;AACH,YAAY,EACV,eAAe,EACf,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EACL,eAAe,EACf,KAAK,OAAO,EACZ,KAAK,SAAS,IAAI,iBAAiB,EACnC,KAAK,QAAQ,IAAI,gBAAgB,GAClC,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AAEnC;;GAEG;AACH,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACnE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzE;;GAEG;AACH,YAAY,EACV,eAAe,EACf,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,cAAc,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -60,3 +60,9 @@ export * from './agent-runtime.js';
60
60
  * Telemetry APIs
61
61
  */
62
62
  export { emitTelemetry, getTelemetryClient } from './telemetry.js';
63
+ /**
64
+ * Development Workspace APIs
65
+ *
66
+ * Shared development state for coordinating Browser, IDE, and Agent clients.
67
+ */
68
+ export * from './workspace/index.js';