@agent-relay/dashboard-server 2.0.66-beta.0 → 2.0.66-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/server.d.ts.map +1 -1
  2. package/dist/server.js +24 -102
  3. package/dist/server.js.map +1 -1
  4. package/out/404.html +1 -1
  5. package/out/_next/static/chunks/118-b821e49d30a9f6af.js +1 -0
  6. package/out/_next/static/chunks/{202-fc0763dd7488e58f.js → 202-6cfbf8339f05e5ef.js} +1 -1
  7. package/out/_next/static/chunks/259-141fb39611979082.js +1 -0
  8. package/out/_next/static/chunks/535-cecb00f34c2ed9ba.js +1 -0
  9. package/out/_next/static/chunks/722-af84568996237c02.js +1 -0
  10. package/out/_next/static/chunks/994-e927457424324a78.js +1 -0
  11. package/out/_next/static/chunks/app/app/[[...slug]]/page-bba8842697e6192c.js +1 -0
  12. package/out/_next/static/chunks/app/{page-5c60a00d938ac40a.js → page-ba281b017e148cd6.js} +1 -1
  13. package/out/_next/static/chunks/app/providers/page-59e92abba4f8d895.js +1 -0
  14. package/out/_next/static/chunks/app/providers/setup/[provider]/page-c667546c4902f1b0.js +1 -0
  15. package/out/_next/static/css/{71615414d8909a44.css → fd373f99378195fc.css} +1 -1
  16. package/out/about.html +2 -2
  17. package/out/about.txt +1 -1
  18. package/out/app/onboarding.html +1 -1
  19. package/out/app/onboarding.txt +1 -1
  20. package/out/app.html +1 -1
  21. package/out/app.txt +2 -2
  22. package/out/blog/go-to-bed-wake-up-to-a-finished-product.html +2 -2
  23. package/out/blog/go-to-bed-wake-up-to-a-finished-product.txt +1 -1
  24. package/out/blog/let-them-cook-multi-agent-orchestration.html +2 -2
  25. package/out/blog/let-them-cook-multi-agent-orchestration.txt +1 -1
  26. package/out/blog.html +2 -2
  27. package/out/blog.txt +1 -1
  28. package/out/careers.html +2 -2
  29. package/out/careers.txt +1 -1
  30. package/out/changelog.html +2 -2
  31. package/out/changelog.txt +1 -1
  32. package/out/cloud/link.html +1 -1
  33. package/out/cloud/link.txt +2 -2
  34. package/out/complete-profile.html +2 -2
  35. package/out/complete-profile.txt +1 -1
  36. package/out/connect-repos.html +1 -1
  37. package/out/connect-repos.txt +2 -2
  38. package/out/contact.html +2 -2
  39. package/out/contact.txt +1 -1
  40. package/out/docs.html +2 -2
  41. package/out/docs.txt +1 -1
  42. package/out/history.html +1 -1
  43. package/out/history.txt +2 -2
  44. package/out/index.html +1 -1
  45. package/out/index.txt +2 -2
  46. package/out/login.html +2 -2
  47. package/out/login.txt +2 -2
  48. package/out/metrics.html +1 -1
  49. package/out/metrics.txt +2 -2
  50. package/out/pricing.html +2 -2
  51. package/out/pricing.txt +1 -1
  52. package/out/privacy.html +2 -2
  53. package/out/privacy.txt +1 -1
  54. package/out/providers/setup/claude.html +1 -1
  55. package/out/providers/setup/claude.txt +2 -2
  56. package/out/providers/setup/codex.html +1 -1
  57. package/out/providers/setup/codex.txt +2 -2
  58. package/out/providers/setup/cursor.html +1 -1
  59. package/out/providers/setup/cursor.txt +2 -2
  60. package/out/providers.html +1 -1
  61. package/out/providers.txt +2 -2
  62. package/out/security.html +2 -2
  63. package/out/security.txt +1 -1
  64. package/out/signup.html +2 -2
  65. package/out/signup.txt +2 -2
  66. package/out/terms.html +2 -2
  67. package/out/terms.txt +1 -1
  68. package/package.json +1 -1
  69. package/out/_next/static/chunks/118-4c8241b0218335de.js +0 -1
  70. package/out/_next/static/chunks/259-3bbaad41b2550936.js +0 -1
  71. package/out/_next/static/chunks/285-1cb1c0ed74f31c6c.js +0 -1
  72. package/out/_next/static/chunks/722-85011b58b9caf88b.js +0 -1
  73. package/out/_next/static/chunks/994-0ce5f1d759089504.js +0 -1
  74. package/out/_next/static/chunks/app/app/[[...slug]]/page-589620c567f85400.js +0 -1
  75. package/out/_next/static/chunks/app/providers/page-394875a22b5ba7ce.js +0 -1
  76. package/out/_next/static/chunks/app/providers/setup/[provider]/page-f058bf6696242d7b.js +0 -1
  77. /package/out/_next/static/{CRgdkwuTcA6Bt0A5Fx1wC → g8CQjGCOpPwFcSToizDmH}/_buildManifest.js +0 -0
  78. /package/out/_next/static/{CRgdkwuTcA6Bt0A5Fx1wC → g8CQjGCOpPwFcSToizDmH}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AA8DA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAmYzD,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AACvH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AA8DA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAkYzD,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AACvH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC"}
