studiograph 1.2.0-beta.9 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/README.md +13 -18
  2. package/dist/agent/orchestrator.d.ts +56 -0
  3. package/dist/agent/orchestrator.js +167 -22
  4. package/dist/agent/orchestrator.js.map +1 -1
  5. package/dist/agent/prompts/system.md +51 -63
  6. package/dist/agent/skill-loader.js +8 -0
  7. package/dist/agent/skill-loader.js.map +1 -1
  8. package/dist/agent/skills/entity-schema.md +4 -19
  9. package/dist/agent/skills/gather-context.md +1 -1
  10. package/dist/agent/tools/graph-tools.d.ts +41 -1
  11. package/dist/agent/tools/graph-tools.js +133 -57
  12. package/dist/agent/tools/graph-tools.js.map +1 -1
  13. package/dist/agent/tools/ops-tools.js +82 -0
  14. package/dist/agent/tools/ops-tools.js.map +1 -1
  15. package/dist/agent/tools/permission-tools.d.ts +90 -0
  16. package/dist/agent/tools/permission-tools.js +207 -0
  17. package/dist/agent/tools/permission-tools.js.map +1 -0
  18. package/dist/agent/tools/sync-tools.js +2 -2
  19. package/dist/agent/tools/sync-tools.js.map +1 -1
  20. package/dist/auth/github.d.ts +1 -1
  21. package/dist/auth/github.js +21 -13
  22. package/dist/auth/github.js.map +1 -1
  23. package/dist/cli/commands/access.d.ts +11 -0
  24. package/dist/cli/commands/access.js +156 -0
  25. package/dist/cli/commands/access.js.map +1 -0
  26. package/dist/cli/commands/app.js +25 -2
  27. package/dist/cli/commands/app.js.map +1 -1
  28. package/dist/cli/commands/clear.d.ts +5 -0
  29. package/dist/cli/commands/clear.js +36 -0
  30. package/dist/cli/commands/clear.js.map +1 -0
  31. package/dist/cli/commands/clone.js +3 -3
  32. package/dist/cli/commands/clone.js.map +1 -1
  33. package/dist/cli/commands/collection.d.ts +10 -0
  34. package/dist/cli/commands/collection.js +187 -0
  35. package/dist/cli/commands/collection.js.map +1 -0
  36. package/dist/cli/commands/commit.js +2 -1
  37. package/dist/cli/commands/commit.js.map +1 -1
  38. package/dist/cli/commands/config.d.ts +100 -0
  39. package/dist/cli/commands/config.js +1 -1
  40. package/dist/cli/commands/config.js.map +1 -1
  41. package/dist/cli/commands/deploy.js +10 -1
  42. package/dist/cli/commands/deploy.js.map +1 -1
  43. package/dist/cli/commands/index.js +1 -1
  44. package/dist/cli/commands/index.js.map +1 -1
  45. package/dist/cli/commands/init.js +32 -40
  46. package/dist/cli/commands/init.js.map +1 -1
  47. package/dist/cli/commands/join.d.ts +0 -6
  48. package/dist/cli/commands/join.js +26 -111
  49. package/dist/cli/commands/join.js.map +1 -1
  50. package/dist/cli/commands/lint.js +1 -2
  51. package/dist/cli/commands/lint.js.map +1 -1
  52. package/dist/cli/commands/mcp.js +6 -5
  53. package/dist/cli/commands/mcp.js.map +1 -1
  54. package/dist/cli/commands/org.d.ts +10 -0
  55. package/dist/cli/commands/org.js +132 -0
  56. package/dist/cli/commands/org.js.map +1 -0
  57. package/dist/cli/commands/orphans.js +1 -2
  58. package/dist/cli/commands/orphans.js.map +1 -1
  59. package/dist/cli/commands/provision.js +3 -3
  60. package/dist/cli/commands/provision.js.map +1 -1
  61. package/dist/cli/commands/resolve.d.ts +8 -0
  62. package/dist/cli/commands/resolve.js +85 -0
  63. package/dist/cli/commands/resolve.js.map +1 -0
  64. package/dist/cli/commands/serve.js +55 -25
  65. package/dist/cli/commands/serve.js.map +1 -1
  66. package/dist/cli/commands/start.js +22 -205
  67. package/dist/cli/commands/start.js.map +1 -1
  68. package/dist/cli/commands/sync.js +53 -8
  69. package/dist/cli/commands/sync.js.map +1 -1
  70. package/dist/cli/commands/team.d.ts +12 -0
  71. package/dist/cli/commands/team.js +185 -0
  72. package/dist/cli/commands/team.js.map +1 -0
  73. package/dist/cli/index.js +41 -34
  74. package/dist/cli/index.js.map +1 -1
  75. package/dist/cli/scaffolding.d.ts +5 -3
  76. package/dist/cli/scaffolding.js +191 -97
  77. package/dist/cli/scaffolding.js.map +1 -1
  78. package/dist/cli/setup-wizard.js +20 -10
  79. package/dist/cli/setup-wizard.js.map +1 -1
  80. package/dist/cli/sync-review-interactive.js +1 -1
  81. package/dist/cli/sync-review-interactive.js.map +1 -1
  82. package/dist/core/graph.d.ts +5 -10
  83. package/dist/core/graph.js +84 -85
  84. package/dist/core/graph.js.map +1 -1
  85. package/dist/core/migration-runner.d.ts +42 -0
  86. package/dist/core/migration-runner.js +232 -0
  87. package/dist/core/migration-runner.js.map +1 -0
  88. package/dist/core/migration-types.d.ts +101 -0
  89. package/dist/core/migration-types.js +21 -0
  90. package/dist/core/migration-types.js.map +1 -0
  91. package/dist/core/migrations/20260219-formalize-memory-location.d.ts +2 -0
  92. package/dist/core/migrations/20260219-formalize-memory-location.js +35 -0
  93. package/dist/core/migrations/20260219-formalize-memory-location.js.map +1 -0
  94. package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +12 -0
  95. package/dist/core/migrations/20260220-add-workspace-metadata.js +65 -0
  96. package/dist/core/migrations/20260220-add-workspace-metadata.js.map +1 -0
  97. package/dist/core/migrations/20260220-add-workspace-readme.d.ts +11 -0
  98. package/dist/core/migrations/20260220-add-workspace-readme.js +82 -0
  99. package/dist/core/migrations/20260220-add-workspace-readme.js.map +1 -0
  100. package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +9 -0
  101. package/dist/core/migrations/20260220-migrate-yaml-to-json.js +64 -0
  102. package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +1 -0
  103. package/dist/core/migrations/index.d.ts +11 -0
  104. package/dist/core/migrations/index.js +23 -0
  105. package/dist/core/migrations/index.js.map +1 -0
  106. package/dist/core/types.d.ts +19 -34
  107. package/dist/core/types.js +3 -21
  108. package/dist/core/types.js.map +1 -1
  109. package/dist/core/user-config.d.ts +27 -0
  110. package/dist/core/user-config.js +51 -0
  111. package/dist/core/user-config.js.map +1 -1
  112. package/dist/core/validation.d.ts +978 -2182
  113. package/dist/core/validation.js +242 -397
  114. package/dist/core/validation.js.map +1 -1
  115. package/dist/core/workspace-manager.d.ts +32 -31
  116. package/dist/core/workspace-manager.js +171 -186
  117. package/dist/core/workspace-manager.js.map +1 -1
  118. package/dist/core/workspace.d.ts +0 -5
  119. package/dist/core/workspace.js +33 -101
  120. package/dist/core/workspace.js.map +1 -1
  121. package/dist/lib/lib/utils.d.ts +2 -0
  122. package/dist/lib/lib/utils.js +6 -0
  123. package/dist/lib/lib/utils.js.map +1 -0
  124. package/dist/mcp/tools.js +13 -13
  125. package/dist/mcp/tools.js.map +1 -1
  126. package/dist/server/chrome/chrome.css +562 -0
  127. package/dist/server/chrome/chrome.js +540 -0
  128. package/dist/server/index.js +163 -10
  129. package/dist/server/index.js.map +1 -1
  130. package/dist/server/plugin-loader.d.ts +7 -0
  131. package/dist/server/plugin-loader.js +9 -1
  132. package/dist/server/plugin-loader.js.map +1 -1
  133. package/dist/server/routes/chat.d.ts +3 -2
  134. package/dist/server/routes/chat.js +67 -16
  135. package/dist/server/routes/chat.js.map +1 -1
  136. package/dist/server/routes/git-api.d.ts +9 -0
  137. package/dist/server/routes/git-api.js +82 -0
  138. package/dist/server/routes/git-api.js.map +1 -0
  139. package/dist/server/routes/graph-api.d.ts +2 -2
  140. package/dist/server/routes/graph-api.js +267 -3
  141. package/dist/server/routes/graph-api.js.map +1 -1
  142. package/dist/server/routes/permissions-api.d.ts +9 -0
  143. package/dist/server/routes/permissions-api.js +176 -0
  144. package/dist/server/routes/permissions-api.js.map +1 -0
  145. package/dist/server/routes/workspace-api.d.ts +9 -0
  146. package/dist/server/routes/workspace-api.js +283 -0
  147. package/dist/server/routes/workspace-api.js.map +1 -0
  148. package/dist/services/assets/base.d.ts +2 -2
  149. package/dist/services/assets/base.js +4 -4
  150. package/dist/services/assets/base.js.map +1 -1
  151. package/dist/services/assets/index.d.ts +6 -6
  152. package/dist/services/assets/index.js +12 -12
  153. package/dist/services/assets/index.js.map +1 -1
  154. package/dist/services/git.d.ts +35 -0
  155. package/dist/services/git.js +93 -0
  156. package/dist/services/git.js.map +1 -1
  157. package/dist/services/github-provisioner.js +1 -2
  158. package/dist/services/github-provisioner.js.map +1 -1
  159. package/dist/services/github-service.d.ts +99 -0
  160. package/dist/services/github-service.js +310 -0
  161. package/dist/services/github-service.js.map +1 -0
  162. package/dist/services/markdown.js +4 -9
  163. package/dist/services/markdown.js.map +1 -1
  164. package/dist/services/memory-service.d.ts +4 -0
  165. package/dist/services/memory-service.js +13 -1
  166. package/dist/services/memory-service.js.map +1 -1
  167. package/dist/services/sync/commit.d.ts +2 -0
  168. package/dist/services/sync/commit.js +21 -6
  169. package/dist/services/sync/commit.js.map +1 -1
  170. package/dist/services/sync/graphrag-indexer.js +2 -2
  171. package/dist/services/sync/graphrag-indexer.js.map +1 -1
  172. package/dist/utils/git.d.ts +5 -0
  173. package/dist/utils/git.js +10 -0
  174. package/dist/utils/git.js.map +1 -1
  175. package/dist/utils/merge-resolver.d.ts +33 -8
  176. package/dist/utils/merge-resolver.js +157 -55
  177. package/dist/utils/merge-resolver.js.map +1 -1
  178. package/dist/utils/preflight.d.ts +1 -1
  179. package/dist/utils/preflight.js +1 -1
  180. package/dist/web/_app/env.js +1 -0
  181. package/dist/web/_app/immutable/assets/0.CDbX4Cwz.css +1 -0
  182. package/dist/web/_app/immutable/assets/2.DRHi7ABa.css +1 -0
  183. package/dist/web/_app/immutable/assets/3.BJy7pVXi.css +1 -0
  184. package/dist/web/_app/immutable/assets/4.Ad16uh9o.css +1 -0
  185. package/dist/web/_app/immutable/assets/5.BhKgiXd2.css +1 -0
  186. package/dist/web/_app/immutable/assets/6.CeHKR5ZY.css +1 -0
  187. package/dist/web/_app/immutable/assets/AppShell.CXdE5aqF.css +1 -0
  188. package/dist/web/_app/immutable/assets/ChatPanel.RFD5GGYI.css +1 -0
  189. package/dist/web/_app/immutable/assets/editor.CPAf2SRV.css +1 -0
  190. package/dist/web/_app/immutable/chunks/3_5VIr68.js +1 -0
  191. package/dist/web/_app/immutable/chunks/4QY4j-jX.js +1 -0
  192. package/dist/web/_app/immutable/chunks/B0nldqWF.js +23 -0
  193. package/dist/web/_app/immutable/chunks/BB_5th5W.js +3383 -0
  194. package/dist/web/_app/immutable/chunks/BButMJ6M.js +1 -0
  195. package/dist/web/_app/immutable/chunks/BiubvAUI.js +2 -0
  196. package/dist/web/_app/immutable/chunks/CAXuTUkp.js +1 -0
  197. package/dist/web/_app/immutable/chunks/CUzqHQY_.js +1 -0
  198. package/dist/web/_app/immutable/chunks/CYrVHOHA.js +1 -0
  199. package/dist/web/_app/immutable/chunks/CqkleIqs.js +1 -0
  200. package/dist/web/_app/immutable/chunks/DPmdIe6Y.js +1 -0
  201. package/dist/web/_app/immutable/chunks/Dh_H7Owr.js +18 -0
  202. package/dist/web/_app/immutable/chunks/DnlgZ_Tk.js +5 -0
  203. package/dist/web/_app/immutable/chunks/DsERsGWg.js +64 -0
  204. package/dist/web/_app/immutable/chunks/DtVH--hH.js +6 -0
  205. package/dist/web/_app/immutable/chunks/F20aIBpJ.js +1 -0
  206. package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +1 -0
  207. package/dist/web/_app/immutable/chunks/WSUKABI_.js +1 -0
  208. package/dist/web/_app/immutable/chunks/YFT1281h.js +2 -0
  209. package/dist/web/_app/immutable/chunks/aosHekRC.js +1 -0
  210. package/dist/web/_app/immutable/chunks/fwnBoL5x.js +1 -0
  211. package/dist/web/_app/immutable/chunks/hHxe9oXh.js +1 -0
  212. package/dist/web/_app/immutable/chunks/nZKqDQ0w.js +6 -0
  213. package/dist/web/_app/immutable/entry/app.B6Ngvu5P.js +2 -0
  214. package/dist/web/_app/immutable/entry/start.NykKAKQv.js +1 -0
  215. package/dist/web/_app/immutable/nodes/0.DQ5KdeNU.js +1 -0
  216. package/dist/web/_app/immutable/nodes/1.BR6DZ9ov.js +1 -0
  217. package/dist/web/_app/immutable/nodes/2.COSjVZ_C.js +1 -0
  218. package/dist/web/_app/immutable/nodes/3.B9r1XIlO.js +1 -0
  219. package/dist/web/_app/immutable/nodes/4.p-c6hlFf.js +16 -0
  220. package/dist/web/_app/immutable/nodes/5.CPc-Bqal.js +4 -0
  221. package/dist/web/_app/immutable/nodes/6.jJ67YnBc.js +2 -0
  222. package/dist/web/_app/version.json +1 -0
  223. package/dist/web/index.html +43 -0
  224. package/package.json +21 -3
  225. package/dist/agent/skills/bundled/enrich-entities.md +0 -124
  226. package/dist/agent/skills/bundled/gather-context.md +0 -46
