@runtimescope/collector 0.9.2 → 0.10.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/dist/dashboard.js CHANGED
@@ -8,8 +8,8 @@ import { join, resolve } from "path";
8
8
  import { fileURLToPath } from "url";
9
9
  var __dirname = fileURLToPath(new URL(".", import.meta.url));
10
10
  var REPO_ROOT = resolve(__dirname, "..", "..", "..");
11
- var MCP_WS_PORT = 9090;
12
- var MCP_HTTP_PORT = 9091;
11
+ var MCP_WS_PORT = 6767;
12
+ var MCP_HTTP_PORT = 6768;
13
13
  var FALLBACK_WS_PORT = 9092;
14
14
  var FALLBACK_HTTP_PORT = 9093;
15
15
  var DASHBOARD_PORT = 3200;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dashboard.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// ============================================================\n// RuntimeScope Dashboard Launcher\n//\n// Smart single command that:\n// 1. Detects if MCP server is already running (port 9090/9091)\n// 2. Starts standalone collector on free ports if needed\n// 3. Launches the dashboard Vite dev server\n//\n// Usage:\n// node dist/dashboard.js\n// npm run dashboard (from repo root)\n// ============================================================\n\nimport { createServer, type Server } from 'node:net';\nimport { spawn, type ChildProcess } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = fileURLToPath(new URL('.', import.meta.url));\n// dist/ is at packages/collector/dist/, so repo root is 3 levels up\nconst REPO_ROOT = resolve(__dirname, '..', '..', '..');\n\nconst MCP_WS_PORT = 9090;\nconst MCP_HTTP_PORT = 9091;\nconst FALLBACK_WS_PORT = 9092;\nconst FALLBACK_HTTP_PORT = 9093;\nconst DASHBOARD_PORT = 3200;\n\n// ---- Port checking ----\n\nfunction isPortInUse(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server: Server = createServer();\n server.once('error', () => resolve(true));\n server.once('listening', () => { server.close(); resolve(false); });\n server.listen(port, '127.0.0.1');\n });\n}\n\n// ---- Main ----\n\nasync function main(): Promise<void> {\n const children: ChildProcess[] = [];\n\n const cleanup = () => {\n console.error('\\n[RuntimeScope] Shutting down...');\n for (const child of children) {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n }\n process.exit(0);\n };\n process.on('SIGINT', cleanup);\n process.on('SIGTERM', cleanup);\n\n // 1. Detect if MCP server is already running\n const mcpRunning = await isPortInUse(MCP_HTTP_PORT);\n let collectorHttpPort: number;\n let collectorWsPort: number;\n let collectorProcess: ChildProcess | null = null;\n\n if (mcpRunning) {\n // MCP server is running — check if it has our HTTP API\n try {\n const res = await fetch(`http://127.0.0.1:${MCP_HTTP_PORT}/api/health`);\n const data = await res.json() as { status?: string };\n if (data.status === 'ok') {\n console.error(`[RuntimeScope] MCP server detected on :${MCP_HTTP_PORT}`);\n collectorHttpPort = MCP_HTTP_PORT;\n collectorWsPort = MCP_WS_PORT;\n } else {\n throw new Error('Not RuntimeScope');\n }\n } catch {\n // Port 9091 is in use but not by RuntimeScope — use fallback\n console.error(`[RuntimeScope] Port ${MCP_HTTP_PORT} in use (not RuntimeScope) — using fallback ports`);\n collectorHttpPort = FALLBACK_HTTP_PORT;\n collectorWsPort = FALLBACK_WS_PORT;\n }\n } else {\n // Nothing on 9090/9091 — start collector on default ports\n collectorHttpPort = MCP_HTTP_PORT;\n collectorWsPort = MCP_WS_PORT;\n }\n\n // 2. Start standalone collector if MCP isn't providing the API\n const needsCollector = collectorHttpPort !== MCP_HTTP_PORT || !mcpRunning;\n\n if (needsCollector) {\n const standalonePath = join(__dirname, 'standalone.js');\n if (!existsSync(standalonePath)) {\n console.error('[RuntimeScope] Error: standalone.js not found. Run `npm run build -w packages/collector` first.');\n process.exit(1);\n }\n\n console.error(`[RuntimeScope] Starting collector on ws://:${collectorWsPort} + http://:${collectorHttpPort}...`);\n\n collectorProcess = spawn('node', [standalonePath], {\n env: {\n ...process.env,\n RUNTIMESCOPE_PORT: String(collectorWsPort),\n RUNTIMESCOPE_HTTP_PORT: String(collectorHttpPort),\n },\n stdio: ['ignore', 'ignore', 'inherit'],\n });\n children.push(collectorProcess);\n\n // Wait for collector to be ready\n for (let i = 0; i < 20; i++) {\n await new Promise((r) => setTimeout(r, 250));\n try {\n const res = await fetch(`http://127.0.0.1:${collectorHttpPort}/api/health`);\n if (res.ok) break;\n } catch { /* not ready yet */ }\n }\n }\n\n // 3. Check if collector API is healthy\n try {\n const res = await fetch(`http://127.0.0.1:${collectorHttpPort}/api/health`);\n const data = await res.json() as { status?: string; sessions?: number };\n console.error(`[RuntimeScope] Collector ready (${data.sessions ?? 0} sessions)`);\n } catch {\n console.error(`[RuntimeScope] Warning: Could not reach collector on :${collectorHttpPort}`);\n }\n\n // 4. Start dashboard\n const dashboardDir = join(REPO_ROOT, 'packages', 'dashboard');\n if (!existsSync(dashboardDir)) {\n console.error(`[RuntimeScope] Dashboard not found at ${dashboardDir}`);\n process.exit(1);\n }\n\n // Check if port 3200 is free\n const dashboardInUse = await isPortInUse(DASHBOARD_PORT);\n if (dashboardInUse) {\n console.error(`[RuntimeScope] Dashboard already running on http://localhost:${DASHBOARD_PORT}`);\n console.error(`[RuntimeScope] Open http://localhost:${DASHBOARD_PORT} in your browser`);\n if (!needsCollector) process.exit(0);\n // Keep running if we started a collector\n return;\n }\n\n console.error(`[RuntimeScope] Starting dashboard on http://localhost:${DASHBOARD_PORT}...`);\n\n const vite = spawn('npx', ['vite', '--port', String(DASHBOARD_PORT)], {\n cwd: dashboardDir,\n env: {\n ...process.env,\n VITE_API_TARGET: `http://127.0.0.1:${collectorHttpPort}`,\n },\n stdio: ['ignore', 'pipe', 'inherit'],\n });\n children.push(vite);\n\n // Wait for Vite to be ready and show the URL\n vite.stdout?.on('data', (data: Buffer) => {\n const line = data.toString();\n if (line.includes('Local:') || line.includes('ready')) {\n // Don't echo Vite's output — we'll print our own summary\n }\n });\n\n // Wait a moment for Vite to start\n await new Promise((r) => setTimeout(r, 3000));\n\n // 5. Print summary\n console.error('');\n console.error(' ╔══════════════════════════════════════════════╗');\n console.error(' ║ RuntimeScope Dashboard ║');\n console.error(' ╠══════════════════════════════════════════════╣');\n console.error(` ║ Dashboard: http://localhost:${DASHBOARD_PORT} ║`);\n console.error(` ║ Collector: ws://127.0.0.1:${collectorWsPort} ║`);\n console.error(` ║ HTTP API: http://127.0.0.1:${collectorHttpPort} ║`);\n console.error(` ║ Source: ${mcpRunning && collectorHttpPort === MCP_HTTP_PORT ? 'MCP Server (Claude Code)' : 'Standalone Collector '} ║`);\n console.error(' ╚══════════════════════════════════════════════╝');\n console.error('');\n console.error(' Press Ctrl+C to stop.');\n console.error('');\n\n // Keep alive\n await new Promise(() => {});\n}\n\nmain().catch((err) => {\n console.error('[RuntimeScope] Fatal:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":["resolve"]}
