@feltdb/core 0.6.11 → 0.6.13

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.
@@ -71,7 +71,7 @@ export function applicationUrlCandidate(project, environment = process.env) {
71
71
  if (project.configuredUrl)
72
72
  return project.configuredUrl;
73
73
  if (project.configuredPort)
74
- return `http://127.0.0.1:${project.configuredPort}`;
74
+ return `http://localhost:${project.configuredPort}/`;
75
75
  return undefined;
76
76
  }
77
77
  export function applicationIsRunning(url, timeoutMs = 750) {
@@ -0,0 +1,35 @@
1
+ import { spawn } from 'child_process';
2
+ function defaultSpawn(command, args) {
3
+ return spawn(command, [...args], { detached: true, stdio: 'ignore' });
4
+ }
5
+ export function browserCommand(url, platform = process.platform) {
6
+ if (platform === 'darwin')
7
+ return ['open', [url]];
8
+ if (platform === 'win32')
9
+ return ['cmd', ['/c', 'start', '', url]];
10
+ if (platform === 'linux')
11
+ return ['xdg-open', [url]];
12
+ return null;
13
+ }
14
+ export function openBrowser(url, spawnBrowser = defaultSpawn) {
15
+ const command = browserCommand(url);
16
+ if (!command || !process.stdout.isTTY || process.env.CI)
17
+ return false;
18
+ try {
19
+ const child = spawnBrowser(command[0], command[1]);
20
+ child.once('error', () => undefined);
21
+ child.unref();
22
+ return true;
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ export function openApplication(url) {
29
+ console.log(`🌐 Application: ${url}`);
30
+ return openBrowser(url);
31
+ }
32
+ export function openStudio(url) {
33
+ console.log(`🛠️ Studio: ${url}`);
34
+ return openBrowser(url);
35
+ }
@@ -13,6 +13,7 @@ import { discoverWorkspace, ensureWorkspaceGitIgnored, generatePairingToken, per
13
13
  import { applicationUrlCandidate, detectApplication, discoverApplicationUrl } from './application.js';
14
14
  import { resolveApplicationLifecycle, startManagedApplication, waitForManagedApplication } from './application-lifecycle.js';
15
15
  import { createDevelopmentSession, developmentSessionEnvironment, developmentSessionSummary, transitionDevelopmentSession } from './development-session.js';
16
+ import { openApplication, openStudio } from './browser-opening.js';
16
17
  function loadProjectEnvironment(file = path.resolve('.env.local')) {
17
18
  if (!fs.existsSync(file))
18
19
  return;
@@ -511,7 +512,7 @@ async function handleDev(args) {
511
512
  if (args.includes('--help')) {
512
513
  console.log('Usage: feltdb dev [--app-url URL] [--studio-port 7701] [--authority-port 7700] [--discovery-port 7799] [--no-open]');
513
514
  console.log('\nOptions:');
514
- console.log(' --app-url <url> Application URL (e.g., http://127.0.0.1:3000)');
515
+ console.log(' --app-url <url> Application URL (e.g., http://localhost:3000/)');
515
516
  console.log(' --studio-port <port> FeltDB Studio port (default: 7701)');
516
517
  console.log(' --authority-port <port> Authority port (default: 7700)');
517
518
  console.log(' --discovery-port <port> Pairing discovery port (default: 7799)');
@@ -628,7 +629,7 @@ async function handleDev(args) {
628
629
  console.log(`Attaching existing FeltDB application (${detectedApplication.feltDBSignals.join(', ')})\n`);
629
630
  }
630
631
  const requestedStudioPort = Number(args.includes('--studio-port') ? args[args.indexOf('--studio-port') + 1] || '7701' : '7701');
631
- const studioPort = String(await availablePort(requestedStudioPort));
632
+ const studioPort = String(await availablePort(requestedStudioPort, 'localhost'));
632
633
  if (studioPort !== String(requestedStudioPort))
633
634
  console.log(`⚠ Port ${requestedStudioPort} is busy; using ${studioPort} for Studio.\n`);
634
635
  process.env.STUDIO_PORT = studioPort;
@@ -678,7 +679,7 @@ async function handleDev(args) {
678
679
  storage: config.storage,
679
680
  lifecycle: applicationLifecycle,
680
681
  authorityUrl,
681
- studioUrl: `http://127.0.0.1:${studioPort}`,
682
+ studioUrl: `http://localhost:${studioPort}/`,
682
683
  pairingUrl: `http://127.0.0.1:${discoveryPort}`,
683
684
  applicationUrl: appUrl,
684
685
  });
@@ -791,7 +792,7 @@ async function handleDev(args) {
791
792
  else {
792
793
  console.log('❌ No application URL is configured.\n');
793
794
  console.log('Start your application, then run:\n');
794
- console.log(' feltdb dev --app-url http://127.0.0.1:<port>\n');
795
+ console.log(' feltdb dev --app-url http://localhost:<port>/\n');
795
796
  console.log('Or set applicationUrl in feltdb.config.json\n');
796
797
  console.log('FeltDB workspace is ready at:');
797
798
  console.log('Authority: ' + developmentSession.authorityUrl);
@@ -812,10 +813,21 @@ async function handleDev(args) {
812
813
  '--lifecycle', developmentSession.lifecycle,
813
814
  ...(developmentSession.applicationUrl ? ['--app-url', developmentSession.applicationUrl] : []),
814
815
  ...((developmentSession.runtime === 'self-hosted' || developmentSession.runtime === 'managed') ? ['--connect', developmentSession.authorityUrl] : []),
815
- ...(open ? [] : ['--no-open']),
816
- ], () => {
816
+ '--no-open',
817
+ ], studioUrl => {
818
+ developmentSession.studioUrl = studioUrl;
817
819
  transitionDevelopmentSession(developmentSession, 'READY');
818
820
  console.log(`\n${developmentSessionSummary(developmentSession)}\n`);
821
+ if (open) {
822
+ if (developmentSession.applicationUrl)
823
+ openApplication(developmentSession.applicationUrl);
824
+ openStudio(developmentSession.studioUrl);
825
+ }
826
+ else {
827
+ if (developmentSession.applicationUrl)
828
+ console.log(`🌐 Application: ${developmentSession.applicationUrl}`);
829
+ console.log(`🛠️ Studio: ${developmentSession.studioUrl}`);
830
+ }
819
831
  transitionDevelopmentSession(developmentSession, 'RUNNING');
820
832
  });
821
833
  if (managedApplication) {
@@ -1092,8 +1104,8 @@ async function handleStudio(args, onReady) {
1092
1104
  ? args[args.indexOf('--port') + 1] || '7701'
1093
1105
  : '7701';
1094
1106
  const host = args.includes('--host')
1095
- ? args[args.indexOf('--host') + 1] || '127.0.0.1'
1096
- : '127.0.0.1';
1107
+ ? args[args.indexOf('--host') + 1] || 'localhost'
1108
+ : 'localhost';
1097
1109
  const open = !args.includes('--no-open');
1098
1110
  const namespace = args.includes('--namespace')
1099
1111
  ? args[args.indexOf('--namespace') + 1] || 'default'
@@ -1223,15 +1235,12 @@ async function handleStudio(args, onReady) {
1223
1235
  if (session.pairingUrl)
1224
1236
  parameters.set('pairing', session.pairingUrl);
1225
1237
  const query = `?${parameters.toString()}`;
1226
- const studioUrl = `http://127.0.0.1:${port}/${query}`;
1238
+ const studioUrl = `http://localhost:${port}/${query}`;
1227
1239
  console.log(`FeltDB Studio ready at ${studioUrl}`);
1228
- onReady?.();
1240
+ onReady?.(studioUrl);
1229
1241
  console.log('Use Ctrl+C to stop the server.');
1230
- if (open) {
1231
- const command = process.platform === 'darwin' ? ['open', studioUrl] : process.platform === 'win32' ? ['cmd', '/c', 'start', '', studioUrl] : ['xdg-open', studioUrl];
1232
- const child = spawn(command[0], command.slice(1), { detached: true, stdio: 'ignore' });
1233
- child.unref();
1234
- }
1242
+ if (open)
1243
+ openStudio(studioUrl);
1235
1244
  await new Promise(() => { });
1236
1245
  }
1237
1246
  function handleHelp() {
package/dist/cli/index.js CHANGED
@@ -23,7 +23,7 @@ import * as path from 'path';
23
23
  import * as readline from 'readline';
24
24
  import { getClient } from './api-client.js';
25
25
  import { loadFeltDBConfig, createDefaultConfig, validateModel, } from './config.js';
26
- const VERSION = '0.6.11';
26
+ const VERSION = '0.6.13';
27
27
  function prompt(question) {
28
28
  const rl = readline.createInterface({
29
29
  input: process.stdin,
@@ -176,11 +176,16 @@ export function startPairingDiscoveryServer(token, port = 7799, host = '127.0.0.
176
176
  return;
177
177
  }
178
178
  response.setHeader('Content-Type', 'application/json; charset=utf-8');
179
+ const activeRuntime = runtimeSession
180
+ ? activeRegistrations().sort((left, right) => right.lastSeenAt - left.lastSeenAt)[0]
181
+ : undefined;
179
182
  response.end(JSON.stringify({
180
183
  workspaceId: token.workspaceId,
181
184
  endpoint: authorityEndpoint,
182
185
  expiresAt: token.expiresAt,
183
186
  namespace: token.namespace,
187
+ sessionId: runtimeSession?.sessionId,
188
+ runtimeInstanceId: activeRuntime?.runtimeInstanceId,
184
189
  }));
185
190
  }
186
191
  catch (error) {
@@ -11,6 +11,7 @@ import { spawn, spawnSync } from 'child_process';
11
11
  import { createProject } from './create.js';
12
12
  import { FELTDB_PACKAGE_VERSION } from './package-versions.js';
13
13
  import { configureManagedAccount } from './managed-account.js';
14
+ import { localFeltdbExecutable } from './development-handoff.js';
14
15
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
16
  function parseArgs(args) {
16
17
  const options = {
@@ -235,7 +236,7 @@ Options:
235
236
  --no-webllm Do not install WebLLM or generate the AI builder
236
237
  --capabilities <list> Choose capabilities: search, vector, or search,vector
237
238
  --no-install Skip npm install
238
- --no-start Skip npm run dev
239
+ --no-start Skip automatic feltdb dev startup
239
240
  -y, --yes Use all defaults (non-interactive mode)
240
241
  -h, --help Show this help message
241
242
  --version Show version number
@@ -314,6 +315,7 @@ Learn more: https://github.com/rkendel1/feltdb`);
314
315
  agents: options.agents,
315
316
  webllm: options.webllm,
316
317
  capabilities: options.capabilities,
318
+ showNextSteps: false,
317
319
  });
318
320
  projectCreated = true;
319
321
  if (options.runtime === 'managed') {
@@ -335,18 +337,18 @@ Learn more: https://github.com/rkendel1/feltdb`);
335
337
  }
336
338
  if (shouldStart) {
337
339
  if (!shouldInstall) {
338
- console.log(`Start after installing dependencies:\n cd ${projectName}\n npm install\n npm run dev\n`);
340
+ console.log(`Start after installing dependencies:\n cd ${projectName}\n npm install\n npm run feltdb:dev\n`);
339
341
  }
340
342
  else {
341
343
  if (options.runtime === 'self-hosted' && spawnSync('docker', ['version'], { stdio: 'ignore' }).status !== 0) {
342
344
  console.log('\n✅ Project and Docker image definition are ready.');
343
345
  console.log('Docker is not currently running, so startup was skipped.');
344
- console.log(`Start Docker Desktop, then run:\n cd ${projectName}\n npm run dev`);
346
+ console.log(`Start Docker Desktop, then run:\n cd ${projectName}\n npm run feltdb:dev`);
345
347
  console.log('Build the production application image with: docker compose build app');
346
348
  }
347
349
  else {
348
- console.log('\n🚀 Starting the application...\n');
349
- await run(npm, ['run', 'dev'], projectDir);
350
+ console.log('\n🚀 Starting your FeltDB development session...\n');
351
+ await run(localFeltdbExecutable(projectDir), ['dev'], projectDir);
350
352
  }
351
353
  }
352
354
  }
@@ -87,7 +87,7 @@ export async function createProject(options) {
87
87
  application: {
88
88
  lifecycle: 'managed',
89
89
  },
90
- applicationUrl: 'http://127.0.0.1:5173',
90
+ applicationUrl: 'http://localhost:5173/',
91
91
  capabilities: {},
92
92
  };
93
93
  if (capabilities.includes('search')) {
@@ -1657,7 +1657,7 @@ Configuration is in \`feltdb.config.json\`:
1657
1657
  "application": {
1658
1658
  "lifecycle": "managed"
1659
1659
  },
1660
- "applicationUrl": "http://127.0.0.1:5173",
1660
+ "applicationUrl": "http://localhost:5173/",
1661
1661
  "capabilities": ["${capabilities}"]
1662
1662
  }
1663
1663
  \`\`\`
@@ -1810,9 +1810,11 @@ MIT
1810
1810
  console.log(`\n✓ Development Workspace initialized`);
1811
1811
  console.log(` Workspace ID: ${workspaceDiscovery.workspaceId}`);
1812
1812
  console.log(` Location: ${path.join(projectName, '.feltdb/workspace.json')}`);
1813
- console.log(`\nNext steps:`);
1814
- console.log(` cd ${projectName}`);
1815
- console.log(` npm install`);
1816
- console.log(` npm run dev`);
1817
- console.log(`\nYour Development Workspace is ready for use!`);
1813
+ if (options.showNextSteps !== false) {
1814
+ console.log(`\nNext steps:`);
1815
+ console.log(` cd ${projectName}`);
1816
+ console.log(` npm install`);
1817
+ console.log(` npm run feltdb:dev`);
1818
+ console.log(`\nYour Development Workspace is ready for use!`);
1819
+ }
1818
1820
  }
@@ -0,0 +1,4 @@
1
+ import path from 'path';
2
+ export function localFeltdbExecutable(projectDir, platform = process.platform) {
3
+ return path.join(projectDir, 'node_modules', '.bin', platform === 'win32' ? 'feltdb.cmd' : 'feltdb');
4
+ }
@@ -38,9 +38,9 @@ export function generateDockerCompose(config) {
38
38
  - --data
39
39
  - /data/feltdb.log
40
40
  - --allow-origin
41
- - http://127.0.0.1:\${APP_PORT:-5173}
41
+ - http://localhost:\${APP_PORT:-5173}
42
42
  - --allow-origin
43
- - http://127.0.0.1:\${STUDIO_PORT:-${config.studioPort}}
43
+ - http://localhost:\${STUDIO_PORT:-${config.studioPort}}
44
44
  volumes:
45
45
  - feltdb_data:/data
46
46
  - ./feltdb.flow:/app/feltdb.flow:ro
@@ -97,7 +97,7 @@ export function generateDockerCompose(config) {
97
97
  container_name: \${COMPOSE_PROJECT_NAME}-studio
98
98
  environment:
99
99
  FELTDB_API_URL: \${FELTDB_PUBLIC_URL:-http://127.0.0.1:${config.port}}
100
- APP_URL: \${APP_PUBLIC_URL:-http://127.0.0.1:5173}
100
+ APP_URL: \${APP_PUBLIC_URL:-http://localhost:5173/}
101
101
  FELTDB_NAMESPACE: \${FELTDB_APP_ID:-${config.appId}}
102
102
  ports:
103
103
  - "\${STUDIO_PORT:-${config.studioPort}}:8000"
@@ -140,7 +140,7 @@ USER feltdb
140
140
  EXPOSE 7700
141
141
  HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=3 CMD curl -fsS http://127.0.0.1:7700/health || exit 1
142
142
  ENTRYPOINT ["/sbin/tini", "--"]
143
- CMD ["feltdb-server", "--host", "0.0.0.0", "--port", "7700", "--namespace", "${config.appId}", "--data", "/data/feltdb.log", "--allow-origin", "http://127.0.0.1:5173", "--allow-origin", "http://127.0.0.1:${config.studioPort}"]
143
+ CMD ["feltdb-server", "--host", "0.0.0.0", "--port", "7700", "--namespace", "${config.appId}", "--data", "/data/feltdb.log", "--allow-origin", "http://localhost:5173", "--allow-origin", "http://localhost:${config.studioPort}"]
144
144
  `;
145
145
  }
146
146
  export function generateStudioDockerfile(config) {
@@ -1,4 +1,4 @@
1
1
  // One release train keeps generated applications installable. The repository
2
2
  // validation script checks these values against every workspace manifest.
3
- export const FELTDB_PACKAGE_VERSION = '0.6.11';
3
+ export const FELTDB_PACKAGE_VERSION = '0.6.13';
4
4
  export const feltdbPackageRange = `^${FELTDB_PACKAGE_VERSION}`;
@@ -16,7 +16,7 @@ export { startRuntimeObservation } from './runtime-observer.js';
16
16
  export type { RuntimeObservationOptions, RuntimeObservationHandle } from './runtime-observer.js';
17
17
  export { collectEvidence, deriveFinding, candidateSourcePaths, recommendChanges, resolveRelevantSource, verificationContractFor, summarizeDefect, } from './investigation-analysis.js';
18
18
  export { RUNTIME_INVESTIGATION_COLLECTION, LEGACY_RUNTIME_INVESTIGATION_COLLECTION, transitionInvestigation, transitionRemediation, transitionVerification, createRemediationContract, classifyWorkspaceActivity, evaluateVerification, agentRemediationHandoff, RUNTIME_INVESTIGATION_INSTRUCTIONS, FELTDB_OBSERVATION_BOUNDARY, } from './runtime-investigation.js';
19
- export type { WorkspaceConnectionOptions, WorkspaceMetadata, PairingTokenData, BrowserPairingResolution, PairingDiscoveryOptions, ClientInfo, } from './workspace-connection.js';
19
+ export type { WorkspaceConnectionOptions, WorkspaceMetadata, PairingTokenData, BrowserPairingResolution, PairingDiscoveryOptions, ClientInfo, CreateRuntimeInvestigationInput, } from './workspace-connection.js';
20
20
  export { connectDevelopmentWorkspace, discoverDevelopmentWorkspace, resolvePairingCode, DevelopmentWorkspaceConnection, } from './workspace-connection.js';
21
21
  export { createWorkspaceId, isValidWorkspaceId, createDevelopmentWorkspace, updateWorkspaceTimestamp, discoverWorkspace, persistWorkspaceDiscovery, } from './workspace-identity.js';
22
22
  //# sourceMappingURL=browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/workspace/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EACV,oBAAoB,EACpB,UAAU,EACV,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,6BAA6B,EAC7B,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,SAAS,EACT,aAAa,EACb,eAAe,EACf,yBAAyB,EACzB,cAAc,EACd,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjG,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,gCAAgC,EAChC,uCAAuC,EACvC,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,UAAU,GACX,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,kBAAkB,EAClB,8BAA8B,GAC/B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/workspace/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EACV,oBAAoB,EACpB,UAAU,EACV,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,6BAA6B,EAC7B,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,SAAS,EACT,aAAa,EACb,eAAe,EACf,yBAAyB,EACzB,cAAc,EACd,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjG,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,gCAAgC,EAChC,uCAAuC,EACvC,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,UAAU,EACV,+BAA+B,GAChC,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,kBAAkB,EAClB,8BAA8B,GAC/B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC"}
@@ -21,7 +21,7 @@ export { captureRepositoryIdentity, changedPaths, repositoryChanged, trackRemedi
21
21
  export { RuntimeInvestigationSupervisor } from './investigation-supervisor.js';
22
22
  export type { SupervisorOptions, AgentHandoffArtifact } from './investigation-supervisor.js';
23
23
  export { RUNTIME_INVESTIGATION_COLLECTION, LEGACY_RUNTIME_INVESTIGATION_COLLECTION, transitionInvestigation, transitionRemediation, transitionVerification, createRemediationContract, classifyWorkspaceActivity, evaluateVerification, agentRemediationHandoff, RUNTIME_INVESTIGATION_INSTRUCTIONS, FELTDB_OBSERVATION_BOUNDARY, } from './runtime-investigation.js';
24
- export type { WorkspaceConnectionOptions, WorkspaceMetadata, PairingTokenData, BrowserPairingResolution, PairingDiscoveryOptions, ClientInfo, } from './workspace-connection.js';
24
+ export type { WorkspaceConnectionOptions, WorkspaceMetadata, PairingTokenData, BrowserPairingResolution, PairingDiscoveryOptions, ClientInfo, CreateRuntimeInvestigationInput, } from './workspace-connection.js';
25
25
  export { connectDevelopmentWorkspace, discoverDevelopmentWorkspace, resolvePairingCode, DevelopmentWorkspaceConnection, } from './workspace-connection.js';
26
26
  export { createWorkspaceId, isValidWorkspaceId, createDevelopmentWorkspace, updateWorkspaceTimestamp, discoverWorkspace, persistWorkspaceDiscovery, } from './workspace-identity.js';
27
27
  export { DevelopmentNode, getDevelopmentNode, shutdownDevelopmentNode, } from './development-node.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,YAAY,EACV,oBAAoB,EACpB,UAAU,EACV,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,6BAA6B,EAC7B,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,SAAS,EACT,aAAa,EACb,eAAe,EACf,yBAAyB,EACzB,cAAc,EACd,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjG,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,yBAAyB,EACzB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAE7F,OAAO,EACL,gCAAgC,EAChC,uCAAuC,EACvC,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,UAAU,GACX,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,kBAAkB,EAClB,8BAA8B,GAC/B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAClF,YAAY,EAAE,yBAAyB,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AAEpH,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,YAAY,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,YAAY,EACV,oBAAoB,EACpB,UAAU,EACV,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,6BAA6B,EAC7B,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,SAAS,EACT,aAAa,EACb,eAAe,EACf,yBAAyB,EACzB,cAAc,EACd,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjG,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,yBAAyB,EACzB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAE7F,OAAO,EACL,gCAAgC,EAChC,uCAAuC,EACvC,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,UAAU,EACV,+BAA+B,GAChC,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,kBAAkB,EAClB,8BAA8B,GAC/B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAClF,YAAY,EAAE,yBAAyB,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AAEpH,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,YAAY,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC"}
@@ -76,8 +76,8 @@ export async function startRuntimeObservation(options) {
76
76
  startedAt: input.startedAt,
77
77
  completedAt,
78
78
  workspaceId: connection.workspaceId,
79
- sessionId: options.sessionId,
80
- runtimeInstanceId: options.runtimeInstanceId,
79
+ sessionId: options.sessionId || connection.sessionId,
80
+ runtimeInstanceId: options.runtimeInstanceId || connection.runtimeInstanceId,
81
81
  page: scope.location ? String(scope.location.href) : undefined,
82
82
  userAgent: scope.navigator ? String(scope.navigator.userAgent) : undefined,
83
83
  correlationId: input.correlationId,
@@ -245,8 +245,8 @@ export async function startRuntimeObservation(options) {
245
245
  };
246
246
  const handle = {
247
247
  workspaceId: connection.workspaceId,
248
- sessionId: options.sessionId,
249
- runtimeInstanceId: options.runtimeInstanceId,
248
+ sessionId: options.sessionId || connection.sessionId,
249
+ runtimeInstanceId: options.runtimeInstanceId || connection.runtimeInstanceId,
250
250
  observations: () => [...emitted],
251
251
  flush,
252
252
  stop: async () => {
@@ -4,8 +4,9 @@
4
4
  * Public API for clients (browser, IDE, agent) to discover and connect
5
5
  * to a FeltDB Development Workspace.
6
6
  */
7
- import type { ClientType } from './workspace-types.js';
7
+ import type { ClientType, RuntimeInvestigation, RuntimeRequestObservation } from './workspace-types.js';
8
8
  import type { WorkspaceEventPayload } from './workspace-types.js';
9
+ import { type RuntimeObservationInput } from './runtime-observation.js';
9
10
  export interface WorkspaceConnectionOptions {
10
11
  pairingCode?: string;
11
12
  workspaceId?: string;
@@ -14,6 +15,10 @@ export interface WorkspaceConnectionOptions {
14
15
  clientType?: ClientType;
15
16
  endpoint?: string;
16
17
  discoveryEndpoint?: string;
18
+ /** Development-session identity supplied by FeltDB, never derived locally. */
19
+ sessionId?: string;
20
+ /** Runtime registration identity supplied by FeltDB, never derived locally. */
21
+ runtimeInstanceId?: string;
17
22
  auth?: {
18
23
  token: string;
19
24
  apiKey?: string;
@@ -31,12 +36,22 @@ export interface PairingTokenData {
31
36
  endpoint?: string;
32
37
  authorityEndpoint?: string;
33
38
  namespace?: string;
39
+ sessionId?: string;
40
+ runtimeInstanceId?: string;
34
41
  }
35
42
  export interface BrowserPairingResolution {
36
43
  workspaceId: string;
37
44
  endpoint: string;
38
45
  expiresAt: number;
39
46
  namespace: string;
47
+ sessionId?: string;
48
+ runtimeInstanceId?: string;
49
+ }
50
+ export interface CreateRuntimeInvestigationInput {
51
+ investigationId?: string;
52
+ observationId: string;
53
+ changeId?: string;
54
+ verificationId?: string;
40
55
  }
41
56
  export interface PairingDiscoveryOptions {
42
57
  endpoint?: string;
@@ -112,6 +127,10 @@ export declare function connectDevelopmentWorkspace(options: WorkspaceConnection
112
127
  */
113
128
  export declare class DevelopmentWorkspaceConnection {
114
129
  workspaceId: string;
130
+ /** Canonical `feltdb dev` session identity, when supplied by pairing/session configuration. */
131
+ sessionId?: string;
132
+ /** Canonical active runtime identity, when supplied by pairing/session configuration. */
133
+ runtimeInstanceId?: string;
115
134
  clientId: string;
116
135
  clientType: ClientType;
117
136
  private options;
@@ -161,6 +180,19 @@ export declare class DevelopmentWorkspaceConnection {
161
180
  * Query entities in workspace collection
162
181
  */
163
182
  query<T>(collection: string): Promise<T[]>;
183
+ /** Record a redacted canonical observation under its FeltDB observation id. */
184
+ recordRuntimeObservation(input: RuntimeObservationInput): Promise<RuntimeRequestObservation>;
185
+ getRuntimeObservation(observationId: string): Promise<RuntimeRequestObservation | null>;
186
+ /** Create the canonical shared-workspace investigation for an existing observation. */
187
+ createRuntimeInvestigation(input: CreateRuntimeInvestigationInput): Promise<RuntimeInvestigation>;
188
+ getRuntimeInvestigation(investigationId: string): Promise<RuntimeInvestigation | null>;
189
+ linkRuntimeObservationToInvestigation(observationId: string, investigationId: string): Promise<RuntimeInvestigation>;
190
+ getRuntimeInvestigationForObservation(observationId: string): Promise<RuntimeInvestigation | null>;
191
+ linkRuntimeInvestigation(input: {
192
+ investigationId: string;
193
+ changeId?: string;
194
+ verificationId?: string;
195
+ }): Promise<RuntimeInvestigation>;
164
196
  /**
165
197
  * Update entity in workspace
166
198
  */
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-connection.d.ts","sourceRoot":"","sources":["../../src/workspace/workspace-connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace-connection.d.ts","sourceRoot":"","sources":["../../src/workspace/workspace-connection.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,0BAA0B,CAAC;AAGlC,MAAM,WAAW,0BAA0B;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,+BAA+B;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CAoB5B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7F,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAsD9H;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,8BAA8B,CAAC,CA4CzC;AAYD;;;;;GAKG;AACH,qBAAa,8BAA8B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,aAAa,CAA4E;IACjG,WAAW,EAAE,MAAM,CAAK;IACxB,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,iBAAiB,CAA6B;gBAGpD,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,0BAA0B;IAUrC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBjC;;OAEG;IACH,OAAO,CAAC,eAAe;IAevB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAItC;;;;;;;;;OASG;IACH,SAAS,CAAC,CAAC,GAAG,OAAO,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,IAAI,GACjD,MAAM,IAAI;IAgBb;;;;OAIG;IACG,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAiB/E;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAIrE;;OAEG;IACG,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAIhD,+EAA+E;IACzE,wBAAwB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAoB5F,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC;IAI7F,uFAAuF;IACjF,0BAA0B,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA8BjG,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAItF,qCAAqC,CACzC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,oBAAoB,CAAC;IA2B1B,qCAAqC,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAOlG,wBAAwB,CAAC,KAAK,EAAE;QACpC,eAAe,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAYjC;;OAEG;IACG,MAAM,CAAC,CAAC,SAAS,MAAM,EAC3B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,OAAO,CAAC,IAAI,CAAC;IAUhB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,gBAAgB;YAKV,eAAe;CAiB9B"}
@@ -5,6 +5,8 @@
5
5
  * to a FeltDB Development Workspace.
6
6
  */
7
7
  import { HttpJsDb } from '../http-db.js';
8
+ import { RUNTIME_OBSERVATION_COLLECTION, createRuntimeObservation, } from './runtime-observation.js';
9
+ import { RUNTIME_INVESTIGATION_COLLECTION } from './runtime-investigation.js';
8
10
  const DEFAULT_PAIRING_DISCOVERY_ENDPOINT = 'http://127.0.0.1:7799';
9
11
  /**
10
12
  * Discover workspace from .feltdb/workspace.json
@@ -117,6 +119,8 @@ export async function resolvePairingCode(pairingCode, source = {}) {
117
119
  export async function connectDevelopmentWorkspace(options) {
118
120
  let workspaceId = options.workspaceId;
119
121
  let authorityEndpoint = options.endpoint;
122
+ let sessionId = options.sessionId;
123
+ let runtimeInstanceId = options.runtimeInstanceId;
120
124
  // Resolve pairing code to workspace ID if provided
121
125
  if (options.pairingCode && !workspaceId) {
122
126
  if (options.projectDir) {
@@ -128,6 +132,8 @@ export async function connectDevelopmentWorkspace(options) {
128
132
  });
129
133
  workspaceId = resolution.workspaceId;
130
134
  authorityEndpoint = resolution.endpoint;
135
+ sessionId = resolution.sessionId;
136
+ runtimeInstanceId = resolution.runtimeInstanceId;
131
137
  }
132
138
  }
133
139
  // Discover workspace if no ID provided
@@ -140,7 +146,7 @@ export async function connectDevelopmentWorkspace(options) {
140
146
  }
141
147
  const clientId = options.clientId || generateClientId(options.clientType);
142
148
  const clientType = options.clientType || 'other';
143
- const connection = new DevelopmentWorkspaceConnection(workspaceId, clientId, clientType, { ...options, endpoint: authorityEndpoint });
149
+ const connection = new DevelopmentWorkspaceConnection(workspaceId, clientId, clientType, { ...options, endpoint: authorityEndpoint, sessionId, runtimeInstanceId });
144
150
  await connection.connect();
145
151
  return connection;
146
152
  }
@@ -166,6 +172,8 @@ export class DevelopmentWorkspaceConnection {
166
172
  this.transport = null;
167
173
  this.unsubscribeEvents = null;
168
174
  this.workspaceId = workspaceId;
175
+ this.sessionId = options.sessionId;
176
+ this.runtimeInstanceId = options.runtimeInstanceId;
169
177
  this.clientId = clientId;
170
178
  this.clientType = clientType;
171
179
  this.options = options;
@@ -264,7 +272,12 @@ export class DevelopmentWorkspaceConnection {
264
272
  * Creates new entity in workspace collection.
265
273
  */
266
274
  async publish(collection, entity) {
267
- const id = generateEntityId();
275
+ const canonicalId = collection === RUNTIME_OBSERVATION_COLLECTION
276
+ ? entity.observationId
277
+ : collection === RUNTIME_INVESTIGATION_COLLECTION
278
+ ? entity.id
279
+ : undefined;
280
+ const id = canonicalId || generateEntityId();
268
281
  await this.requireTransport().publish({
269
282
  workspaceId: this.workspaceId,
270
283
  collection,
@@ -286,6 +299,108 @@ export class DevelopmentWorkspaceConnection {
286
299
  async query(collection) {
287
300
  return this.requireTransport().query({ workspaceId: this.workspaceId, collection });
288
301
  }
302
+ /** Record a redacted canonical observation under its FeltDB observation id. */
303
+ async recordRuntimeObservation(input) {
304
+ if (!this.sessionId || !this.runtimeInstanceId) {
305
+ throw new Error('Canonical runtime observation requires FeltDB sessionId and runtimeInstanceId');
306
+ }
307
+ const observation = createRuntimeObservation({
308
+ ...input,
309
+ workspaceId: this.workspaceId,
310
+ sessionId: this.sessionId,
311
+ runtimeInstanceId: this.runtimeInstanceId,
312
+ });
313
+ await this.requireTransport().publish({
314
+ workspaceId: this.workspaceId,
315
+ collection: RUNTIME_OBSERVATION_COLLECTION,
316
+ entityId: observation.observationId,
317
+ value: observation,
318
+ originClientId: this.clientId,
319
+ });
320
+ return observation;
321
+ }
322
+ async getRuntimeObservation(observationId) {
323
+ return this.get(RUNTIME_OBSERVATION_COLLECTION, observationId);
324
+ }
325
+ /** Create the canonical shared-workspace investigation for an existing observation. */
326
+ async createRuntimeInvestigation(input) {
327
+ const observation = await this.getRuntimeObservation(input.observationId);
328
+ if (!observation)
329
+ throw new Error(`Runtime observation not found: ${input.observationId}`);
330
+ const now = Date.now();
331
+ const investigation = {
332
+ id: input.investigationId || `inv_${now}_${Math.random().toString(36).slice(2, 9)}`,
333
+ workspaceId: this.workspaceId,
334
+ observationId: observation.observationId,
335
+ observationIds: [observation.observationId],
336
+ runtimeInstanceId: observation.runtimeInstanceId,
337
+ sessionId: observation.sessionId,
338
+ changeId: input.changeId,
339
+ verificationId: input.verificationId,
340
+ remediationContractId: '',
341
+ investigationState: 'OBSERVED',
342
+ remediationState: 'NOT_STARTED',
343
+ verificationState: 'NOT_READY',
344
+ createdAt: now,
345
+ updatedAt: now,
346
+ };
347
+ await this.requireTransport().publish({
348
+ workspaceId: this.workspaceId,
349
+ collection: RUNTIME_INVESTIGATION_COLLECTION,
350
+ entityId: investigation.id,
351
+ value: investigation,
352
+ originClientId: this.clientId,
353
+ });
354
+ return investigation;
355
+ }
356
+ async getRuntimeInvestigation(investigationId) {
357
+ return this.get(RUNTIME_INVESTIGATION_COLLECTION, investigationId);
358
+ }
359
+ async linkRuntimeObservationToInvestigation(observationId, investigationId) {
360
+ const [observation, investigation] = await Promise.all([
361
+ this.getRuntimeObservation(observationId),
362
+ this.getRuntimeInvestigation(investigationId),
363
+ ]);
364
+ if (!observation)
365
+ throw new Error(`Runtime observation not found: ${observationId}`);
366
+ if (!investigation)
367
+ throw new Error(`Runtime investigation not found: ${investigationId}`);
368
+ if (observation.workspaceId !== this.workspaceId || investigation.workspaceId !== this.workspaceId) {
369
+ throw new Error('Runtime observation and investigation must belong to the connected workspace');
370
+ }
371
+ const owner = await this.getRuntimeInvestigationForObservation(observationId);
372
+ if (owner && owner.id !== investigationId) {
373
+ throw new Error(`Runtime observation ${observationId} is already linked to ${owner.id}`);
374
+ }
375
+ const observationIds = [...new Set([
376
+ investigation.observationId,
377
+ ...(investigation.observationIds || []),
378
+ observationId,
379
+ ])];
380
+ const updatedAt = Date.now();
381
+ await this.update(RUNTIME_INVESTIGATION_COLLECTION, investigationId, {
382
+ observationIds,
383
+ updatedAt,
384
+ });
385
+ return { ...investigation, observationIds, updatedAt };
386
+ }
387
+ async getRuntimeInvestigationForObservation(observationId) {
388
+ const investigations = await this.query(RUNTIME_INVESTIGATION_COLLECTION);
389
+ return investigations.find(investigation => investigation.observationId === observationId
390
+ || investigation.observationIds?.includes(observationId)) || null;
391
+ }
392
+ async linkRuntimeInvestigation(input) {
393
+ const investigation = await this.getRuntimeInvestigation(input.investigationId);
394
+ if (!investigation)
395
+ throw new Error(`Runtime investigation not found: ${input.investigationId}`);
396
+ const updates = {
397
+ ...(input.changeId ? { changeId: input.changeId } : {}),
398
+ ...(input.verificationId ? { verificationId: input.verificationId } : {}),
399
+ updatedAt: Date.now(),
400
+ };
401
+ await this.update(RUNTIME_INVESTIGATION_COLLECTION, investigation.id, updates);
402
+ return { ...investigation, ...updates };
403
+ }
289
404
  /**
290
405
  * Update entity in workspace
291
406
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feltdb/core",
3
- "version": "0.6.11",
3
+ "version": "0.6.13",
4
4
  "description": "FeltDB Core - Application-facing database with Browser, Local, and Server runtimes. Durable state, reactive APIs.",
5
5
  "license": "MIT",
6
6
  "type": "module",