package/dist/server.js CHANGED
@@ -5,7 +5,7 @@ import path from 'path';
5
5
  import fs from 'fs';
6
6
  import os from 'os';
7
7
  import crypto from 'crypto';
8
- import { exec, execFile } from 'child_process';
8
+ import { exec } from 'child_process';
9
9
  import { fileURLToPath } from 'url';
10
10
  import { createStorageAdapter } from '@agent-relay/storage/adapter';
11
11
  import { RelayClient } from '@agent-relay/sdk';
@@ -642,9 +642,6 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
642
642
  clearInterval(bridgePingInterval);
643
643
  });
644
644
  const onlineUsers = new Map();
645
- // Track cwd per spawned agent (name -> cwd)
646
- // This is set when /api/spawn is called and included in /api/spawned responses
647
- const agentCwdMap = new Map();
648
645
  // Validation helpers for presence
649
646
  const isValidUsername = (username) => {
650
647
  if (typeof username !== 'string')
@@ -1837,7 +1834,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
1837
1834
  // Ignore errors reading processing state - it's optional
1838
1835
  }
1839
1836
  }
1840
- // Mark spawned agents with isSpawned flag, team, model, and cwd
1837
+ // Mark spawned agents with isSpawned flag, team, and model
1841
1838
  if (spawnReader) {
1842
1839
  const activeWorkers = spawnReader.getActiveWorkers();
1843
1840
  for (const worker of activeWorkers) {
@@ -1847,12 +1844,6 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
1847
1844
  if (worker.team) {
1848
1845
  agent.team = worker.team;
1849
1846
  }
1850
- // Inject cwd from agentCwdMap (set during /api/spawn) or from worker info
1851
- // (set by SpawnManager for relay-protocol spawns that bypass /api/spawn)
1852
- const workerCwd = agentCwdMap.get(worker.name) || worker.cwd;
1853
- if (workerCwd) {
1854
- agent.cwd = workerCwd;
1855
- }
1856
1847
  // Extract model from spawn command (e.g., "codex --model gpt-5.2-codex" → "gpt-5.2-codex")
1857
1848
  if (worker.cli) {
1858
1849
  // Support both `--model foo` and `--model=foo`
@@ -1881,21 +1872,6 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
1881
1872
  // Ignore errors reading workers.json
1882
1873
  }
1883
1874
  }
1884
- // Mark relay-protocol spawned agents (spawned by other agents, not via dashboard /api/spawn)
1885
- // These agents have log files in the team directory but aren't tracked by agentCwdMap
1886
- if (spawnReader) {
1887
- for (const [name, agent] of agentsMap) {
1888
- if (agent.isSpawned)
1889
- continue;
1890
- if (onlineUsers.has(name) || name === 'Dashboard')
1891
- continue;
1892
- // Check if there's a log file for this agent (indicates it was spawned)
1893
- const logPath = path.join(teamDir, `${name}.log`);
1894
- if (fs.existsSync(logPath)) {
1895
- agent.isSpawned = true;
1896
- }
1897
- }
1898
- }
1899
1875
  // Set team from teams.json for agents that don't have a team yet
1900
1876
  // This ensures agents defined in teams.json are associated with their team
1901
1877
  // even if they weren't spawned via auto-spawn
@@ -4191,9 +4167,26 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
4191
4167
  });
