@snapback/cli 1.1.15 → 3.0.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 +50 -12
- package/dist/{auth-HFJRXXG2.js → auth-TDIHGKKL.js} +8 -8
- package/dist/{auto-provision-organization-SF6XM7X4.js → auto-provision-organization-CXHL46P3.js} +4 -4
- package/dist/{chunk-23G5VYA3.js → chunk-CPZWXRP2.js} +196 -23
- package/dist/{chunk-OI2HNNT6.js → chunk-E6V6QKS7.js} +34 -2
- package/dist/{chunk-XYU5FFE3.js → chunk-FMWCFAY7.js} +1 -1
- package/dist/{chunk-HR34NJP7.js → chunk-LIBBDBW5.js} +4 -1
- package/dist/{chunk-DNEADD2G.js → chunk-O7HMAZ7L.js} +10 -12
- package/dist/{chunk-ICKSHS3A.js → chunk-Q4VC7GND.js} +39 -3
- package/dist/{client-WIO6W447.js → client-62E3L6DW.js} +1 -1
- package/dist/{dist-TEWNOZYS.js → dist-5LR7APG5.js} +1 -1
- package/dist/{dist-E7E2T3DQ.js → dist-NFU5UJEW.js} +1 -1
- package/dist/dist-OO5LJHL6.js +12 -0
- package/dist/index.js +492 -321
- package/dist/{local-service-adapter-3JHN6G4O.js → local-service-adapter-AB3UYRUK.js} +1 -1
- package/package.json +3 -3
- package/dist/dist-YZBJAYEJ.js +0 -12
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/@snapback/cli)
|
|
7
7
|
[](https://github.com/snapback-dev/snapback-cli/blob/main/LICENSE)
|
|
8
8
|
|
|
9
|
-
AI coding
|
|
9
|
+
AI coding agents—Cursor, Claude Code, GitHub Copilot, Windsurf—are incredible until they're not. One hallucinated change cascades into hours of debugging. Git doesn't help because you haven't committed yet. And the faster you vibe-code, the faster mistakes compound.
|
|
10
10
|
|
|
11
11
|
**SnapBack makes your codebase smarter every session.** Day 1: Detection. Day 30: Patterns. Day 90: Prediction.
|
|
12
12
|
|
|
@@ -261,14 +261,33 @@ snap tools repair
|
|
|
261
261
|
|
|
262
262
|
### Available MCP Tools
|
|
263
263
|
|
|
264
|
-
Once configured, your AI assistant
|
|
264
|
+
Once configured, your AI assistant uses the **V2 4-tool surface** — a session-oriented API designed for agentic coding loops:
|
|
265
265
|
|
|
266
|
-
| Tool |
|
|
267
|
-
|
|
268
|
-
| `
|
|
269
|
-
| `
|
|
270
|
-
| `
|
|
271
|
-
| `
|
|
266
|
+
| Tool | When to call | What it returns |
|
|
267
|
+
|------|-------------|----------------|
|
|
268
|
+
| `snap_begin` | Start of every task | Intelligence briefing: past learnings, active warnings, session lineage |
|
|
269
|
+
| `snap_pulse` | Mid-session check | Read-only vitals: pulse level, risk pressure, trajectory |
|
|
270
|
+
| `snap_learn` | Any discovery | Captures a pattern, gotcha, or decision for future sessions |
|
|
271
|
+
| `snap_end` | Task complete | Ceremony: outcome recorded, carry-forward context for next session |
|
|
272
|
+
|
|
273
|
+
**The agentic workflow** (runs automatically in your AI assistant):
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
snap_begin({ task: "refactor auth module" })
|
|
277
|
+
→ briefing with learnings, warnings, risk context
|
|
278
|
+
|
|
279
|
+
[... agent works ...]
|
|
280
|
+
|
|
281
|
+
snap_pulse() // optional mid-session check
|
|
282
|
+
→ pulse: elevated, pressure: 42%, trajectory: stable
|
|
283
|
+
|
|
284
|
+
snap_learn({ insight: "always snapshot before token refresh logic" })
|
|
285
|
+
|
|
286
|
+
snap_end({ outcome: "completed", summary: "..." })
|
|
287
|
+
→ ceremony: files changed, patterns captured, context for next session
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
The full surface (check, advise, safe_to_write, refactoring intelligence, learning intelligence) is also available for advanced workflows — see [MCP documentation →](https://docs.snapback.dev/mcp).
|
|
272
291
|
|
|
273
292
|
---
|
|
274
293
|
|
|
@@ -331,10 +350,13 @@ Once configured, your AI assistant can use:
|
|
|
331
350
|
|
|
332
351
|
| Command | Description |
|
|
333
352
|
|---------|-------------|
|
|
334
|
-
| `snap context [task]` |
|
|
353
|
+
| `snap context [task]` | Pre-task briefing: relevant patterns, warnings, risk context (CLI equivalent of `snap_begin`) |
|
|
335
354
|
| `snap validate <file>` | Run 7-layer validation pipeline |
|
|
336
355
|
| `snap validate --all` | Validate all staged files |
|
|
337
356
|
| `snap stats` | Show learning statistics |
|
|
357
|
+
| `snap metrics [file]` | File momentum scores — which files are highest-churn / highest-risk |
|
|
358
|
+
| `snap sync` | Collect signals and fit momentum scoring normalizers |
|
|
359
|
+
| `snap refresh [--since]` | Incremental signal update |
|
|
338
360
|
|
|
339
361
|
### Learning Commands
|
|
340
362
|
|
|
@@ -374,14 +396,30 @@ Once configured, your AI assistant can use:
|
|
|
374
396
|
| `snap tools validate` | Validate MCP configurations |
|
|
375
397
|
| `snap tools repair` | Repair broken MCP configurations |
|
|
376
398
|
|
|
377
|
-
### Daemon Commands
|
|
399
|
+
### Daemon & Service Commands
|
|
378
400
|
|
|
379
401
|
| Command | Description |
|
|
380
402
|
|---------|-------------|
|
|
381
|
-
| `snap daemon start` | Start SnapBack daemon |
|
|
403
|
+
| `snap daemon start [--detach]` | Start SnapBack daemon (CLI↔Extension coordination) |
|
|
382
404
|
| `snap daemon stop` | Stop SnapBack daemon |
|
|
383
405
|
| `snap daemon status` | Check daemon status |
|
|
384
406
|
| `snap daemon restart` | Restart daemon |
|
|
407
|
+
| `snap daemon ping` | Verify daemon is responsive |
|
|
408
|
+
| `snap service start [--daemon]` | Start local service (shared state for multi-client) |
|
|
409
|
+
| `snap service stop` | Stop local service |
|
|
410
|
+
| `snap service status` | Check service status |
|
|
411
|
+
| `snap service logs [--follow]` | Stream service logs |
|
|
412
|
+
| `snap service install` | Register as system service |
|
|
413
|
+
| `snap service uninstall` | Unregister system service |
|
|
414
|
+
|
|
415
|
+
### Workspace Baseline Commands
|
|
416
|
+
|
|
417
|
+
| Command | Description |
|
|
418
|
+
|---------|-------------|
|
|
419
|
+
| `snap baseline scan` | Scan workspace and build intelligence baseline |
|
|
420
|
+
| `snap baseline status` | Show baseline freshness and coverage |
|
|
421
|
+
| `snap baseline show` | Display current baseline data |
|
|
422
|
+
| `snap baseline invalidate` | Force baseline rebuild on next scan |
|
|
385
423
|
|
|
386
424
|
### Utility Commands
|
|
387
425
|
|
|
@@ -390,7 +428,7 @@ Once configured, your AI assistant can use:
|
|
|
390
428
|
| `snap wizard` | Interactive first-run setup |
|
|
391
429
|
| `snap doctor` | Diagnostics and health check |
|
|
392
430
|
| `snap doctor --fix` | Auto-fix detected issues |
|
|
393
|
-
| `snap upgrade` |
|
|
431
|
+
| `snap upgrade [--check|--canary]` | Update CLI or check for new version |
|
|
394
432
|
| `snap config list` | List configuration values |
|
|
395
433
|
| `snap config get <key>` | Get a specific config value |
|
|
396
434
|
| `snap config set <key> <value>` | Set a configuration value |
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node --no-warnings=ExperimentalWarning
|
|
2
|
-
import { config, EntitlementsServiceImpl, getBaseUrl, ENABLE_ENHANCED_2FA, ENABLE_SSO, ENABLE_CAPTCHA, ENABLE_MULTI_SESSION, getOrganizationWithPurchasesAndMembersCount, getPendingInvitationByEmail } from './chunk-
|
|
2
|
+
import { config, EntitlementsServiceImpl, getBaseUrl, ENABLE_ENHANCED_2FA, ENABLE_SSO, ENABLE_CAPTCHA, ENABLE_MULTI_SESSION, getOrganizationWithPurchasesAndMembersCount, getPendingInvitationByEmail } from './chunk-CPZWXRP2.js';
|
|
3
3
|
import './chunk-GQ73B37K.js';
|
|
4
|
-
import { combinedSchema, db } from './chunk-
|
|
5
|
-
import { trackEvent } from './chunk-
|
|
6
|
-
import './chunk-
|
|
4
|
+
import { combinedSchema, db } from './chunk-LIBBDBW5.js';
|
|
5
|
+
import { trackEvent } from './chunk-FMWCFAY7.js';
|
|
6
|
+
import './chunk-Q4VC7GND.js';
|
|
7
7
|
import { logger } from './chunk-PL4HF4M2.js';
|
|
8
8
|
import { createLogger, LogLevel } from './chunk-WS36HDEU.js';
|
|
9
9
|
import './chunk-5EOPYJ4Y.js';
|
|
@@ -1043,7 +1043,7 @@ var _auth = betterAuth({
|
|
|
1043
1043
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1044
1044
|
});
|
|
1045
1045
|
try {
|
|
1046
|
-
const { db: db2 } = await import('./dist-
|
|
1046
|
+
const { db: db2 } = await import('./dist-OO5LJHL6.js');
|
|
1047
1047
|
const { sql } = await import('drizzle-orm');
|
|
1048
1048
|
if (db2) {
|
|
1049
1049
|
const result = await db2.execute(sql`
|
|
@@ -1073,7 +1073,7 @@ var _auth = betterAuth({
|
|
|
1073
1073
|
}
|
|
1074
1074
|
try {
|
|
1075
1075
|
if (!session.activeOrganizationId) {
|
|
1076
|
-
const { db: db2, combinedSchema: combinedSchema2 } = await import('./dist-
|
|
1076
|
+
const { db: db2, combinedSchema: combinedSchema2 } = await import('./dist-OO5LJHL6.js');
|
|
1077
1077
|
const { sql } = await import('drizzle-orm');
|
|
1078
1078
|
if (db2) {
|
|
1079
1079
|
const { member: member2, session: sessionTable } = combinedSchema2;
|
|
@@ -1130,7 +1130,7 @@ var _auth = betterAuth({
|
|
|
1130
1130
|
});
|
|
1131
1131
|
}
|
|
1132
1132
|
try {
|
|
1133
|
-
const { autoProvisionOrganization } = await import('./auto-provision-organization-
|
|
1133
|
+
const { autoProvisionOrganization } = await import('./auto-provision-organization-CXHL46P3.js');
|
|
1134
1134
|
const result = await autoProvisionOrganization(user2);
|
|
1135
1135
|
if (!result.success) {
|
|
1136
1136
|
logger.warn("Auto-org provisioning failed", {
|
|
@@ -1424,7 +1424,7 @@ This invitation expires in ${expiresInDays} days.`,
|
|
|
1424
1424
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1425
1425
|
}).catch(() => {
|
|
1426
1426
|
});
|
|
1427
|
-
import('./dist-
|
|
1427
|
+
import('./dist-NFU5UJEW.js').then(({ captureError }) => {
|
|
1428
1428
|
if (captureError && error instanceof Error) {
|
|
1429
1429
|
captureError(error, {
|
|
1430
1430
|
tags: {
|
package/dist/{auto-provision-organization-SF6XM7X4.js → auto-provision-organization-CXHL46P3.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node --no-warnings=ExperimentalWarning
|
|
2
|
-
import { trackEvent } from './chunk-
|
|
3
|
-
import './chunk-
|
|
2
|
+
import { trackEvent } from './chunk-FMWCFAY7.js';
|
|
3
|
+
import './chunk-Q4VC7GND.js';
|
|
4
4
|
import { logger } from './chunk-PL4HF4M2.js';
|
|
5
5
|
import './chunk-WS36HDEU.js';
|
|
6
6
|
import './chunk-5EOPYJ4Y.js';
|
|
@@ -56,7 +56,7 @@ __name(getDisplayName, "getDisplayName");
|
|
|
56
56
|
async function autoProvisionOrganization(user) {
|
|
57
57
|
const startTime = Date.now();
|
|
58
58
|
try {
|
|
59
|
-
const { db, combinedSchema } = await import('./dist-
|
|
59
|
+
const { db, combinedSchema } = await import('./dist-OO5LJHL6.js');
|
|
60
60
|
const { sql } = await import('drizzle-orm');
|
|
61
61
|
if (!db) {
|
|
62
62
|
logger.error("Database not available for auto-provisioning", {
|
|
@@ -138,7 +138,7 @@ async function autoProvisionOrganization(user) {
|
|
|
138
138
|
__name(autoProvisionOrganization, "autoProvisionOrganization");
|
|
139
139
|
async function userHasOrganization(userId) {
|
|
140
140
|
try {
|
|
141
|
-
const { db, combinedSchema } = await import('./dist-
|
|
141
|
+
const { db, combinedSchema } = await import('./dist-OO5LJHL6.js');
|
|
142
142
|
const { sql } = await import('drizzle-orm');
|
|
143
143
|
if (!db) {
|
|
144
144
|
return false;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node --no-warnings=ExperimentalWarning
|
|
2
2
|
import { isRedisAvailable, getCache, setCache, deleteCache } from './chunk-GQ73B37K.js';
|
|
3
|
-
import { snapshots, snapshotFiles, agentSuggestions, quarantineEvents, postAcceptOutcomes, policyEvaluations, loops, feedback, combinedSchema, user, aiChat, organization, member, invitation, purchase, session, account, verification, passkey, db, userAttributions, subscriptions, trials, pioneers, usageLimits, creditsLedger, mcpObservations, mcpToolInvocations, extensionSyncState, pioneerActions, sagas, apiKeys, TIER_STALENESS_THRESHOLD_MS, WORKSPACE_LINK_TTL_MS, patterns, closeDatabaseConnection, checkDatabaseConnection } from './chunk-
|
|
3
|
+
import { snapshots, snapshotFiles, agentSuggestions, quarantineEvents, postAcceptOutcomes, policyEvaluations, loops, feedback, telemetryEvents, telemetryIdempotencyKeys, combinedSchema, user, aiChat, organization, member, invitation, purchase, session, account, verification, passkey, db, userAttributions, subscriptions, trials, pioneers, usageLimits, creditsLedger, mcpObservations, mcpToolInvocations, extensionSyncState, pioneerActions, sagas, apiKeys, TIER_STALENESS_THRESHOLD_MS, WORKSPACE_LINK_TTL_MS, patterns, closeDatabaseConnection, checkDatabaseConnection } from './chunk-LIBBDBW5.js';
|
|
4
4
|
import { logger } from './chunk-PL4HF4M2.js';
|
|
5
5
|
import { shouldMergeAttribution, createLogger, LogLevel, isFeatureAvailableAtTier, getTierFeatures, getTierLimit, EventBus, generateIdempotencyKey, getActionPoints, calculatePioneerTier, PIONEER_TIER_THRESHOLDS, isFirstTimeAction, TIER_UPGRADE_SAGA } from './chunk-WS36HDEU.js';
|
|
6
6
|
import { __name } from './chunk-7ADPL4Q3.js';
|
|
@@ -521,6 +521,179 @@ var TelemetrySinkDb = class {
|
|
|
521
521
|
}
|
|
522
522
|
}
|
|
523
523
|
};
|
|
524
|
+
var TelemetrySinkDbAdapter = class {
|
|
525
|
+
static {
|
|
526
|
+
__name(this, "TelemetrySinkDbAdapter");
|
|
527
|
+
}
|
|
528
|
+
db;
|
|
529
|
+
constructor(db2) {
|
|
530
|
+
this.db = db2;
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Store telemetry events with idempotency check
|
|
534
|
+
*/
|
|
535
|
+
async storeEvents(events) {
|
|
536
|
+
if (events.length === 0) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
try {
|
|
540
|
+
const values = events.map((event) => ({
|
|
541
|
+
id: event.id,
|
|
542
|
+
userId: this.extractUserId(event),
|
|
543
|
+
apiKeyId: this.extractApiKeyId(event),
|
|
544
|
+
eventType: event.eventType,
|
|
545
|
+
eventCategory: this.categorizeEvent(event),
|
|
546
|
+
properties: this.redactProperties(event.payload),
|
|
547
|
+
sessionId: event.context?.sessionId,
|
|
548
|
+
platform: event.context?.client,
|
|
549
|
+
timestamp: new Date(event.timestamp),
|
|
550
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
551
|
+
}));
|
|
552
|
+
await this.db.insert(telemetryEvents).values(values);
|
|
553
|
+
} catch (error) {
|
|
554
|
+
console.error("Failed to store telemetry events", {
|
|
555
|
+
count: events.length,
|
|
556
|
+
error: error instanceof Error ? error.message : String(error)
|
|
557
|
+
});
|
|
558
|
+
throw error;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Retrieve telemetry events with optional filtering
|
|
563
|
+
*/
|
|
564
|
+
async getEvents(filter) {
|
|
565
|
+
try {
|
|
566
|
+
const results = await this.db.select().from(telemetryEvents);
|
|
567
|
+
let events = results.map((row) => this.toTelemetryEvent(row));
|
|
568
|
+
if (filter?.eventType) {
|
|
569
|
+
events = events.filter((e) => e.eventType === filter.eventType);
|
|
570
|
+
}
|
|
571
|
+
if (filter?.sessionId) {
|
|
572
|
+
events = events.filter((e) => e.context?.sessionId === filter.sessionId);
|
|
573
|
+
}
|
|
574
|
+
if (filter?.startTime !== void 0) {
|
|
575
|
+
events = events.filter((e) => e.timestamp >= filter.startTime);
|
|
576
|
+
}
|
|
577
|
+
if (filter?.endTime !== void 0) {
|
|
578
|
+
events = events.filter((e) => e.timestamp <= filter.endTime);
|
|
579
|
+
}
|
|
580
|
+
return events;
|
|
581
|
+
} catch (error) {
|
|
582
|
+
console.error("Failed to retrieve telemetry events", {
|
|
583
|
+
error: error instanceof Error ? error.message : String(error)
|
|
584
|
+
});
|
|
585
|
+
throw error;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Check if a request ID has been processed (idempotency)
|
|
590
|
+
*/
|
|
591
|
+
async hasRequestId(requestId) {
|
|
592
|
+
try {
|
|
593
|
+
const result = await this.db.select().from(telemetryIdempotencyKeys).where(eq(telemetryIdempotencyKeys.idempotencyKey, requestId)).limit(1);
|
|
594
|
+
return result.length > 0;
|
|
595
|
+
} catch (error) {
|
|
596
|
+
console.error("Failed to check idempotency key", {
|
|
597
|
+
requestId,
|
|
598
|
+
error: error instanceof Error ? error.message : String(error)
|
|
599
|
+
});
|
|
600
|
+
throw error;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Record a request ID as processed (idempotency)
|
|
605
|
+
* Caches response data for duplicate request handling (2026 best practice)
|
|
606
|
+
*/
|
|
607
|
+
async recordRequestId(requestId, responseData = {}) {
|
|
608
|
+
try {
|
|
609
|
+
const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1e3);
|
|
610
|
+
await this.db.insert(telemetryIdempotencyKeys).values({
|
|
611
|
+
idempotencyKey: requestId,
|
|
612
|
+
responseData,
|
|
613
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
614
|
+
expiresAt
|
|
615
|
+
});
|
|
616
|
+
} catch (error) {
|
|
617
|
+
console.error("Failed to record idempotency key", {
|
|
618
|
+
requestId,
|
|
619
|
+
error: error instanceof Error ? error.message : String(error)
|
|
620
|
+
});
|
|
621
|
+
throw error;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Extract user ID from event context or payload
|
|
626
|
+
*/
|
|
627
|
+
extractUserId(event) {
|
|
628
|
+
return event.payload.userId || event.payload.user_id || null;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Extract API key ID from event context or payload
|
|
632
|
+
*/
|
|
633
|
+
extractApiKeyId(event) {
|
|
634
|
+
return event.payload.apiKeyId || event.payload.api_key_id || null;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Categorize event based on eventType
|
|
638
|
+
* Maps to eventCategory enum in schema
|
|
639
|
+
*/
|
|
640
|
+
categorizeEvent(event) {
|
|
641
|
+
const type = event.eventType.toLowerCase();
|
|
642
|
+
if (type.includes("error")) return "error";
|
|
643
|
+
if (type.includes("feature") || type.includes("usage")) return "feature_usage";
|
|
644
|
+
if (type.includes("lifecycle") || type.includes("session")) return "lifecycle";
|
|
645
|
+
if (type.includes("engagement") || type.includes("interaction")) return "engagement";
|
|
646
|
+
return "system";
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Redact sensitive properties before storage (GDPR compliance 2026)
|
|
650
|
+
* Prevents PII leakage through telemetry data
|
|
651
|
+
*/
|
|
652
|
+
redactProperties(properties) {
|
|
653
|
+
const sensitiveFields = [
|
|
654
|
+
"email",
|
|
655
|
+
"password",
|
|
656
|
+
"token",
|
|
657
|
+
"apiKey",
|
|
658
|
+
"api_key",
|
|
659
|
+
"secret",
|
|
660
|
+
"accessToken",
|
|
661
|
+
"access_token",
|
|
662
|
+
"refreshToken",
|
|
663
|
+
"refresh_token",
|
|
664
|
+
"creditCard",
|
|
665
|
+
"credit_card",
|
|
666
|
+
"ssn",
|
|
667
|
+
"socialSecurity"
|
|
668
|
+
];
|
|
669
|
+
const redacted = {
|
|
670
|
+
...properties
|
|
671
|
+
};
|
|
672
|
+
for (const field of sensitiveFields) {
|
|
673
|
+
if (field in redacted) {
|
|
674
|
+
redacted[field] = "[REDACTED]";
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return redacted;
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Transform database row to TelemetryEvent contract type
|
|
681
|
+
*/
|
|
682
|
+
toTelemetryEvent(row) {
|
|
683
|
+
return {
|
|
684
|
+
id: row.id,
|
|
685
|
+
eventType: row.eventType,
|
|
686
|
+
payload: row.properties || {},
|
|
687
|
+
timestamp: row.timestamp.getTime(),
|
|
688
|
+
context: {
|
|
689
|
+
sessionId: row.sessionId || void 0,
|
|
690
|
+
requestId: row.requestId || `synthetic-${row.id}`,
|
|
691
|
+
workspaceId: row.workspaceId || void 0,
|
|
692
|
+
client: row.platform || "unknown"
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
};
|
|
524
697
|
|
|
525
698
|
// ../../packages/platform/dist/db/database-service.js
|
|
526
699
|
var databaseService = {
|
|
@@ -607,7 +780,7 @@ async function getCapabilities(userId, options = {}) {
|
|
|
607
780
|
throw new Error("Database not available");
|
|
608
781
|
}
|
|
609
782
|
let capabilities = await db.query.userDetectionCapabilities.findFirst({
|
|
610
|
-
where: /* @__PURE__ */ __name((cap, { eq:
|
|
783
|
+
where: /* @__PURE__ */ __name((cap, { eq: eq16 }) => eq16(cap.userId, validatedUserId), "where")
|
|
611
784
|
});
|
|
612
785
|
if (!capabilities) {
|
|
613
786
|
const [created] = await db.insert(userDetectionCapabilities).values({
|
|
@@ -830,7 +1003,7 @@ async function getCapabilityAuditHistory(userId, limit = 50) {
|
|
|
830
1003
|
return [];
|
|
831
1004
|
}
|
|
832
1005
|
return await db.query.capabilityAudit.findMany({
|
|
833
|
-
where: /* @__PURE__ */ __name((audit, { eq:
|
|
1006
|
+
where: /* @__PURE__ */ __name((audit, { eq: eq16 }) => eq16(audit.userId, userId), "where"),
|
|
834
1007
|
orderBy: /* @__PURE__ */ __name((audit, { desc: desc4 }) => desc4(audit.createdAt), "orderBy"),
|
|
835
1008
|
limit
|
|
836
1009
|
});
|
|
@@ -997,7 +1170,7 @@ async function getOrganizationById(id) {
|
|
|
997
1170
|
throw new Error("Database not available");
|
|
998
1171
|
}
|
|
999
1172
|
return await db.query.organization.findFirst({
|
|
1000
|
-
where: /* @__PURE__ */ __name((org, { eq:
|
|
1173
|
+
where: /* @__PURE__ */ __name((org, { eq: eq16 }) => eq16(org.id, id), "where"),
|
|
1001
1174
|
with: {
|
|
1002
1175
|
members: true,
|
|
1003
1176
|
invitations: true
|
|
@@ -1012,7 +1185,7 @@ async function getOrganizationsWithMembers(userId) {
|
|
|
1012
1185
|
return await db.query.organization.findMany({
|
|
1013
1186
|
with: {
|
|
1014
1187
|
members: {
|
|
1015
|
-
where: /* @__PURE__ */ __name((member3, { eq:
|
|
1188
|
+
where: /* @__PURE__ */ __name((member3, { eq: eq16 }) => eq16(member3.userId, userId), "where"),
|
|
1016
1189
|
with: {
|
|
1017
1190
|
user: true
|
|
1018
1191
|
}
|
|
@@ -1026,7 +1199,7 @@ async function getInvitationById(id) {
|
|
|
1026
1199
|
throw new Error("Database not available");
|
|
1027
1200
|
}
|
|
1028
1201
|
return await db.query.invitation.findFirst({
|
|
1029
|
-
where: /* @__PURE__ */ __name((invitation2, { eq:
|
|
1202
|
+
where: /* @__PURE__ */ __name((invitation2, { eq: eq16 }) => eq16(invitation2.id, id), "where"),
|
|
1030
1203
|
with: {
|
|
1031
1204
|
organization: true
|
|
1032
1205
|
}
|
|
@@ -1038,7 +1211,7 @@ async function getOrganizationBySlug(slug) {
|
|
|
1038
1211
|
throw new Error("Database not available");
|
|
1039
1212
|
}
|
|
1040
1213
|
return await db.query.organization.findFirst({
|
|
1041
|
-
where: /* @__PURE__ */ __name((org, { eq:
|
|
1214
|
+
where: /* @__PURE__ */ __name((org, { eq: eq16 }) => eq16(org.slug, slug), "where")
|
|
1042
1215
|
});
|
|
1043
1216
|
}
|
|
1044
1217
|
__name(getOrganizationBySlug, "getOrganizationBySlug");
|
|
@@ -1047,7 +1220,7 @@ async function getOrganizationMembership(organizationId, userId) {
|
|
|
1047
1220
|
throw new Error("Database not available");
|
|
1048
1221
|
}
|
|
1049
1222
|
return await db.query.member.findFirst({
|
|
1050
|
-
where: /* @__PURE__ */ __name((member3, { and: and6, eq:
|
|
1223
|
+
where: /* @__PURE__ */ __name((member3, { and: and6, eq: eq16 }) => and6(eq16(member3.organizationId, organizationId), eq16(member3.userId, userId)), "where"),
|
|
1051
1224
|
with: {
|
|
1052
1225
|
organization: true
|
|
1053
1226
|
}
|
|
@@ -1059,7 +1232,7 @@ async function getOrganizationWithPurchasesAndMembersCount(organizationId) {
|
|
|
1059
1232
|
throw new Error("Database not available");
|
|
1060
1233
|
}
|
|
1061
1234
|
return await db.query.organization.findFirst({
|
|
1062
|
-
where: /* @__PURE__ */ __name((org, { eq:
|
|
1235
|
+
where: /* @__PURE__ */ __name((org, { eq: eq16 }) => eq16(org.id, organizationId), "where"),
|
|
1063
1236
|
with: {
|
|
1064
1237
|
purchases: true
|
|
1065
1238
|
},
|
|
@@ -1074,7 +1247,7 @@ async function getPendingInvitationByEmail(email) {
|
|
|
1074
1247
|
throw new Error("Database not available");
|
|
1075
1248
|
}
|
|
1076
1249
|
return await db.query.invitation.findFirst({
|
|
1077
|
-
where: /* @__PURE__ */ __name((invitation2, { and: and6, eq:
|
|
1250
|
+
where: /* @__PURE__ */ __name((invitation2, { and: and6, eq: eq16 }) => and6(eq16(invitation2.email, email), eq16(invitation2.status, "pending")), "where")
|
|
1078
1251
|
});
|
|
1079
1252
|
}
|
|
1080
1253
|
__name(getPendingInvitationByEmail, "getPendingInvitationByEmail");
|
|
@@ -1335,7 +1508,7 @@ async function getPurchasesByOrganizationId(organizationId) {
|
|
|
1335
1508
|
throw new Error("Database not available");
|
|
1336
1509
|
}
|
|
1337
1510
|
return db.query.purchase.findMany({
|
|
1338
|
-
where: /* @__PURE__ */ __name((purchase3, { eq:
|
|
1511
|
+
where: /* @__PURE__ */ __name((purchase3, { eq: eq16 }) => eq16(purchase3.organizationId, organizationId), "where")
|
|
1339
1512
|
});
|
|
1340
1513
|
}
|
|
1341
1514
|
__name(getPurchasesByOrganizationId, "getPurchasesByOrganizationId");
|
|
@@ -1344,7 +1517,7 @@ async function getPurchasesByUserId(userId) {
|
|
|
1344
1517
|
throw new Error("Database not available");
|
|
1345
1518
|
}
|
|
1346
1519
|
return db.query.purchase.findMany({
|
|
1347
|
-
where: /* @__PURE__ */ __name((purchase3, { eq:
|
|
1520
|
+
where: /* @__PURE__ */ __name((purchase3, { eq: eq16 }) => eq16(purchase3.userId, userId), "where")
|
|
1348
1521
|
});
|
|
1349
1522
|
}
|
|
1350
1523
|
__name(getPurchasesByUserId, "getPurchasesByUserId");
|
|
@@ -1353,7 +1526,7 @@ async function getPurchaseById(id) {
|
|
|
1353
1526
|
throw new Error("Database not available");
|
|
1354
1527
|
}
|
|
1355
1528
|
return db.query.purchase.findFirst({
|
|
1356
|
-
where: /* @__PURE__ */ __name((purchase3, { eq:
|
|
1529
|
+
where: /* @__PURE__ */ __name((purchase3, { eq: eq16 }) => eq16(purchase3.id, id), "where")
|
|
1357
1530
|
});
|
|
1358
1531
|
}
|
|
1359
1532
|
__name(getPurchaseById, "getPurchaseById");
|
|
@@ -1362,7 +1535,7 @@ async function getPurchaseBySubscriptionId(subscriptionId) {
|
|
|
1362
1535
|
throw new Error("Database not available");
|
|
1363
1536
|
}
|
|
1364
1537
|
return db.query.purchase.findFirst({
|
|
1365
|
-
where: /* @__PURE__ */ __name((purchase3, { eq:
|
|
1538
|
+
where: /* @__PURE__ */ __name((purchase3, { eq: eq16 }) => eq16(purchase3.subscriptionId, subscriptionId), "where")
|
|
1366
1539
|
});
|
|
1367
1540
|
}
|
|
1368
1541
|
__name(getPurchaseBySubscriptionId, "getPurchaseBySubscriptionId");
|
|
@@ -1438,7 +1611,7 @@ async function getUserById(id) {
|
|
|
1438
1611
|
throw new Error("Database not available");
|
|
1439
1612
|
}
|
|
1440
1613
|
return await db.query.user.findFirst({
|
|
1441
|
-
where: /* @__PURE__ */ __name((user3, { eq:
|
|
1614
|
+
where: /* @__PURE__ */ __name((user3, { eq: eq16 }) => eq16(user3.id, id), "where")
|
|
1442
1615
|
});
|
|
1443
1616
|
}
|
|
1444
1617
|
__name(getUserById, "getUserById");
|
|
@@ -1447,7 +1620,7 @@ async function getUserByEmail(email) {
|
|
|
1447
1620
|
throw new Error("Database not available");
|
|
1448
1621
|
}
|
|
1449
1622
|
return await db.query.user.findFirst({
|
|
1450
|
-
where: /* @__PURE__ */ __name((user3, { eq:
|
|
1623
|
+
where: /* @__PURE__ */ __name((user3, { eq: eq16 }) => eq16(user3.email, email), "where")
|
|
1451
1624
|
});
|
|
1452
1625
|
}
|
|
1453
1626
|
__name(getUserByEmail, "getUserByEmail");
|
|
@@ -1480,7 +1653,7 @@ async function getAccountById(id) {
|
|
|
1480
1653
|
throw new Error("Database not available");
|
|
1481
1654
|
}
|
|
1482
1655
|
return await db.query.account.findFirst({
|
|
1483
|
-
where: /* @__PURE__ */ __name((account3, { eq:
|
|
1656
|
+
where: /* @__PURE__ */ __name((account3, { eq: eq16 }) => eq16(account3.id, id), "where")
|
|
1484
1657
|
});
|
|
1485
1658
|
}
|
|
1486
1659
|
__name(getAccountById, "getAccountById");
|
|
@@ -1541,7 +1714,7 @@ async function getWorkspaceLinkById(workspaceId) {
|
|
|
1541
1714
|
}
|
|
1542
1715
|
const validatedId = workspaceIdSchema.parse(workspaceId);
|
|
1543
1716
|
return await db.query.workspaceLinks.findFirst({
|
|
1544
|
-
where: /* @__PURE__ */ __name((link, { eq:
|
|
1717
|
+
where: /* @__PURE__ */ __name((link, { eq: eq16 }) => eq16(link.workspaceId, validatedId), "where")
|
|
1545
1718
|
});
|
|
1546
1719
|
}
|
|
1547
1720
|
__name(getWorkspaceLinkById, "getWorkspaceLinkById");
|
|
@@ -1555,7 +1728,7 @@ async function resolveTierByWorkspaceId(workspaceId) {
|
|
|
1555
1728
|
try {
|
|
1556
1729
|
const validatedId = workspaceIdSchema.parse(workspaceId);
|
|
1557
1730
|
const link = await db.query.workspaceLinks.findFirst({
|
|
1558
|
-
where: /* @__PURE__ */ __name((link2, { eq:
|
|
1731
|
+
where: /* @__PURE__ */ __name((link2, { eq: eq16 }) => eq16(link2.workspaceId, validatedId), "where")
|
|
1559
1732
|
});
|
|
1560
1733
|
if (!link) {
|
|
1561
1734
|
return {
|
|
@@ -1681,7 +1854,7 @@ async function getWorkspaceLinksByUserId(userId) {
|
|
|
1681
1854
|
throw new Error("Database not available");
|
|
1682
1855
|
}
|
|
1683
1856
|
return await db.query.workspaceLinks.findMany({
|
|
1684
|
-
where: /* @__PURE__ */ __name((link, { eq:
|
|
1857
|
+
where: /* @__PURE__ */ __name((link, { eq: eq16 }) => eq16(link.userId, userId), "where"),
|
|
1685
1858
|
orderBy: /* @__PURE__ */ __name((link, { desc: desc4 }) => desc4(link.lastSeenAt), "orderBy")
|
|
1686
1859
|
});
|
|
1687
1860
|
}
|
|
@@ -1874,7 +2047,7 @@ var extensionSessions = pgTable("extension_sessions", {
|
|
|
1874
2047
|
// ../../packages/platform/dist/db/test-utils.js
|
|
1875
2048
|
var testInTransaction = /* @__PURE__ */ __name((testName, testFn) => {
|
|
1876
2049
|
return async () => {
|
|
1877
|
-
const module = await import('./client-
|
|
2050
|
+
const module = await import('./client-62E3L6DW.js');
|
|
1878
2051
|
const db2 = module.db;
|
|
1879
2052
|
try {
|
|
1880
2053
|
await testFn(db2);
|
|
@@ -1898,7 +2071,7 @@ var truncateAllTables = /* @__PURE__ */ __name(async () => {
|
|
|
1898
2071
|
console.warn("truncateAllTables is not implemented - tests may have side effects");
|
|
1899
2072
|
}, "truncateAllTables");
|
|
1900
2073
|
var getTestDb = /* @__PURE__ */ __name(async () => {
|
|
1901
|
-
const module = await import('./client-
|
|
2074
|
+
const module = await import('./client-62E3L6DW.js');
|
|
1902
2075
|
return module.db;
|
|
1903
2076
|
}, "getTestDb");
|
|
1904
2077
|
var closeTestDb = /* @__PURE__ */ __name(async () => {
|
|
@@ -4256,4 +4429,4 @@ function createTierUpgradeSagaWithDeps(deps) {
|
|
|
4256
4429
|
}
|
|
4257
4430
|
__name(createTierUpgradeSagaWithDeps, "createTierUpgradeSagaWithDeps");
|
|
4258
4431
|
|
|
4259
|
-
export { AccountSchema, AiChatSchema, AttributionServiceImpl, ENABLE_CAPTCHA, ENABLE_ENHANCED_2FA, ENABLE_MULTI_SESSION, ENABLE_SSO, EntitlementsServiceImpl, InvitationSchema, MCPService, MemberSchema, OrganizationSchema, OrganizationUpdateSchema, PasskeySchema, PioneerServiceImpl, PurchaseInsertSchema, PurchaseSchema, PurchaseUpdateSchema, SagaOrchestratorImpl, SessionSchema, SnapshotStoreDb, TelemetrySinkDb, UserSchema, UserUpdateSchema, VerificationSchema, anonymizeEmail, anonymizeUserData, anonymizeUserId, appendFalsePositivePatterns, calculateDecayedWeight, cleanupExpiredData, clearCapabilityCache, closeTestDb, config, countAllOrganizations, countAllUsers, createPurchase, createTestUser, createTierUpgradeSagaWithDeps, createUser, createUserAccount, databaseService, deletePurchaseBySubscriptionId, deleteUserApiKeys, deleteUserData, exportUserData, extensionLinkTokens, extensionSessions, findSimilarPatterns, generateOrganizationSlug, getAccountById, getBaseUrl, getCacheMetrics, getCapabilities, getCapabilityAuditHistory, getInvitationById, getMCPService, getOrganizationById, getOrganizationBySlug, getOrganizationMembership, getOrganizationWithPurchasesAndMembersCount, getOrganizations, getOrganizationsWithMembers, getPendingInvitationByEmail, getPurchaseById, getPurchaseBySubscriptionId, getPurchasesByOrganizationId, getPurchasesByUserId, getTestDb, getUserByEmail, getUserById, getUserPrivacyPreferences, getUsers, getVectorStats, getWorkspaceLinkById, getWorkspaceLinksByUserId, handleTierDowngrade, handleTierUpgrade, healthCheck, incrementDetectionsAnalyzed, insertPatternWithEmbedding, invalidateCapabilityCache, isPgvectorEnabled, linkWorkspace, logAnonymizedEvent, logCapabilityAudit, mergeSignalIntoPattern, recordFalsePositiveSignal, resetCacheMetrics, resetCapabilities, resolveTierByWorkspaceId, sagaPersistence, sanitizeForLogging, searchSimilarPatterns, shouldRetainData, signalToPattern, testInTransaction, truncateAllTables, unlinkAllWorkspacesForUser, unlinkWorkspace, updateCapabilities, updateOrganization, updatePatternEmbedding, updatePurchase, updateUser, updateWorkspaceTier };
|
|
4432
|
+
export { AccountSchema, AiChatSchema, AttributionServiceImpl, ENABLE_CAPTCHA, ENABLE_ENHANCED_2FA, ENABLE_MULTI_SESSION, ENABLE_SSO, EntitlementsServiceImpl, InvitationSchema, MCPService, MemberSchema, OrganizationSchema, OrganizationUpdateSchema, PasskeySchema, PioneerServiceImpl, PurchaseInsertSchema, PurchaseSchema, PurchaseUpdateSchema, SagaOrchestratorImpl, SessionSchema, SnapshotStoreDb, TelemetrySinkDb, TelemetrySinkDbAdapter, UserSchema, UserUpdateSchema, VerificationSchema, anonymizeEmail, anonymizeUserData, anonymizeUserId, appendFalsePositivePatterns, calculateDecayedWeight, cleanupExpiredData, clearCapabilityCache, closeTestDb, config, countAllOrganizations, countAllUsers, createPurchase, createTestUser, createTierUpgradeSagaWithDeps, createUser, createUserAccount, databaseService, deletePurchaseBySubscriptionId, deleteUserApiKeys, deleteUserData, exportUserData, extensionLinkTokens, extensionSessions, findSimilarPatterns, generateOrganizationSlug, getAccountById, getBaseUrl, getCacheMetrics, getCapabilities, getCapabilityAuditHistory, getInvitationById, getMCPService, getOrganizationById, getOrganizationBySlug, getOrganizationMembership, getOrganizationWithPurchasesAndMembersCount, getOrganizations, getOrganizationsWithMembers, getPendingInvitationByEmail, getPurchaseById, getPurchaseBySubscriptionId, getPurchasesByOrganizationId, getPurchasesByUserId, getTestDb, getUserByEmail, getUserById, getUserPrivacyPreferences, getUsers, getVectorStats, getWorkspaceLinkById, getWorkspaceLinksByUserId, handleTierDowngrade, handleTierUpgrade, healthCheck, incrementDetectionsAnalyzed, insertPatternWithEmbedding, invalidateCapabilityCache, isPgvectorEnabled, linkWorkspace, logAnonymizedEvent, logCapabilityAudit, mergeSignalIntoPattern, recordFalsePositiveSignal, resetCacheMetrics, resetCapabilities, resolveTierByWorkspaceId, sagaPersistence, sanitizeForLogging, searchSimilarPatterns, shouldRetainData, signalToPattern, testInTransaction, truncateAllTables, unlinkAllWorkspacesForUser, unlinkWorkspace, updateCapabilities, updateOrganization, updatePatternEmbedding, updatePurchase, updateUser, updateWorkspaceTier };
|
|
@@ -874,6 +874,32 @@ function resolveNodePath() {
|
|
|
874
874
|
}
|
|
875
875
|
__name(resolveNodePath, "resolveNodePath");
|
|
876
876
|
__name2(resolveNodePath, "resolveNodePath");
|
|
877
|
+
function resolveSnapbackBinaryPath() {
|
|
878
|
+
try {
|
|
879
|
+
const isWindows = process.platform === "win32";
|
|
880
|
+
const command = isWindows ? "where snapback" : "which snapback";
|
|
881
|
+
const result = execSync(command, {
|
|
882
|
+
encoding: "utf-8",
|
|
883
|
+
timeout: 5e3
|
|
884
|
+
}).trim();
|
|
885
|
+
const binaryPath = result.split(/\r?\n/)[0].trim();
|
|
886
|
+
if (binaryPath && existsSync(binaryPath)) {
|
|
887
|
+
return binaryPath;
|
|
888
|
+
}
|
|
889
|
+
} catch {
|
|
890
|
+
}
|
|
891
|
+
const commonPaths = [
|
|
892
|
+
"/opt/homebrew/bin/snapback",
|
|
893
|
+
"/usr/local/bin/snapback",
|
|
894
|
+
"/usr/bin/snapback"
|
|
895
|
+
];
|
|
896
|
+
for (const p of commonPaths) {
|
|
897
|
+
if (existsSync(p)) return p;
|
|
898
|
+
}
|
|
899
|
+
return "snapback";
|
|
900
|
+
}
|
|
901
|
+
__name(resolveSnapbackBinaryPath, "resolveSnapbackBinaryPath");
|
|
902
|
+
__name2(resolveSnapbackBinaryPath, "resolveSnapbackBinaryPath");
|
|
877
903
|
function isCommandExecutable2(command) {
|
|
878
904
|
if (command.startsWith("/") || command.match(/^[A-Z]:\\/i)) {
|
|
879
905
|
return existsSync(command);
|
|
@@ -1038,7 +1064,7 @@ function getSnapbackMCPConfig(options = {}) {
|
|
|
1038
1064
|
args.push("--workspace", workspaceRoot);
|
|
1039
1065
|
}
|
|
1040
1066
|
return {
|
|
1041
|
-
command:
|
|
1067
|
+
command: resolveSnapbackBinaryPath(),
|
|
1042
1068
|
args,
|
|
1043
1069
|
...Object.keys(env).length > 0 && {
|
|
1044
1070
|
env
|
|
@@ -1205,7 +1231,13 @@ function mergeConfig(existing, snapbackConfig, format) {
|
|
|
1205
1231
|
}
|
|
1206
1232
|
};
|
|
1207
1233
|
case "qoder": {
|
|
1208
|
-
|
|
1234
|
+
let qoderType;
|
|
1235
|
+
if (snapbackConfig.url) {
|
|
1236
|
+
const isLocal = snapbackConfig.url.startsWith("http://localhost") || snapbackConfig.url.startsWith("http://127.0.0.1");
|
|
1237
|
+
qoderType = isLocal ? "sse" : "http";
|
|
1238
|
+
} else {
|
|
1239
|
+
qoderType = "stdio";
|
|
1240
|
+
}
|
|
1209
1241
|
return {
|
|
1210
1242
|
...existing,
|
|
1211
1243
|
mcpServers: {
|
|
@@ -50,7 +50,7 @@ async function emitPostHogEvent(eventType, metadata) {
|
|
|
50
50
|
__name(emitPostHogEvent, "emitPostHogEvent");
|
|
51
51
|
async function writeAuditLog(eventType, metadata) {
|
|
52
52
|
try {
|
|
53
|
-
const { db, snapbackSchema } = await import('./dist-
|
|
53
|
+
const { db, snapbackSchema } = await import('./dist-OO5LJHL6.js');
|
|
54
54
|
if (!db) {
|
|
55
55
|
logger.warn("Database not available for audit logging", {
|
|
56
56
|
eventType
|
|
@@ -4202,7 +4202,10 @@ var quarantineEvents = pgTable("quarantine_events", {
|
|
|
4202
4202
|
errorReason: text("error_reason").notNull(),
|
|
4203
4203
|
errorStack: text("error_stack"),
|
|
4204
4204
|
attemptedAt: timestamp("attempted_at").defaultNow().notNull(),
|
|
4205
|
-
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
4205
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
4206
|
+
// Retry logic columns (for replayQuarantined implementation)
|
|
4207
|
+
retryCount: integer("retry_count").default(0).notNull(),
|
|
4208
|
+
lastAttemptedAt: timestamp("last_attempted_at")
|
|
4206
4209
|
}, (table) => {
|
|
4207
4210
|
return {
|
|
4208
4211
|
attemptedAtIndex: index("quarantine_events_attempted_at_idx").on(table.attemptedAt),
|