1
+ {"version":3,"sources":["../src/dashboard.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// ============================================================\n// RuntimeScope Dashboard Launcher\n//\n// Smart single command that:\n// 1. Detects if MCP server is already running (port 6767/6768)\n// 2. Starts standalone collector on free ports if needed\n// 3. Launches the dashboard Vite dev server\n//\n// Usage:\n// node dist/dashboard.js\n// npm run dashboard (from repo root)\n// ============================================================\n\nimport { createServer, type Server } from 'node:net';\nimport { spawn, type ChildProcess } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = fileURLToPath(new URL('.', import.meta.url));\n// dist/ is at packages/collector/dist/, so repo root is 3 levels up\nconst REPO_ROOT = resolve(__dirname, '..', '..', '..');\n\nconst MCP_WS_PORT = 6767;\nconst MCP_HTTP_PORT = 6768;\nconst FALLBACK_WS_PORT = 9092;\nconst FALLBACK_HTTP_PORT = 9093;\nconst DASHBOARD_PORT = 3200;\n\n// ---- Port checking ----\n\nfunction isPortInUse(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server: Server = createServer();\n server.once('error', () => resolve(true));\n server.once('listening', () => { server.close(); resolve(false); });\n server.listen(port, '127.0.0.1');\n });\n}\n\n// ---- Main ----\n\nasync function main(): Promise<void> {\n const children: ChildProcess[] = [];\n\n const cleanup = () => {\n console.error('\\n[RuntimeScope] Shutting down...');\n for (const child of children) {\n try { child.kill('SIGTERM'); } catch { /* already dead */ }\n }\n process.exit(0);\n };\n process.on('SIGINT', cleanup);\n process.on('SIGTERM', cleanup);\n\n // 1. Detect if MCP server is already running\n const mcpRunning = await isPortInUse(MCP_HTTP_PORT);\n let collectorHttpPort: number;\n let collectorWsPort: number;\n let collectorProcess: ChildProcess | null = null;\n\n if (mcpRunning) {\n // MCP server is running — check if it has our HTTP API\n try {\n const res = await fetch(`http://127.0.0.1:${MCP_HTTP_PORT}/api/health`);\n const data = await res.json() as { status?: string };\n if (data.status === 'ok') {\n console.error(`[RuntimeScope] MCP server detected on :${MCP_HTTP_PORT}`);\n collectorHttpPort = MCP_HTTP_PORT;\n collectorWsPort = MCP_WS_PORT;\n } else {\n throw new Error('Not RuntimeScope');\n }\n } catch {\n // Port 6768 is in use but not by RuntimeScope — use fallback\n console.error(`[RuntimeScope] Port ${MCP_HTTP_PORT} in use (not RuntimeScope) — using fallback ports`);\n collectorHttpPort = FALLBACK_HTTP_PORT;\n collectorWsPort = FALLBACK_WS_PORT;\n }\n } else {\n // Nothing on 6767/6768 — start collector on default ports\n collectorHttpPort = MCP_HTTP_PORT;\n collectorWsPort = MCP_WS_PORT;\n }\n\n // 2. Start standalone collector if MCP isn't providing the API\n const needsCollector = collectorHttpPort !== MCP_HTTP_PORT || !mcpRunning;\n\n if (needsCollector) {\n const standalonePath = join(__dirname, 'standalone.js');\n if (!existsSync(standalonePath)) {\n console.error('[RuntimeScope] Error: standalone.js not found. Run `npm run build -w packages/collector` first.');\n process.exit(1);\n }\n\n console.error(`[RuntimeScope] Starting collector on ws://:${collectorWsPort} + http://:${collectorHttpPort}...`);\n\n collectorProcess = spawn('node', [standalonePath], {\n env: {\n ...process.env,\n RUNTIMESCOPE_PORT: String(collectorWsPort),\n RUNTIMESCOPE_HTTP_PORT: String(collectorHttpPort),\n },\n stdio: ['ignore', 'ignore', 'inherit'],\n });\n children.push(collectorProcess);\n\n // Wait for collector to be ready\n for (let i = 0; i < 20; i++) {\n await new Promise((r) => setTimeout(r, 250));\n try {\n const res = await fetch(`http://127.0.0.1:${collectorHttpPort}/api/health`);\n if (res.ok) break;\n } catch { /* not ready yet */ }\n }\n }\n\n // 3. Check if collector API is healthy\n try {\n const res = await fetch(`http://127.0.0.1:${collectorHttpPort}/api/health`);\n const data = await res.json() as { status?: string; sessions?: number };\n console.error(`[RuntimeScope] Collector ready (${data.sessions ?? 0} sessions)`);\n } catch {\n console.error(`[RuntimeScope] Warning: Could not reach collector on :${collectorHttpPort}`);\n }\n\n // 4. Start dashboard\n const dashboardDir = join(REPO_ROOT, 'packages', 'dashboard');\n if (!existsSync(dashboardDir)) {\n console.error(`[RuntimeScope] Dashboard not found at ${dashboardDir}`);\n process.exit(1);\n }\n\n // Check if port 3200 is free\n const dashboardInUse = await isPortInUse(DASHBOARD_PORT);\n if (dashboardInUse) {\n console.error(`[RuntimeScope] Dashboard already running on http://localhost:${DASHBOARD_PORT}`);\n console.error(`[RuntimeScope] Open http://localhost:${DASHBOARD_PORT} in your browser`);\n if (!needsCollector) process.exit(0);\n // Keep running if we started a collector\n return;\n }\n\n console.error(`[RuntimeScope] Starting dashboard on http://localhost:${DASHBOARD_PORT}...`);\n\n const vite = spawn('npx', ['vite', '--port', String(DASHBOARD_PORT)], {\n cwd: dashboardDir,\n env: {\n ...process.env,\n VITE_API_TARGET: `http://127.0.0.1:${collectorHttpPort}`,\n },\n stdio: ['ignore', 'pipe', 'inherit'],\n });\n children.push(vite);\n\n // Wait for Vite to be ready and show the URL\n vite.stdout?.on('data', (data: Buffer) => {\n const line = data.toString();\n if (line.includes('Local:') || line.includes('ready')) {\n // Don't echo Vite's output — we'll print our own summary\n }\n });\n\n // Wait a moment for Vite to start\n await new Promise((r) => setTimeout(r, 3000));\n\n // 5. Print summary\n console.error('');\n console.error(' ╔══════════════════════════════════════════════╗');\n console.error(' ║ RuntimeScope Dashboard ║');\n console.error(' ╠══════════════════════════════════════════════╣');\n console.error(` ║ Dashboard: http://localhost:${DASHBOARD_PORT} ║`);\n console.error(` ║ Collector: ws://127.0.0.1:${collectorWsPort} ║`);\n console.error(` ║ HTTP API: http://127.0.0.1:${collectorHttpPort} ║`);\n console.error(` ║ Source: ${mcpRunning && collectorHttpPort === MCP_HTTP_PORT ? 'MCP Server (Claude Code)' : 'Standalone Collector '} ║`);\n console.error(' ╚══════════════════════════════════════════════╝');\n console.error('');\n console.error(' Press Ctrl+C to stop.');\n console.error('');\n\n // Keep alive\n await new Promise(() => {});\n}\n\nmain().catch((err) => {\n console.error('[RuntimeScope] Fatal:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":["resolve"]}
package/dist/index.d.ts CHANGED
@@ -984,6 +984,8 @@ declare class EventStore {
984
984
  getAllEvents(sinceSeconds?: number, sessionId?: string, projectId?: string): RuntimeEvent[];
985
985
  getSessionIdsForProject(appName: string): string[];
986
986
  getSessionIdsForProjectId(projectId: string): string[];
987
+ /** Re-tag all sessions with oldProjectId to use newProjectId. */
988
+ retagSessions(oldProjectId: string, newProjectId: string): void;
987
989
  /** Check if an event belongs to the given projectId (via its session). */
988
990
  private matchesProjectId;
989
991
  getStateEvents(filter?: StateFilter): StateEvent[];
@@ -1094,8 +1096,17 @@ interface InfrastructureConfig {
1094
1096
  }>;
1095
1097
  services?: Record<string, string>;
1096
1098
  }
1099
+ /** Minimal interface for PmStore used by rebuildAppIndex (avoids circular deps). */
1100
+ interface PmStoreIndexSource {
1101
+ listProjects(): Array<{
1102
+ runtimeApps?: string[];
1103
+ runtimeProjectId?: string;
1104
+ path?: string;
1105
+ }>;
1106
+ }
1097
1107
  declare class ProjectManager {
1098
1108
  private readonly baseDir;
1109
+ private appProjectIndex;
1099
1110
  constructor(baseDir?: string);
1100
1111
  get rootDir(): string;
1101
1112
  getProjectDir(projectName: string): string;
@@ -1116,6 +1127,14 @@ declare class ProjectManager {
1116
1127
  setProjectIdForApp(appName: string, projectId: string): void;
1117
1128
  /** Resolve a projectId to an appName by scanning all project configs. Returns null if not found. */
1118
1129
  getAppForProjectId(projectId: string): string | null;
1130
+ /**
1131
+ * Build reverse index: appName -> projectId.
1132
+ * Scans all project configs, PM projects with runtimeApps + runtimeProjectId,
1133
+ * and project-level .runtimescope/config.json files from PM project paths.
1134
+ */
1135
+ rebuildAppIndex(pmStore?: PmStoreIndexSource): void;
1136
+ /** O(1) lookup from the cached index. */
1137
+ resolveAppProjectId(appName: string): string | null;
1119
1138
  resolveEnvVars(value: string): string;
1120
1139
  private mkdirp;
1121
1140
  private readJson;
@@ -1129,6 +1148,33 @@ declare class ProjectManager {
1129
1148
  private parseSimpleYaml;
1130
1149
  }
1131
1150
 
1151
+ /** Minimal interface for PmStore to avoid circular dependencies. */
1152
+ interface PmStoreLike {
1153
+ findProjectIdByApp(appName: string): string | null;
1154
+ getWorkspaceByApiKey?(key: string): {
1155
+ id: string;
1156
+ slug: string;
1157
+ name: string;
1158
+ } | null;
1159
+ listProjects?(): Array<{
1160
+ id: string;
1161
+ runtimeProjectId?: string;
1162
+ workspaceId?: string;
1163
+ }>;
1164
+ setProjectWorkspace?(projectId: string, workspaceId: string): void;
1165
+ autoLinkApp?(appName: string, projectId?: string): string | null;
1166
+ }
1167
+ /** Generate a new project ID (proj_ + 12 random alphanumeric chars). */
1168
+ declare function generateProjectId(): string;
1169
+ /** Validate that a string is a well-formed project ID. */
1170
+ declare function isValidProjectId(id: string): boolean;
1171
+ /**
1172
+ * Look up or create a project ID for a given appName.
1173
+ * Persists the ID in the ProjectManager config so the same appName
1174
+ * always returns the same project ID (idempotent).
1175
+ */
1176
+ declare function getOrCreateProjectId(projectManager: ProjectManager, appName: string): string;
1177
+
1132
1178
  interface RateLimitConfig {
1133
1179
  maxEventsPerSecond?: number;
1134
1180
  maxEventsPerMinute?: number;
@@ -1192,6 +1238,7 @@ declare class CollectorServer {
1192
1238
  private pruneTimer;
1193
1239
  private heartbeatTimer;
1194
1240
  private tlsConfig;
1241
+ private pmStore;
1195
1242
  constructor(options?: CollectorServerOptions);
1196
1243
  getStore(): EventStore;
1197
1244
  getPort(): number | null;
@@ -1200,6 +1247,8 @@ declare class CollectorServer {
1200
1247
  getSqliteStore(projectName: string): SqliteStore | undefined;
1201
1248
  getSqliteStores(): Map<string, SqliteStore>;
1202
1249
  getRateLimiter(): SessionRateLimiter;
1250
+ /** Set the PmStore for project ID resolution (called after construction when PmStore is available). */
1251
+ setPmStore(pmStore: PmStoreLike | null): void;
1203
1252
  onConnect(cb: (sessionId: string, projectName: string, projectId?: string) => void): void;
1204
1253
  onDisconnect(cb: (sessionId: string, projectName: string, projectId?: string) => void): void;
1205
1254
  start(options?: CollectorServerOptions): Promise<void>;
@@ -1258,20 +1307,11 @@ declare class RingBuffer<T> {
1258
1307
  */
1259
1308
  declare function detectIssues(events: RuntimeEvent[]): DetectedIssue[];
1260
1309
 
1261
- /** Generate a new project ID (proj_ + 12 random alphanumeric chars). */
1262
- declare function generateProjectId(): string;
1263
- /** Validate that a string is a well-formed project ID. */
1264
- declare function isValidProjectId(id: string): boolean;
1265
- /**
1266
- * Look up or create a project ID for a given appName.
1267
- * Persists the ID in the ProjectManager config so the same appName
1268
- * always returns the same project ID (idempotent).
1269
- */
1270
- declare function getOrCreateProjectId(projectManager: ProjectManager, appName: string): string;
1271
-
1272
1310
  interface RuntimeScopeProjectConfig {
1273
1311
  /** Stable project identifier (proj_xxx). Groups all SDKs for this project. */
1274
1312
  projectId: string;
1313
+ /** DSN connection string: runtimescope://<projectId>@<host>:<port>/<appName> */
1314
+ dsn?: string;
1275
1315
  /** Human-readable project name. */
1276
1316
  appName: string;
1277
1317
  /** Optional description for dashboard/reports. */
@@ -1343,6 +1383,26 @@ declare function scaffoldProjectConfig(projectDir: string, opts: {
1343
1383
  * Returns the main appName plus any SDK-specific appNames.
1344
1384
  */
1345
1385
  declare function resolveProjectAppNames(config: RuntimeScopeProjectConfig): string[];
1386
+ interface MigratablePmStore {
1387
+ listProjects(): Array<{
1388
+ id: string;
1389
+ name: string;
1390
+ path?: string;
1391
+ runtimeApps?: string[];
1392
+ runtimeProjectId?: string;
1393
+ }>;
1394
+ updateProject(id: string, updates: Record<string, unknown>): void;
1395
+ }
1396
+ interface MigrationResult {
1397
+ unified: number;
1398
+ skipped: number;
1399
+ details: string[];
1400
+ }
1401
+ /**
1402
+ * Scan PM projects with multiple runtimeApps and ensure all their
1403
+ * appNames share the same canonical projectId (from .runtimescope/config.json).
1404
+ */
1405
+ declare function migrateProjectIds(projectManager: ProjectManager, pmStore?: MigratablePmStore | null): MigrationResult;
1346
1406
 
1347
1407
  declare function isSqliteAvailable(): boolean;
1348
1408
 
@@ -1497,10 +1557,40 @@ declare class SessionManager {
1497
1557
 
1498
1558
  declare function compareSessions(metricsA: SessionMetrics, metricsB: SessionMetrics): SessionDiffResult;
1499
1559
 
1560
+ /**
1561
+ * A workspace is the top-level tenancy boundary. Every project belongs to
1562
+ * exactly one workspace, and every API key is scoped to one workspace.
1563
+ * On single-user installs a "personal" workspace is auto-created and is
1564
+ * invisible to users until they create a second one.
1565
+ */
1566
+ interface PmWorkspace {
1567
+ id: string;
1568
+ name: string;
1569
+ slug: string;
1570
+ description?: string;
1571
+ createdAt: number;
1572
+ updatedAt: number;
1573
+ isDefault?: boolean;
1574
+ }
1575
+ /**
1576
+ * Workspace-scoped API key. SDKs authenticate with a key, the collector
1577
+ * looks up its workspace, and only projects in that workspace can accept
1578
+ * events from that key.
1579
+ */
1580
+ interface PmApiKey {
1581
+ key: string;
1582
+ workspaceId: string;
1583
+ label: string;
1584
+ createdAt: number;
1585
+ lastUsedAt?: number;
1586
+ expiresAt?: number;
1587
+ revokedAt?: number;
1588
+ }
1500
1589
  type ProjectPhase = 'preliminary' | 'application_development' | 'post_implementation';
1501
1590
  type ProjectStatus = 'active' | 'suspended' | 'abandoned';
1502
1591
  interface PmProject {
1503
1592
  id: string;
1593
+ workspaceId?: string;
1504
1594
  name: string;
1505
1595
  path?: string;
1506
1596
  claudeProjectKey?: string;
@@ -1683,6 +1773,11 @@ declare class PmStore {
1683
1773
  constructor(options: PmStoreOptions);
1684
1774
  private createSchema;
1685
1775
  private runMigrations;
1776
+ /**
1777
+ * Ensure a default "personal" workspace exists and every project has a
1778
+ * workspace_id. Runs on every startup — idempotent.
1779
+ */
1780
+ private ensureDefaultWorkspace;
1686
1781
  upsertProject(project: PmProject): void;
1687
1782
  getProject(id: string): PmProject | null;
1688
1783
  listProjects(): PmProject[];
@@ -1693,7 +1788,26 @@ declare class PmStore {
1693
1788
  * Returns the project ID if linked, null if no match found.
1694
1789
  */
1695
1790
  autoLinkApp(appName: string, projectId?: string): string | null;
1791
+ /** Find a project's runtimeProjectId by checking if appName appears in any project's runtimeApps. */
1792
+ findProjectIdByApp(appName: string): string | null;
1696
1793
  listCategories(): string[];
1794
+ listWorkspaces(): PmWorkspace[];
1795
+ getWorkspace(id: string): PmWorkspace | null;
1796
+ getWorkspaceBySlug(slug: string): PmWorkspace | null;
1797
+ getDefaultWorkspace(): PmWorkspace;
1798
+ createWorkspace(input: {
1799
+ name: string;
1800
+ slug?: string;
1801
+ description?: string;
1802
+ }): PmWorkspace;
1803
+ updateWorkspace(id: string, updates: Partial<Pick<PmWorkspace, 'name' | 'slug' | 'description'>>): void;
1804
+ deleteWorkspace(id: string): void;
1805
+ /** Move a project between workspaces. */
1806
+ setProjectWorkspace(projectId: string, workspaceId: string): void;
1807
+ createApiKey(workspaceId: string, label: string, expiresAt?: number): PmApiKey;
1808
+ listApiKeys(workspaceId: string): PmApiKey[];
1809
+ revokeApiKey(key: string): void;
1810
+ getWorkspaceByApiKey(key: string): PmWorkspace | null;
1697
1811
  private mapProjectRow;
1698
1812
  createTask(task: PmTask): PmTask;
1699
1813
  updateTask(id: string, updates: Partial<PmTask>): void;
@@ -1754,6 +1868,14 @@ declare class PmStore {
1754
1868
  category?: string;
1755
1869
  }): Promise<Buffer>;
1756
1870
  private mapCapexRow;
1871
+ deleteProject(id: string): void;
1872
+ isDeletedPath(path: string): boolean;
1873
+ recoverProject(path: string): void;
1874
+ listDeletedProjects(): Array<{
1875
+ path: string;
1876
+ name: string;
1877
+ deletedAt: number;
1878
+ }>;
1757
1879
  close(): void;
1758
1880
  }
1759
1881
  interface ProjectSummaryRow {
@@ -1929,4 +2051,4 @@ declare function parseProcessList(): ProcessInfo[];
1929
2051
  /** Get RSS memory in MB for a given PID. Cross-platform. */
1930
2052
  declare function getProcessMemoryMB(pid: number): number;
1931
2053
 
1932
- export { type ApiChangeRecord, type ApiContract, type ApiContractField, ApiDiscoveryEngine, type ApiEndpoint, type ApiEndpointHealth, type ApiKeyEntry, type AuthConfig, type AuthInfo, AuthManager, BUILT_IN_RULES, type BackgroundSpriteSheet, type BaseEvent, type BuildMeta, type BuildStatus, type CSSArchitecture, type CSSCustomProperty, type CapexClassification, type CapexSummary, type CaptureConfig, CollectorServer, type CollectorServerOptions, type ColorToken, type CommandResponse, type ComputedStyleEntry, ConnectionManager, type ConsoleEvent, type ConsoleFilter, type ConsoleLevel, type CustomEvent, type CustomEventFilter, DataBrowser, type DatabaseConnectionConfig, type DatabaseEvent, type DatabaseFilter, type DatabaseOperation, type DatabaseSchema, type DatabaseSource, type DeployLog, type DetectedBuildTool, type DetectedFramework, type DetectedHosting, type DetectedIssue, type DetectedMetaFramework, type DetectedUILibrary, type DevProcess, type DevProcessType, type DomSnapshotEvent, type ElementSnapshotNode, type EventBatchPayload, EventStore, type EventType, type FontFaceInfo, type FontUsage, type FormFieldInfo, type GitCommit, type GitFileChange, type GitFileStatus, type GitStatus, type GlobalConfig, type GraphQLOperation, type HandshakePayload, type HeadingInfo, type HistoricalFilter, HttpServer, type HttpServerOptions, type IconFontInfo, type ImageAsset, type IndexSuggestion, InfraConnector, type InfraOverview, type InfrastructureConfig, type InlineSVGAsset, type InteractiveElementInfo, type IssueSeverity, type LandmarkInfo, type LayoutNode, type ManagedConnection, type MaskSpriteSheet, type MemoryFile, type MetricDelta, type NavigationEvent, type NetworkEvent, type NetworkFilter, type NormalizedQueryStats, type PerformanceEvent, type PerformanceFilter, type PerformanceMetricName, type PmCapexEntry, type PmNote, type PmProject, type PmSession, PmStore, type PmTask, type PortUsage, type ProcessInfo, ProcessMonitor, type ProjectConfig, ProjectDiscovery, ProjectManager, type ProjectPhase, type ProjectStatus, type RateLimitConfig, type ReadOptions, type ReadResult, type ReconAccessibilityEvent, type ReconAssetInventoryEvent, type ReconComputedStylesEvent, type ReconDesignTokensEvent, type ReconElementSnapshotEvent, type ReconEventType, type ReconFilter, type ReconFontsEvent, type ReconLayoutTreeEvent, type ReconMetadataEvent, type RedactionRule, Redactor, type RedactorConfig, type RenderComponentProfile, type RenderEvent, type RenderFilter, RingBuffer, type RulesFiles, type RuntimeEvent, type RuntimeLog, type RuntimeScopeProjectConfig, type SVGSpriteSymbol, type SchemaColumn, type SchemaForeignKey, type SchemaIndex, SchemaIntrospector, type SchemaTable, type SdkEntry, type ServerCommand, type ServerMetricName, type ServiceInfo, type SessionDiffResult, type SessionEvent, type SessionInfo, type SessionInfoExtended, SessionManager, type SessionMetrics, SessionRateLimiter, type SessionSnapshot, type SessionStats, type SpacingValue, type SpriteFrame, SqliteStore, type SqliteStoreOptions, type StateEvent, type StateFilter, type TaskPriority, type TaskSource, type TaskStatus, type TechStackDetection, type TimelineFilter, type TlsConfig, type ToolResponse, type TypographyToken, type UIInteractionAction, type UIInteractionEvent, type UIInteractionFilter, type UserContext, type WSMessage, type WebVitalRating, type WorkType, type WriteOptions, type WriteResult, aggregateQueryStats, calculateActiveMinutes, calculateCostMicrodollars, compareSessions, detectIssues, detectN1Queries, detectOverfetching, detectSlowQueries, findPidsInDirectory, generateApiKey, generateProjectId, getListenPorts, getOrCreateProjectId, getPidsOnPort, getProcessCwd, getProcessMemoryMB, isSqliteAvailable, isValidProjectId, loadTlsOptions, parseProcessList, parseSessionJsonl, readProjectConfig, resolveProjectAppNames, resolveTlsConfig, scaffoldProjectConfig, suggestIndexes, writeProjectConfig };
2054
+ export { type ApiChangeRecord, type ApiContract, type ApiContractField, ApiDiscoveryEngine, type ApiEndpoint, type ApiEndpointHealth, type ApiKeyEntry, type AuthConfig, type AuthInfo, AuthManager, BUILT_IN_RULES, type BackgroundSpriteSheet, type BaseEvent, type BuildMeta, type BuildStatus, type CSSArchitecture, type CSSCustomProperty, type CapexClassification, type CapexSummary, type CaptureConfig, CollectorServer, type CollectorServerOptions, type ColorToken, type CommandResponse, type ComputedStyleEntry, ConnectionManager, type ConsoleEvent, type ConsoleFilter, type ConsoleLevel, type CustomEvent, type CustomEventFilter, DataBrowser, type DatabaseConnectionConfig, type DatabaseEvent, type DatabaseFilter, type DatabaseOperation, type DatabaseSchema, type DatabaseSource, type DeployLog, type DetectedBuildTool, type DetectedFramework, type DetectedHosting, type DetectedIssue, type DetectedMetaFramework, type DetectedUILibrary, type DevProcess, type DevProcessType, type DomSnapshotEvent, type ElementSnapshotNode, type EventBatchPayload, EventStore, type EventType, type FontFaceInfo, type FontUsage, type FormFieldInfo, type GitCommit, type GitFileChange, type GitFileStatus, type GitStatus, type GlobalConfig, type GraphQLOperation, type HandshakePayload, type HeadingInfo, type HistoricalFilter, HttpServer, type HttpServerOptions, type IconFontInfo, type ImageAsset, type IndexSuggestion, InfraConnector, type InfraOverview, type InfrastructureConfig, type InlineSVGAsset, type InteractiveElementInfo, type IssueSeverity, type LandmarkInfo, type LayoutNode, type ManagedConnection, type MaskSpriteSheet, type MemoryFile, type MetricDelta, type NavigationEvent, type NetworkEvent, type NetworkFilter, type NormalizedQueryStats, type PerformanceEvent, type PerformanceFilter, type PerformanceMetricName, type PmApiKey, type PmCapexEntry, type PmNote, type PmProject, type PmSession, PmStore, type PmStoreIndexSource, type PmTask, type PmWorkspace, type PortUsage, type ProcessInfo, ProcessMonitor, type ProjectConfig, ProjectDiscovery, ProjectManager, type ProjectPhase, type ProjectStatus, type RateLimitConfig, type ReadOptions, type ReadResult, type ReconAccessibilityEvent, type ReconAssetInventoryEvent, type ReconComputedStylesEvent, type ReconDesignTokensEvent, type ReconElementSnapshotEvent, type ReconEventType, type ReconFilter, type ReconFontsEvent, type ReconLayoutTreeEvent, type ReconMetadataEvent, type RedactionRule, Redactor, type RedactorConfig, type RenderComponentProfile, type RenderEvent, type RenderFilter, RingBuffer, type RulesFiles, type RuntimeEvent, type RuntimeLog, type RuntimeScopeProjectConfig, type SVGSpriteSymbol, type SchemaColumn, type SchemaForeignKey, type SchemaIndex, SchemaIntrospector, type SchemaTable, type SdkEntry, type ServerCommand, type ServerMetricName, type ServiceInfo, type SessionDiffResult, type SessionEvent, type SessionInfo, type SessionInfoExtended, SessionManager, type SessionMetrics, SessionRateLimiter, type SessionSnapshot, type SessionStats, type SpacingValue, type SpriteFrame, SqliteStore, type SqliteStoreOptions, type StateEvent, type StateFilter, type TaskPriority, type TaskSource, type TaskStatus, type TechStackDetection, type TimelineFilter, type TlsConfig, type ToolResponse, type TypographyToken, type UIInteractionAction, type UIInteractionEvent, type UIInteractionFilter, type UserContext, type WSMessage, type WebVitalRating, type WorkType, type WriteOptions, type WriteResult, aggregateQueryStats, calculateActiveMinutes, calculateCostMicrodollars, compareSessions, detectIssues, detectN1Queries, detectOverfetching, detectSlowQueries, findPidsInDirectory, generateApiKey, generateProjectId, getListenPorts, getOrCreateProjectId, getPidsOnPort, getProcessCwd, getProcessMemoryMB, isSqliteAvailable, isValidProjectId, loadTlsOptions, migrateProjectIds, parseProcessList, parseSessionJsonl, readProjectConfig, resolveProjectAppNames, resolveTlsConfig, scaffoldProjectConfig, suggestIndexes, writeProjectConfig };
package/dist/index.js CHANGED
@@ -25,10 +25,15 @@ import {
25
25
  isSqliteAvailable,
26
26
  isValidProjectId,
27
27
  loadTlsOptions,
28
+ migrateProjectIds,
28
29
  parseProcessList,
29
30
  parseSessionJsonl,
30
- resolveTlsConfig
31
- } from "./chunk-GENCCHYK.js";
31
+ readProjectConfig,
32
+ resolveProjectAppNames,
33
+ resolveTlsConfig,
34
+ scaffoldProjectConfig,
35
+ writeProjectConfig
36
+ } from "./chunk-WWFIEANS.js";
32
37
  import {
33
38
  __require
34
39
  } from "./chunk-UP2VWCW5.js";
@@ -334,76 +339,6 @@ function detectPoorWebVitals(events) {
334
339
  return issues;
335
340
  }
336
341
 
337
- // src/project-config.ts
338
- import { readFileSync, existsSync, writeFileSync, mkdirSync } from "fs";
339
- import { join } from "path";
340
- var DEFAULT_CAPTURE = {
341
- network: true,
342
- console: true,
343
- xhr: true,
344
- body: false,
345
- performance: true,
346
- renders: true,
347
- navigation: true,
348
- clicks: false,
349
- http: false,
350
- errors: true,
351
- stackTraces: false
352
- };
353
- function readProjectConfig(projectDir) {
354
- const configPath = join(projectDir, ".runtimescope", "config.json");
355
- if (!existsSync(configPath)) return null;
356
- try {
357
- const content = readFileSync(configPath, "utf-8");
358
- return JSON.parse(content);
359
- } catch {
360
- return null;
361
- }
362
- }
363
- function writeProjectConfig(projectDir, config) {
364
- const dir = join(projectDir, ".runtimescope");
365
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
366
- writeFileSync(join(dir, "config.json"), JSON.stringify(config, null, 2) + "\n", "utf-8");
367
- }
368
- function scaffoldProjectConfig(projectDir, opts) {
369
- const existing = readProjectConfig(projectDir);
370
- if (existing) {
371
- if (opts.sdkType) {
372
- const alreadyHas = existing.sdks.some((s) => s.type === opts.sdkType);
373
- if (!alreadyHas) {
374
- existing.sdks.push({
375
- type: opts.sdkType,
376
- framework: opts.framework,
377
- appName: opts.appName !== existing.appName ? opts.appName : void 0
378
- });
379
- writeProjectConfig(projectDir, existing);
380
- }
381
- }
382
- return existing;
383
- }
384
- const config = {
385
- projectId: generateProjectId(),
386
- appName: opts.appName,
387
- description: opts.description,
388
- sdks: opts.sdkType ? [{ type: opts.sdkType, framework: opts.framework }] : [],
389
- capture: { ...DEFAULT_CAPTURE },
390
- category: opts.category
391
- };
392
- writeProjectConfig(projectDir, config);
393
- const gitignorePath = join(projectDir, ".runtimescope", ".gitignore");
394
- if (!existsSync(gitignorePath)) {
395
- writeFileSync(gitignorePath, "# Keep config.json committed, ignore local state\n*.log\n*.db\n.env\n", "utf-8");
396
- }
397
- return config;
398
- }
399
- function resolveProjectAppNames(config) {
400
- const names = /* @__PURE__ */ new Set([config.appName]);
401
- for (const sdk of config.sdks) {
402
- if (sdk.appName) names.add(sdk.appName);
403
- }
404
- return Array.from(names);
405
- }
406
-
407
342
  // src/engines/api-discovery.ts
408
343
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
409
344
  var NUMERIC_RE = /^\d+$/;
@@ -2134,6 +2069,7 @@ export {
2134
2069
  isSqliteAvailable,
2135
2070
  isValidProjectId,
2136
2071
  loadTlsOptions,
2072
+ migrateProjectIds,
2137
2073
  parseProcessList,
2138
2074
  parseSessionJsonl,
2139
2075
  readProjectConfig,