4192
4168
  }
4193
4169
  }
4194
- // Note: We only show spawned agents with actual PIDs in memory metrics.
4195
- // Human users and non-process entries from agents.json are excluded since
4196
- // they don't have memory usage to track.
4170
+ // Also check agents.json for registered agents that may not be spawned
4171
+ const agentsPath = path.join(teamDir, 'agents.json');
4172
+ if (fs.existsSync(agentsPath)) {
4173
+ const data = JSON.parse(fs.readFileSync(agentsPath, 'utf-8'));
4174
+ const registeredAgents = data.agents || [];
4175
+ for (const agent of registeredAgents) {
4176
+ if (!agents.find(a => a.name === agent.name)) {
4177
+ // Check if recently active (within 30 seconds)
4178
+ const lastSeen = agent.lastSeen ? new Date(agent.lastSeen).getTime() : 0;
4179
+ const isActive = Date.now() - lastSeen < 30000;
4180
+ if (isActive) {
4181
+ agents.push({
4182
+ name: agent.name,
4183
+ status: 'active',
4184
+ alertLevel: 'normal',
4185
+ });
4186
+ }
4187
+ }
4188
+ }
4189
+ }
4197
4190
  res.json({
4198
4191
  agents,
4199
4192
  system: {
@@ -4671,20 +4664,6 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
4671
4664
  const online = isAgentOnline(name);
4672
4665
  res.json({ name, online });
4673
4666
  });
4674
- /**
4675
- * PUT /api/agents/:name/cwd - Register an agent's working directory
4676
- * Used by relay-pty-orchestrator after daemon socket spawns (which bypass /api/spawn).
4677
- */
4678
- app.put('/api/agents/:name/cwd', (req, res) => {
4679
- const { name } = req.params;
4680
- const { cwd } = req.body || {};
4681
- if (!cwd || typeof cwd !== 'string') {
4682
- return res.status(400).json({ error: 'Missing required field: cwd' });
4683
- }
4684
- agentCwdMap.set(name, cwd);
4685
- broadcastData().catch(() => { });
4686
- res.json({ success: true, name, cwd });
4687
- });
4688
4667
  // ===== Agent Spawn API =====
4689
4668
  /**
4690
4669
  * POST /api/spawn - Spawn a new agent
@@ -4704,8 +4683,6 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
4704
4683
  error: 'Missing required field: name',
4705
4684
  });
4706
4685
  }
4707
- // Inherit spawner's cwd if no explicit cwd provided (for nested/agent-to-agent spawns)
4708
- const effectiveCwd = cwd || (spawnerName ? agentCwdMap.get(spawnerName) : undefined);
4709
4686
  try {
4710
4687
  let result;
4711
4688
  if (useExternalSpawnManager) {
@@ -4725,7 +4702,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
4725
4702
  cli,
4726
4703
  task,
4727
4704
  team: team || undefined,
4728
- cwd: effectiveCwd || undefined,
4705
+ cwd: cwd || undefined,
4729
4706
  interactive,
4730
4707
  shadowMode,
4731
4708
  shadowAgent,
@@ -4745,7 +4722,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
4745
4722
  task,
4746
4723
  team: team || undefined,
4747
4724
  spawnerName: spawnerName || undefined,
4748
- cwd: effectiveCwd || undefined,
4725
+ cwd: cwd || undefined,
4749
4726
  interactive,
4750
4727
  shadowMode,
4751
4728
  shadowAgent,
@@ -4758,10 +4735,6 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
4758
4735
  result = await spawner.spawn(request);
4759
4736
  }
4760
4737
  if (result.success) {
4761
- // Track cwd for this agent so /api/spawned can return it
4762
- if (effectiveCwd) {
4763
- agentCwdMap.set(name, effectiveCwd);
4764
- }
4765
4738
  // Broadcast update to WebSocket clients
4766
4739
  broadcastData().catch(() => { });
4767
4740
  // Broadcast agent_spawned event to activity feed
@@ -4785,55 +4758,6 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
4785
4758
  });
4786
4759
  }
4787
4760
  });
4788
- /**
4789
- * POST /api/repos/clone - Clone a repo into the workspace directory
4790
- * Body: { fullName: "Owner/RepoName" }
4791
- * Used by cloud API to hot-clone repos added to a running workspace.
4792
- */
4793
- app.post('/api/repos/clone', async (req, res) => {
4794
- const { fullName } = req.body;
4795
- if (!fullName || typeof fullName !== 'string' || !fullName.includes('/')) {
4796
- return res.status(400).json({ success: false, error: 'fullName is required (e.g., "Owner/RepoName")' });
4797
- }
4798
- // Validate format: "Owner/RepoName" with safe characters only
4799
- if (!/^[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+$/.test(fullName)) {
4800
- return res.status(400).json({ success: false, error: 'Invalid repository name format' });
4801
- }
4802
- const repoName = fullName.split('/').pop();
4803
- const workspaceDir = process.env.WORKSPACE_DIR || path.dirname(projectRoot || dataDir);
4804
- const targetDir = path.join(workspaceDir, repoName);
4805
- // Idempotent: skip if already cloned
4806
- if (fs.existsSync(targetDir)) {
4807
- return res.json({ success: true, message: 'Already cloned', path: targetDir });
4808
- }
4809
- const githubToken = process.env.GITHUB_TOKEN;
4810
- if (!githubToken) {
4811
- return res.status(500).json({ success: false, error: 'GITHUB_TOKEN not available' });
4812
- }
4813
- const cloneUrl = `https://x-access-token:${githubToken}@github.com/${fullName}.git`;
4814
- try {
4815
- // Use execFile to avoid shell injection
4816
- await new Promise((resolve, reject) => {
4817
- execFile('git', ['clone', cloneUrl, targetDir], { timeout: 120000 }, (error, _stdout, stderr) => {
4818
- if (error) {
4819
- reject(new Error(stderr || error.message));
4820
- }
4821
- else {
4822
- resolve();
4823
- }
4824
- });
4825
- });
4826
- // Mark directory as safe for git
4827
- execFile('git', ['config', '--global', '--add', 'safe.directory', targetDir], () => { });
4828
- res.json({ success: true, path: targetDir });
4829
- }
4830
- catch (err) {
4831
- // Sanitize error message to avoid leaking GITHUB_TOKEN embedded in the clone URL
4832
- const safeMessage = (err.message || 'Clone failed').replace(/https:\/\/[^@]+@/g, 'https://***@');
4833
- console.error('[api/repos/clone] Clone failed:', safeMessage);
4834
- res.status(500).json({ success: false, error: safeMessage });
4835
- }
4836
- });
4837
4761
  /**
4838
4762
  * POST /api/spawn/architect - Spawn an Architect agent for bridge mode
4839
4763
  * Body: { cli?: string }
@@ -4984,7 +4908,6 @@ Start by greeting the project leads and asking for status updates.`;
4984
4908
  spawnedAt: worker.spawnedAt,
4985
4909
  task: worker.task,
4986
4910
  team: worker.team,
4987
- cwd: agentCwdMap.get(worker.name) || worker.cwd,
4988
4911
  source: 'spawner',
4989
4912
  });
4990
4913
  }
@@ -5055,7 +4978,6 @@ Start by greeting the project leads and asking for status updates.`;
5055
4978
  released = await spawner.release(name);
5056
4979
  }
5057
4980
  if (released) {
5058
- agentCwdMap.delete(name);
5059
4981
  broadcastData().catch(() => { });
5060
4982
  // Broadcast agent_released event to activity feed
5061
4983
  broadcastPresence({