@@ -8,20 +8,31 @@
8
8
  * - App plugins mounted via PluginLoader
9
9
  */
10
10
  import Fastify from 'fastify';
11
+ import cookie from '@fastify/cookie';
11
12
  import cors from '@fastify/cors';
13
+ import { randomBytes } from 'crypto';
14
+ import { existsSync, readFileSync, createReadStream, statSync } from 'fs';
15
+ import { join, extname } from 'path';
12
16
  import { AgentOrchestrator } from '../agent/orchestrator.js';
13
- import { PluginLoader } from './plugin-loader.js';
17
+ import { PluginLoader, MIME_TYPES } from './plugin-loader.js';
14
18
  import { registerGraphApiRoutes } from './routes/graph-api.js';
15
19
  import { registerChatRoutes } from './routes/chat.js';
16
20
  import { registerWebhookRoutes } from './routes/webhook.js';
21
+ import { registerWorkspaceApiRoutes } from './routes/workspace-api.js';
22
+ import { registerPermissionsApiRoutes } from './routes/permissions-api.js';
23
+ import { MemoryService } from '../services/memory-service.js';
17
24
  /**
18
- * Auth middleware — validates Authorization: Bearer <key> header.
25
+ * Auth middleware — validates Authorization: Bearer <key> header or web session cookie.
19
26
  * Applied to all write-adjacent or sensitive routes.
20
27
  */
21
- function requireApiKey(apiKeys) {
28
+ function requireApiKey(apiKeys, webSessionToken) {
22
29
  return async (req, reply) => {
23
30
  if (apiKeys.length === 0)
24
31
  return; // no keys configured — open (dev mode)
32
+ // Accept web session cookie from the built-in SPA
33
+ const sessionCookie = req.cookies?.['__sg_session'];
34
+ if (sessionCookie === webSessionToken)
35
+ return;
25
36
  const auth = req.headers['authorization'];
26
37
  const token = auth?.startsWith('Bearer ') ? auth.slice(7) : undefined;
27
38
  if (!token || !apiKeys.includes(token)) {
@@ -30,11 +41,21 @@ function requireApiKey(apiKeys) {
30
41
  };
31
42
  }
32
43
  export async function createServer(config) {
33
- const fastify = Fastify({ logger: true });
44
+ const isRemote = !!process.env.STUDIOGRAPH_CONFIG_REPO;
45
+ const fastify = Fastify({
46
+ logger: isRemote
47
+ ? true
48
+ : { level: 'warn' },
49
+ });
34
50
  // CORS
35
51
  await fastify.register(cors, {
36
52
  origin: true,
53
+ credentials: true,
37
54
  });
55
+ // Cookie support for web UI session auth
56
+ await fastify.register(cookie);
57
+ // Generate a per-process session token for the built-in web UI
58
+ const webSessionToken = randomBytes(32).toString('hex');
38
59
  // Parse raw body for webhook HMAC validation
39
60
  fastify.addContentTypeParser('application/json', { parseAs: 'buffer' }, (req, body, done) => {
40
61
  try {
@@ -46,15 +67,42 @@ export async function createServer(config) {
46
67
  }
47
68
  });
48
69
  // Auth hook — protect chat and webhook routes
49
- const authHook = requireApiKey(config.apiKeys);
70
+ const authHook = requireApiKey(config.apiKeys, webSessionToken);
50
71
  fastify.addHook('preHandler', async (req, reply) => {
51
- const protectedPaths = ['/api/chat', '/webhooks/'];
52
- if (protectedPaths.some(p => req.url.startsWith(p))) {
72
+ const protectedPaths = ['/api/chat', '/webhooks/', '/api/permissions'];
73
+ const protectedPostPaths = ['/api/commit', '/api/push', '/api/pull', '/api/revert'];
74
+ const isWriteRoute = req.method === 'PUT' && req.url.startsWith('/api/repos/');
75
+ const isRepoPost = req.method === 'POST' && req.url.match(/^\/api\/repos\/[^/]+\/(publish|revert)/);
76
+ const isProtectedPost = req.method === 'POST' && protectedPostPaths.some(p => req.url.startsWith(p));
77
+ if (isWriteRoute || isProtectedPost || isRepoPost || protectedPaths.some(p => req.url.startsWith(p))) {
53
78
  await authHook(req, reply);
54
79
  }
55
80
  });
56
81
  // Register graph API routes (unauthenticated read-only)
57
82
  await registerGraphApiRoutes(fastify, config.workspaceManager);
83
+ // Register workspace API routes (git operations)
84
+ await registerWorkspaceApiRoutes(fastify, config.workspaceManager, config.gitUser);
85
+ // Register permissions API routes (GitHub org/team/repo access)
86
+ await registerPermissionsApiRoutes(fastify, config.workspaceConfig);
87
+ // Serve chrome assets (shared header/footer for app editors)
88
+ const chromeDir = join(import.meta.dirname, 'chrome');
89
+ if (existsSync(chromeDir)) {
90
+ const CHROME_MIME = { '.js': 'application/javascript', '.css': 'text/css' };
91
+ fastify.get('/api/chrome/:file', async (req, reply) => {
92
+ const file = req.params.file;
93
+ if (file.includes('..') || file.includes('/')) {
94
+ return reply.status(400).send({ error: 'Invalid path' });
95
+ }
96
+ const filePath = join(chromeDir, file);
97
+ if (!existsSync(filePath) || !statSync(filePath).isFile()) {
98
+ return reply.status(404).send({ error: 'Not found' });
99
+ }
100
+ const ext = extname(filePath).toLowerCase();
101
+ reply.type(CHROME_MIME[ext] || 'application/octet-stream');
102
+ reply.header('Cache-Control', 'public, max-age=300');
103
+ return reply.send(createReadStream(filePath));
104
+ });
105
+ }
58
106
  // Discover installed apps and collect their skill/tool dirs
59
107
  const loader = new PluginLoader();
60
108
  const manifests = loader.loadApps(config.appsDir);
@@ -68,22 +116,60 @@ export async function createServer(config) {
68
116
  if (toolsDir)
69
117
  appToolsDirs.push(toolsDir);
70
118
  }
71
- // Initialize agent — non-fatal so the server can still serve graph API and apps
119
+ // Initialize memory service and agent — non-fatal so the server can still serve graph API and apps
120
+ const memoryService = new MemoryService();
121
+ let agent = null;
72
122
  try {
73
- const agent = new AgentOrchestrator({
123
+ const recentMemory = memoryService.loadRecentMemory();
124
+ agent = new AgentOrchestrator({
74
125
  workspacePath: config.workspacePath,
75
126
  workspaceConfig: config.workspaceConfig,
76
127
  gitUser: config.gitUser,
77
128
  skillsDirs: appSkillsDirs,
78
129
  toolsDirs: appToolsDirs,
130
+ recentMemory,
79
131
  });
80
- await registerChatRoutes(fastify, agent);
132
+ await registerChatRoutes(fastify, agent, memoryService);
81
133
  }
82
134
  catch (err) {
83
135
  fastify.log.warn(`Agent not available: ${err.message ?? err} — chat routes disabled`);
84
136
  }
85
137
  // GitHub webhook route
86
138
  await registerWebhookRoutes(fastify, config.workspaceManager, config.webhookSecret);
139
+ // GET /api/apps — list installed app manifests with resolved entity type names
140
+ const resolvedApps = manifests.map(m => {
141
+ let entityTypes = [];
142
+ try {
143
+ const etPath = join(config.appsDir, m.name, m.entityTypes);
144
+ if (existsSync(etPath)) {
145
+ const raw = JSON.parse(readFileSync(etPath, 'utf-8'));
146
+ if (Array.isArray(raw)) {
147
+ entityTypes = raw.map((item) => item.name).filter(Boolean);
148
+ }
149
+ }
150
+ }
151
+ catch {
152
+ // gracefully degrade — return empty array
153
+ }
154
+ return { name: m.name, version: m.version, description: m.description, mountPath: m.mountPath, entityTypes };
155
+ });
156
+ fastify.get('/api/apps', async (_req, reply) => {
157
+ return reply.send(resolvedApps);
158
+ });
159
+ // GET /api/workspace — workspace metadata (name, etc.)
160
+ fastify.get('/api/workspace', async (_req, reply) => {
161
+ return reply.send({ name: config.workspaceConfig.team_name });
162
+ });
163
+ // DELETE /api/memory — clear all agent memory files
164
+ fastify.delete('/api/memory', async (_req, reply) => {
165
+ const count = memoryService.clear();
166
+ return reply.send({ cleared: count });
167
+ });
168
+ // DELETE /api/sessions — clear all saved agent sessions
169
+ fastify.delete('/api/sessions', async (_req, reply) => {
170
+ const count = agent?.clearSessions() ?? 0;
171
+ return reply.send({ cleared: count });
172
+ });
87
173
  // Mount app plugins
88
174
  for (const manifest of manifests) {
89
175
  try {
@@ -97,6 +183,73 @@ export async function createServer(config) {
97
183
  fastify.log.error(err, `Failed to mount app "${manifest.name}"`);
98
184
  }
99
185
  }
186
+ // Serve web UI static files from dist/web/ with SPA fallback
187
+ const webDir = join(import.meta.dirname, '..', 'web');
188
+ if (existsSync(webDir)) {
189
+ const indexPath = join(webDir, 'index.html');
190
+ // SPA fallback for app routes: if an app plugin returns a JSON error for a
191
+ // browser GET request, serve the SPA instead. This happens when the browser
192
+ // refreshes a URL like /documents/document/doc-123 — the app's greedy route
193
+ // catches it but fails because the params don't match its expectations.
194
+ // Read fresh from disk each time so rebuilds take effect without server restart.
195
+ const readIndexHtml = () => readFileSync(indexPath);
196
+ // Set session cookie on HTML responses so the web UI can call protected routes
197
+ fastify.addHook('onSend', async (request, reply, payload) => {
198
+ if (reply.sent)
199
+ return payload;
200
+ const ct = reply.getHeader('content-type');
201
+ if (typeof ct === 'string' && ct.includes('text/html') && !request.cookies?.['__sg_session']) {
202
+ reply.setCookie('__sg_session', webSessionToken, {
203
+ path: '/',
204
+ httpOnly: true,
205
+ sameSite: 'strict',
206
+ secure: request.headers['x-forwarded-proto'] === 'https',
207
+ });
208
+ }
209
+ return payload;
210
+ });
211
+ fastify.addHook('onSend', async (request, reply, payload) => {
212
+ if (reply.sent)
213
+ return payload;
214
+ const ct = reply.getHeader('content-type');
215
+ if (request.method === 'GET' &&
216
+ reply.statusCode >= 400 &&
217
+ request.headers.accept?.includes('text/html') &&
218
+ typeof ct === 'string' && ct.includes('application/json')) {
219
+ reply.removeHeader('content-length');
220
+ reply.code(200).type('text/html');
221
+ return readIndexHtml();
222
+ }
223
+ return payload;
224
+ });
225
+ // Use setNotFoundHandler so app plugins and API routes take priority
226
+ fastify.setNotFoundHandler(async (req, reply) => {
227
+ const urlPath = req.url.split('?')[0];
228
+ const filePath = urlPath === '/' ? '/index.html' : urlPath;
229
+ const fullPath = join(webDir, filePath);
230
+ // Serve the file if it exists (and is a file, not directory)
231
+ if (existsSync(fullPath) && statSync(fullPath).isFile()) {
232
+ if (fullPath.includes('..')) {
233
+ return reply.status(400).send({ error: 'Invalid path' });
234
+ }
235
+ const ext = extname(fullPath).toLowerCase();
236
+ const contentType = MIME_TYPES[ext] || 'application/octet-stream';
237
+ reply.type(contentType);
238
+ return reply.send(createReadStream(fullPath));
239
+ }
240
+ // SPA fallback — serve index.html for client-side routing.
241
+ // Only for GET requests — POST/PUT/DELETE to unknown routes should return 404 JSON.
242
+ // Skip for paths that look like static assets (have a file extension like .js, .css, etc.)
243
+ // to avoid returning HTML when the browser expects JS/CSS, which would cause silent errors.
244
+ const hasFileExt = extname(urlPath).length > 1;
245
+ if (req.method === 'GET' && !hasFileExt && existsSync(indexPath)) {
246
+ reply.type('text/html');
247
+ return reply.send(createReadStream(indexPath));
248
+ }
249
+ return reply.status(404).send({ error: 'Not found' });
250
+ });
251
+ fastify.log.info('Web UI enabled — serving from dist/web/');
252
+ }
100
253
  return fastify;
101
254
  }
102
255
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,13 @@
8
8
  import type { FastifyInstance } from 'fastify';
9
9
  import { WorkspaceManager } from '../core/workspace-manager.js';
10
10
  import { GitUser } from '../services/git.js';
11
+ /**
12
+ * A require() function rooted at the server's module context.
13
+ * Plugins use this to resolve packages (e.g. playwright) from the
14
+ * server's node_modules, since their own deployed location lacks them.
15
+ */
16
+ export declare const serverRequire: NodeJS.Require;
17
+ export declare const MIME_TYPES: Record<string, string>;
11
18
  export interface AppManifest {
12
19
  name: string;
13
20
  version: string;
@@ -7,7 +7,14 @@
7
7
  */
8
8
  import { existsSync, readdirSync, readFileSync, createReadStream } from 'fs';
9
9
  import { join, extname } from 'path';
10
- const MIME_TYPES = {
10
+ import { createRequire } from 'node:module';
11
+ /**
12
+ * A require() function rooted at the server's module context.
13
+ * Plugins use this to resolve packages (e.g. playwright) from the
14
+ * server's node_modules, since their own deployed location lacks them.
15
+ */
16
+ export const serverRequire = createRequire(import.meta.url);
17
+ export const MIME_TYPES = {
11
18
  '.html': 'text/html',
12
19
  '.css': 'text/css',
13
20
  '.js': 'application/javascript',
@@ -122,6 +129,7 @@ export class PluginLoader {
122
129
  gitUser: opts.gitUser,
123
130
  appsDir: appDir,
124
131
  staticDir,
132
+ serverRequire,
125
133
  });
126
134
  // Mount static file handler if app has a static/ directory
127
135
  if (staticDir) {
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/server/plugin-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/server/plugin-loader.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,11 @@
2
2
  * Chat / Agent SSE routes
3
3
  *
4
4
  * POST /api/chat — send a message, await full response
5
- * GET /api/chat/stream — SSE stream of agent events (future)
5
+ * POST /api/chat/stream — SSE stream of agent events with session persistence
6
6
  *
7
7
  * Single agent instance per server process (single-user v1).
8
8
  */
9
9
  import type { FastifyInstance } from 'fastify';
10
10
  import { AgentOrchestrator } from '../../agent/orchestrator.js';
11
- export declare function registerChatRoutes(fastify: FastifyInstance, agent: AgentOrchestrator): Promise<void>;
11
+ import type { MemoryService } from '../../services/memory-service.js';
12
+ export declare function registerChatRoutes(fastify: FastifyInstance, agent: AgentOrchestrator, memoryService?: MemoryService): Promise<void>;
@@ -2,11 +2,11 @@
2
2
  * Chat / Agent SSE routes
3
3
  *
4
4
  * POST /api/chat — send a message, await full response
5
- * GET /api/chat/stream — SSE stream of agent events (future)
5
+ * POST /api/chat/stream — SSE stream of agent events with session persistence
6
6
  *
7
7
  * Single agent instance per server process (single-user v1).
8
8
  */
9
- export async function registerChatRoutes(fastify, agent) {
9
+ export async function registerChatRoutes(fastify, agent, memoryService) {
10
10
  // POST /api/chat — send message, get full response
11
11
  fastify.post('/api/chat', async (req, reply) => {
12
12
  const { message } = req.body;
@@ -22,11 +22,20 @@ export async function registerChatRoutes(fastify, agent) {
22
22
  return reply.status(500).send({ error: err.message || 'Agent error' });
23
23
  }
24
24
  });
25
- // GET /api/chat/stream — SSE stream of agent events
26
- fastify.get('/api/chat/stream', async (req, reply) => {
27
- const { message } = req.query;
28
- if (!message || !message.trim()) {
29
- return reply.status(400).send({ error: 'message query param is required' });
25
+ // POST /api/chat/stream — SSE stream of agent events
26
+ fastify.post('/api/chat/stream', async (req, reply) => {
27
+ const { message, context, sessionId, history } = req.body;
28
+ if (!message || typeof message !== 'string' || !message.trim()) {
29
+ return reply.status(400).send({ error: 'message is required' });
30
+ }
31
+ // Switch agent to the requested session (restores prior conversation)
32
+ if (sessionId) {
33
+ try {
34
+ await agent.switchSession(sessionId, history);
35
+ }
36
+ catch (err) {
37
+ fastify.log.warn(`Session switch failed: ${err.message}`);
38
+ }
30
39
  }
31
40
  // Set SSE headers
32
41
  reply.raw.setHeader('Content-Type', 'text/event-stream');
@@ -37,27 +46,69 @@ export async function registerChatRoutes(fastify, agent) {
37
46
  reply.raw.write(`data: ${JSON.stringify(data)}\n\n`);
38
47
  };
39
48
  try {
49
+ // Hook highlight callback so highlight_entities tool sends SSE events
50
+ agent.setHighlightCallback((ids) => {
51
+ sendEvent({ type: 'highlight', entityIds: ids });
52
+ });
53
+ // Hook mutation callback so create/update/delete send SSE events
54
+ agent.setMutationCallback((m) => {
55
+ sendEvent({ type: 'mutation', action: m.action, repo: m.repo, entityType: m.entityType, entityId: m.entityId });
56
+ });
40
57
  // Subscribe to agent events before sending message
41
- const unsubscribe = agent.agent?.subscribe?.((event) => {
58
+ let hasContent = false;
59
+ let needsTurnSep = false;
60
+ const rawAgent = agent.getAgent();
61
+ const unsubscribe = rawAgent.subscribe((event) => {
42
62
  if (event.type === 'message_update') {
43
63
  const msgEvent = event.assistantMessageEvent;
44
64
  if (msgEvent?.type === 'text_delta') {
65
+ if (needsTurnSep && hasContent) {
66
+ sendEvent({ type: 'token', text: '\n\n' });
67
+ }
68
+ needsTurnSep = false;
69
+ hasContent = true;
45
70
  sendEvent({ type: 'token', text: msgEvent.delta });
46
71
  }
47
72
  }
48
- else if (event.type === 'tool_start') {
49
- sendEvent({ type: 'tool_start', name: event.name });
50
- }
51
- else if (event.type === 'tool_end') {
52
- sendEvent({ type: 'tool_end', name: event.name });
73
+ else if (event.type === 'message_end') {
74
+ if (event.message?.role === 'assistant') {
75
+ needsTurnSep = true;
76
+ // Extract tool names from the completed assistant message
77
+ for (const block of event.message.content ?? []) {
78
+ if (block.type === 'toolCall' && block.name) {
79
+ sendEvent({ type: 'tool_start', name: block.name });
80
+ }
81
+ }
82
+ }
53
83
  }
54
84
  });
55
- const response = await agent.chat(message);
56
- if (unsubscribe)
57
- unsubscribe();
85
+ const fullMessage = context
86
+ ? `[Currently viewing: ${context}]\n\n${message}`
87
+ : message;
88
+ const response = await agent.chat(fullMessage);
89
+ unsubscribe();
90
+ agent.setHighlightCallback(null);
91
+ agent.setMutationCallback(null);
92
+ // Persist session to disk after response
93
+ if (sessionId) {
94
+ try {
95
+ agent.saveSession();
96
+ }
97
+ catch { /* non-fatal */ }
98
+ }
99
+ // Write brief entry to today's daily memory
100
+ if (memoryService && response.content) {
101
+ try {
102
+ const snippet = `User: ${message.slice(0, 100)}${message.length > 100 ? '…' : ''}\nAgent: ${response.content.slice(0, 200)}${response.content.length > 200 ? '…' : ''}`;
103
+ memoryService.saveSessionSummary(snippet, { source: 'web-chat', sessionId });
104
+ }
105
+ catch { /* non-fatal */ }
106
+ }
58
107
  sendEvent({ type: 'done', message: response.content });
59
108
  }
60
109
  catch (err) {
110
+ agent.setHighlightCallback(null);
111
+ agent.setMutationCallback(null);
61
112
  sendEvent({ type: 'error', message: err.message || 'Agent error' });
62
113
  }
63
114
  reply.raw.end();
@@ -1 +1 @@
1
- {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/server/routes/chat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/server/routes/chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Git API routes
3
+ *
4
+ * Status, commit, and pull operations across workspace repos.
5
+ * All routes are protected by auth.
6
+ */
7
+ import type { FastifyInstance } from 'fastify';
8
+ import { WorkspaceManager } from '../../core/workspace-manager.js';
9
+ export declare function registerGitApiRoutes(fastify: FastifyInstance, workspaceManager: WorkspaceManager, workspacePath: string): Promise<void>;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Git API routes
3
+ *
4
+ * Status, commit, and pull operations across workspace repos.
5
+ * All routes are protected by auth.
6
+ */
7
+ import { spawnSync } from 'child_process';
8
+ import { commitRepos } from '../../services/sync/commit.js';
9
+ export async function registerGitApiRoutes(fastify, workspaceManager, workspacePath) {
10
+ // GET /api/git/status — per-repo git status
11
+ fastify.get('/api/git/status', async (_req, reply) => {
12
+ const repoConfigs = workspaceManager.getAllRepoConfigs();
13
+ const statuses = [];
14
+ for (const config of repoConfigs) {
15
+ try {
16
+ const graph = workspaceManager.getGraph(config.name);
17
+ const git = graph.gitService;
18
+ if (!git)
19
+ continue;
20
+ const status = git.getStatus();
21
+ // Get current branch
22
+ const branchResult = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
23
+ cwd: config.path,
24
+ encoding: 'utf-8',
25
+ });
26
+ const branch = branchResult.stdout?.trim() || 'main';
27
+ statuses.push({
28
+ repo: config.name,
29
+ branch,
30
+ ...status,
31
+ totalChanges: status.modified.length + status.added.length + status.deleted.length + status.untracked.length,
32
+ });
33
+ }
34
+ catch {
35
+ // Skip repos that don't have git
36
+ }
37
+ }
38
+ return reply.send(statuses);
39
+ });
40
+ // POST /api/git/commit — commit all repos
41
+ fastify.post('/api/git/commit', async (req, reply) => {
42
+ const { message } = req.body ?? {};
43
+ try {
44
+ await commitRepos(workspacePath, undefined, {
45
+ messagePrefix: message,
46
+ });
47
+ return reply.send({ success: true });
48
+ }
49
+ catch (err) {
50
+ return reply.status(500).send({ error: err.message });
51
+ }
52
+ });
53
+ // POST /api/git/pull — pull all repos
54
+ fastify.post('/api/git/pull', async (_req, reply) => {
55
+ const repoConfigs = workspaceManager.getAllRepoConfigs();
56
+ const results = [];
57
+ for (const config of repoConfigs) {
58
+ try {
59
+ const result = spawnSync('git', ['pull', '--rebase', '--autostash'], {
60
+ cwd: config.path,
61
+ encoding: 'utf-8',
62
+ timeout: 30000,
63
+ });
64
+ if (result.status === 0) {
65
+ results.push({ repo: config.name, success: true });
66
+ }
67
+ else {
68
+ results.push({
69
+ repo: config.name,
70
+ success: false,
71
+ message: result.stderr?.trim() || 'Pull failed',
72
+ });
73
+ }
74
+ }
75
+ catch (err) {
76
+ results.push({ repo: config.name, success: false, message: err.message });
77
+ }
78
+ }
79
+ return reply.send({ results });
80
+ });
81
+ }
82
+ //# sourceMappingURL=git-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-api.js","sourceRoot":"","sources":["../../../src/server/routes/git-api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAwB,EACxB,gBAAkC,EAClC,aAAqB;IAErB,4CAA4C;IAC5C,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACnD,MAAM,WAAW,GAAG,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;QACzD,MAAM,QAAQ,GAQT,EAAE,CAAC;QAER,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACrD,MAAM,GAAG,GAAI,KAAa,CAAC,UAAU,CAAC;gBACtC,IAAI,CAAC,GAAG;oBAAE,SAAS;gBAEnB,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;gBAC/B,qBAAqB;gBACrB,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE;oBAC3E,GAAG,EAAE,MAAM,CAAC,IAAI;oBAChB,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAC;gBACH,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC;gBAErD,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,MAAM;oBACN,GAAG,MAAM;oBACT,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM;iBAC7G,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,iCAAiC;YACnC,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,0CAA0C;IAC1C,OAAO,CAAC,IAAI,CAET,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QACzC,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,aAAa,EAAE,SAAS,EAAE;gBAC1C,aAAa,EAAE,OAAO;aACvB,CAAC,CAAC;YACH,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,sCAAsC;IACtC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QAClD,MAAM,WAAW,GAAG,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;QACzD,MAAM,OAAO,GAAgE,EAAE,CAAC;QAEhF,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,CAAC,EAAE;oBACnE,GAAG,EAAE,MAAM,CAAC,IAAI;oBAChB,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,KAAK;iBACf,CAAC,CAAC;gBAEH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACxB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACrD,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,IAAI,CAAC;wBACX,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,OAAO,EAAE,KAAK;wBACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,aAAa;qBAChD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Graph API routes
3
3
  *
4
- * Read-only REST façade over WorkspaceManager.
5
- * All writes go through the agent (/api/chat).
4
+ * REST façade over WorkspaceManager.
5
+ * Read endpoints are unauthenticated; write endpoints require auth.
6
6
  */
7
7
  import type { FastifyInstance } from 'fastify';
8
8
  import { WorkspaceManager } from '../../core/workspace-manager.js';