@unbrained/pm-web 2026.7.10 → 2026.7.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +26 -0
  3. package/dist/app.d.ts +1 -0
  4. package/dist/app.js +38 -2
  5. package/dist/app.js.map +1 -1
  6. package/dist/auth.d.ts +2 -1
  7. package/dist/auth.js +10 -0
  8. package/dist/auth.js.map +1 -1
  9. package/dist/db.js +17 -1
  10. package/dist/db.js.map +1 -1
  11. package/dist/ical.js.map +1 -1
  12. package/dist/index.d.ts +1 -22
  13. package/dist/index.js +2 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/oidc.d.ts +89 -0
  16. package/dist/oidc.js +305 -0
  17. package/dist/oidc.js.map +1 -0
  18. package/dist/routes/auth.js +3 -15
  19. package/dist/routes/auth.js.map +1 -1
  20. package/dist/routes/github.js +3 -3
  21. package/dist/routes/github.js.map +1 -1
  22. package/dist/routes/oidc.d.ts +4 -0
  23. package/dist/routes/oidc.js +147 -0
  24. package/dist/routes/oidc.js.map +1 -0
  25. package/dist/routes/pm.js +121 -107
  26. package/dist/routes/pm.js.map +1 -1
  27. package/dist/routes/projects.js +9 -2
  28. package/dist/routes/projects.js.map +1 -1
  29. package/dist/server.js +7 -2
  30. package/dist/server.js.map +1 -1
  31. package/dist/services/pm-runner.d.ts +11 -3
  32. package/dist/services/pm-runner.js +167 -54
  33. package/dist/services/pm-runner.js.map +1 -1
  34. package/dist/services/realtime-bus.d.ts +1 -0
  35. package/dist/services/realtime-bus.js +148 -0
  36. package/dist/services/realtime-bus.js.map +1 -0
  37. package/dist/services/sse.d.ts +3 -1
  38. package/dist/services/sse.js +83 -48
  39. package/dist/services/sse.js.map +1 -1
  40. package/manifest.json +1 -1
  41. package/package.json +11 -11
  42. package/public/cookie-consent.js +54 -39
  43. package/public/cookie-settings.html +7 -7
  44. package/public/index.html +2 -0
  45. package/public/legal-notice.html +10 -12
  46. package/public/privacy-policy.html +14 -24
  47. package/public/src/app.js +4 -4
  48. package/public/src/app.js.map +1 -1
  49. package/public/src/app.ts +4 -4
  50. package/public/src/components/toast.js.map +1 -1
  51. package/public/src/cookie-consent.ts +68 -0
  52. package/public/src/sw.ts +443 -0
  53. package/public/src/views/auth.js +22 -0
  54. package/public/src/views/auth.js.map +1 -1
  55. package/public/src/views/auth.ts +20 -0
  56. package/public/src/views/graph.js.map +1 -1
  57. package/public/styles.css +2 -0
  58. package/public/sw.js +320 -256
  59. package/public/terms.html +7 -9
  60. package/public/tsconfig.json +1 -1
  61. package/public/tsconfig.scripts.json +18 -0
  62. package/public/tsconfig.sw.json +18 -0
  63. package/sql/schema.sql +16 -0
package/dist/server.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { initSchema, assertDbConfigured } from "./db.js";
2
2
  import { createApp } from "./app.js";
3
3
  import { cleanupStaleClients } from "./services/sse.js";
4
+ import { startRealtimeBus } from "./services/realtime-bus.js";
5
+ import { assertOidcConfiguration } from "./oidc.js";
4
6
  const PORT = parseInt(process.env.PORT || "4000", 10);
5
7
  const app = createApp();
6
8
  // Validate configuration before doing anything that needs the database, so a
@@ -8,6 +10,7 @@ const app = createApp();
8
10
  // DNS/connection timeout.
9
11
  try {
10
12
  assertDbConfigured();
13
+ assertOidcConfiguration();
11
14
  }
12
15
  catch (err) {
13
16
  console.error(err instanceof Error ? err.message : String(err));
@@ -15,7 +18,8 @@ catch (err) {
15
18
  }
16
19
  // Init DB schema, then start server
17
20
  initSchema()
18
- .then(() => {
21
+ .then(async () => {
22
+ const closeRealtimeBus = await startRealtimeBus();
19
23
  // Express 5 invokes the listen callback WITH the error (it is installed
20
24
  // as the server's 'error' handler), so ignoring the argument turns
21
25
  // EADDRINUSE into a false "running" message and a process that idles
@@ -31,11 +35,12 @@ initSchema()
31
35
  console.error(`Server error on :${PORT}:`, err.message);
32
36
  process.exit(1);
33
37
  });
38
+ server.on("close", () => { void closeRealtimeBus(); });
34
39
  // Periodic cleanup of stale SSE clients
35
40
  setInterval(cleanupStaleClients, 5 * 60 * 1000);
36
41
  })
37
42
  .catch((err) => {
38
- console.error("Failed to initialize database schema:", err instanceof Error ? err.message : err);
43
+ console.error("Failed to initialize pm-web runtime:", err instanceof Error ? err.message : err);
39
44
  process.exit(1);
40
45
  });
41
46
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtD,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;AAExB,6EAA6E;AAC7E,+EAA+E;AAC/E,0BAA0B;AAC1B,IAAI,CAAC;IACH,kBAAkB,EAAE,CAAC;AACvB,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,oCAAoC;AACpC,UAAU,EAAE;KACT,IAAI,CAAC,GAAG,EAAE;IACT,wEAAwE;IACxE,mEAAmE;IACnE,qEAAqE;IACrE,mCAAmC;IACnC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE;QAC9C,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,CAAC,KAAK,CAAC,mBAAmB,IAAI,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;QAChC,OAAO,CAAC,KAAK,CAAC,oBAAoB,IAAI,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,wCAAwC;IACxC,WAAW,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AAClD,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACb,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACjG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtD,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;AAExB,6EAA6E;AAC7E,+EAA+E;AAC/E,0BAA0B;AAC1B,IAAI,CAAC;IACH,kBAAkB,EAAE,CAAC;IACrB,uBAAuB,EAAE,CAAC;AAC5B,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,oCAAoC;AACpC,UAAU,EAAE;KACT,IAAI,CAAC,KAAK,IAAI,EAAE;IACf,MAAM,gBAAgB,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAClD,wEAAwE;IACxE,mEAAmE;IACnE,qEAAqE;IACrE,mCAAmC;IACnC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE;QAC9C,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,CAAC,KAAK,CAAC,mBAAmB,IAAI,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;QAChC,OAAO,CAAC,KAAK,CAAC,oBAAoB,IAAI,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,wCAAwC;IACxC,WAAW,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AAClD,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACb,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -1,5 +1,12 @@
1
+ export declare class Semaphore {
2
+ private readonly limit;
3
+ private active;
4
+ private readonly waiting;
5
+ constructor(limit: number);
6
+ acquire(): Promise<() => void>;
7
+ }
1
8
  export declare function getProjectDir(userId: string, slug: string): string;
2
- export declare function initProject(userId: string, slug: string, prefix: string): void;
9
+ export declare function initProject(userId: string, slug: string, prefix: string): Promise<void>;
3
10
  export declare function projectExists(userId: string, slug: string): boolean;
4
11
  export interface PmRunOptions {
5
12
  args: string[];
@@ -7,6 +14,7 @@ export interface PmRunOptions {
7
14
  slug: string;
8
15
  input?: string;
9
16
  jsonOutput?: boolean;
17
+ timeoutMs?: number;
10
18
  }
11
19
  export interface PmRunResult {
12
20
  stdout: string;
@@ -20,6 +28,6 @@ export interface EnsureGraphExtensionResult {
20
28
  active: boolean;
21
29
  error?: string;
22
30
  }
23
- export declare function ensureGraphExtension(userId: string, slug: string): EnsureGraphExtensionResult;
24
- export declare function runPm(opts: PmRunOptions): PmRunResult;
31
+ export declare function ensureGraphExtension(userId: string, slug: string): Promise<EnsureGraphExtensionResult>;
32
+ export declare function runPm(opts: PmRunOptions): Promise<PmRunResult>;
25
33
  export declare function deleteProjectDir(userId: string, slug: string): void;
@@ -1,7 +1,44 @@
1
- import { spawnSync } from "node:child_process";
1
+ import { spawn } from "node:child_process";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- const PROJECTS_ROOT = process.env.PROJECTS_ROOT || "/app/projects";
4
+ const DEFAULT_COMMAND_TIMEOUT_MS = 30_000;
5
+ const MAX_OUTPUT_BYTES = 32 * 1024 * 1024;
6
+ function positiveInteger(value, fallback) {
7
+ const parsed = Number.parseInt(value ?? "", 10);
8
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : fallback;
9
+ }
10
+ export class Semaphore {
11
+ limit;
12
+ active = 0;
13
+ waiting = [];
14
+ constructor(limit) {
15
+ this.limit = limit;
16
+ }
17
+ async acquire() {
18
+ if (this.active >= this.limit) {
19
+ await new Promise((resolve) => this.waiting.push(resolve));
20
+ }
21
+ else {
22
+ this.active += 1;
23
+ }
24
+ let released = false;
25
+ return () => {
26
+ if (released)
27
+ return;
28
+ released = true;
29
+ const next = this.waiting.shift();
30
+ if (next)
31
+ next();
32
+ else
33
+ this.active -= 1;
34
+ };
35
+ }
36
+ }
37
+ const commandSlots = new Semaphore(positiveInteger(process.env.PM_WEB_PM_CONCURRENCY, 8));
38
+ const workspaceTails = new Map();
39
+ function projectsRoot() {
40
+ return process.env.PROJECTS_ROOT || "/app/projects";
41
+ }
5
42
  const OLLAMA_BASE_URL = process.env.OLLAMA_BASE_URL ||
6
43
  process.env.OLLAMA_HOST ||
7
44
  "http://localhost:11434";
@@ -11,23 +48,123 @@ const OLLAMA_API_KEY = process.env.OLLAMA_API_KEY || "";
11
48
  const PM_GRAPH_EXTENSION_PATH = process.env.PM_GRAPH_EXTENSION_PATH ||
12
49
  path.join(process.cwd(), "extensions", "pm-graph");
13
50
  export function getProjectDir(userId, slug) {
14
- return path.join(PROJECTS_ROOT, userId, slug);
51
+ return path.join(projectsRoot(), userId, slug);
52
+ }
53
+ let cachedPmCommand;
54
+ function pmCliCommand() {
55
+ if (process.env.PM_CLI_BIN)
56
+ return { command: process.env.PM_CLI_BIN, prefixArgs: [] };
57
+ if (cachedPmCommand)
58
+ return cachedPmCommand;
59
+ if (process.platform === "win32") {
60
+ const entry = path.join(process.cwd(), "node_modules", "@unbrained", "pm-cli", "dist", "cli.js");
61
+ cachedPmCommand = fs.existsSync(entry)
62
+ ? { command: process.execPath, prefixArgs: [entry] }
63
+ : { command: "pm", prefixArgs: [] };
64
+ return cachedPmCommand;
65
+ }
66
+ const local = path.join(process.cwd(), "node_modules", ".bin", "pm");
67
+ cachedPmCommand = fs.existsSync(local)
68
+ ? { command: local, prefixArgs: [] }
69
+ : { command: "pm", prefixArgs: [] };
70
+ return cachedPmCommand;
71
+ }
72
+ async function runProcess(cwd, args, options = {}) {
73
+ const timeoutMs = options.timeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS;
74
+ return new Promise((resolve) => {
75
+ const pmCommand = pmCliCommand();
76
+ let child;
77
+ try {
78
+ child = spawn(pmCommand.command, [...pmCommand.prefixArgs, ...args], {
79
+ cwd,
80
+ env: { ...process.env, HOME: "/tmp", NO_COLOR: "1", ...options.env },
81
+ stdio: ["pipe", "pipe", "pipe"],
82
+ windowsHide: true,
83
+ });
84
+ }
85
+ catch (error) {
86
+ resolve({
87
+ stdout: "",
88
+ stderr: error instanceof Error ? error.message : String(error),
89
+ ok: false,
90
+ });
91
+ return;
92
+ }
93
+ const stdout = [];
94
+ const stderr = [];
95
+ let outputBytes = 0;
96
+ let failure = "";
97
+ let settled = false;
98
+ let forceKill;
99
+ const terminate = (reason) => {
100
+ if (failure)
101
+ return;
102
+ failure = reason;
103
+ child.kill("SIGTERM");
104
+ forceKill = setTimeout(() => child.kill("SIGKILL"), 1_000);
105
+ forceKill.unref();
106
+ };
107
+ const collect = (chunks, chunk) => {
108
+ outputBytes += chunk.length;
109
+ if (outputBytes > MAX_OUTPUT_BYTES) {
110
+ terminate(`pm command exceeded the ${MAX_OUTPUT_BYTES}-byte output limit`);
111
+ return;
112
+ }
113
+ chunks.push(chunk);
114
+ };
115
+ child.stdout.on("data", (chunk) => collect(stdout, chunk));
116
+ child.stderr.on("data", (chunk) => collect(stderr, chunk));
117
+ child.on("error", (error) => {
118
+ failure = error.message;
119
+ });
120
+ const timeout = setTimeout(() => terminate(`pm command timed out after ${timeoutMs}ms`), timeoutMs);
121
+ timeout.unref();
122
+ child.on("close", (code) => {
123
+ if (settled)
124
+ return;
125
+ settled = true;
126
+ clearTimeout(timeout);
127
+ if (forceKill)
128
+ clearTimeout(forceKill);
129
+ const stderrText = Buffer.concat(stderr).toString("utf8");
130
+ resolve({
131
+ stdout: Buffer.concat(stdout).toString("utf8"),
132
+ stderr: failure ? `${stderrText}${stderrText ? "\n" : ""}${failure}` : stderrText,
133
+ ok: code === 0 && !failure,
134
+ });
135
+ });
136
+ child.stdin.on("error", () => undefined);
137
+ child.stdin.end(options.input);
138
+ });
139
+ }
140
+ async function runSerialized(workspace, work) {
141
+ const previous = workspaceTails.get(workspace) ?? Promise.resolve();
142
+ let releaseWorkspace;
143
+ const gate = new Promise((resolve) => { releaseWorkspace = resolve; });
144
+ const tail = previous.catch(() => undefined).then(() => gate);
145
+ workspaceTails.set(workspace, tail);
146
+ await previous.catch(() => undefined);
147
+ const releaseSlot = await commandSlots.acquire();
148
+ try {
149
+ return await work();
150
+ }
151
+ finally {
152
+ releaseSlot();
153
+ releaseWorkspace();
154
+ void tail.finally(() => {
155
+ if (workspaceTails.get(workspace) === tail)
156
+ workspaceTails.delete(workspace);
157
+ });
158
+ }
15
159
  }
16
- export function initProject(userId, slug, prefix) {
160
+ export async function initProject(userId, slug, prefix) {
17
161
  const dir = getProjectDir(userId, slug);
18
162
  fs.mkdirSync(dir, { recursive: true });
19
- const result = spawnSync("pm", ["init", prefix], {
20
- cwd: dir,
21
- encoding: "utf8",
22
- timeout: 15_000,
23
- env: { ...process.env, HOME: "/tmp" },
24
- });
25
- if (result.error)
26
- throw result.error;
27
- if (result.status !== 0)
163
+ const result = await runSerialized(dir, () => runProcess(dir, ["init", prefix], { timeoutMs: 15_000 }));
164
+ if (!result.ok)
28
165
  throw new Error(result.stderr || "pm init failed");
29
166
  configureLocalOllamaSearch(dir);
30
- ensureGraphExtension(userId, slug);
167
+ await ensureGraphExtension(userId, slug);
31
168
  }
32
169
  function configureLocalOllamaSearch(projectDir) {
33
170
  const settingsPath = path.join(projectDir, ".agents", "pm", "settings.json");
@@ -76,14 +213,9 @@ function bundledGraphExtensionManifest() {
76
213
  function projectGraphExtensionManifest(projectDir) {
77
214
  return readJsonFile(path.join(projectDir, ".agents", "pm", "extensions", "pm-graph", "manifest.json"));
78
215
  }
79
- function graphExtensionIsActive(projectDir) {
80
- const result = spawnSync("pm", ["extension", "explore", "--project", "--json"], {
81
- cwd: projectDir,
82
- encoding: "utf8",
83
- timeout: 15_000,
84
- env: { ...process.env, HOME: "/tmp", NO_COLOR: "1" },
85
- });
86
- if (result.status !== 0 || !result.stdout)
216
+ async function graphExtensionIsActive(projectDir) {
217
+ const result = await runSerialized(projectDir, () => runProcess(projectDir, ["extension", "explore", "--project", "--json"], { timeoutMs: 15_000 }));
218
+ if (!result.ok || !result.stdout)
87
219
  return false;
88
220
  try {
89
221
  const parsed = JSON.parse(result.stdout);
@@ -93,20 +225,10 @@ function graphExtensionIsActive(projectDir) {
93
225
  return false;
94
226
  }
95
227
  }
96
- function runExtensionCommand(projectDir, args) {
97
- const result = spawnSync("pm", args, {
98
- cwd: projectDir,
99
- encoding: "utf8",
100
- timeout: 30_000,
101
- env: { ...process.env, HOME: "/tmp", NO_COLOR: "1" },
102
- });
103
- return {
104
- stdout: result.stdout || "",
105
- stderr: result.stderr || (result.error ? result.error.message : ""),
106
- ok: result.status === 0,
107
- };
228
+ async function runExtensionCommand(projectDir, args) {
229
+ return runSerialized(projectDir, () => runProcess(projectDir, args));
108
230
  }
109
- export function ensureGraphExtension(userId, slug) {
231
+ export async function ensureGraphExtension(userId, slug) {
110
232
  const dir = getProjectDir(userId, slug);
111
233
  const bundledManifest = bundledGraphExtensionManifest();
112
234
  if (!bundledManifest) {
@@ -120,7 +242,7 @@ export function ensureGraphExtension(userId, slug) {
120
242
  const projectManifest = projectGraphExtensionManifest(dir);
121
243
  const needsInstall = !projectManifest || projectManifest.version !== bundledManifest.version;
122
244
  if (needsInstall) {
123
- const install = runExtensionCommand(dir, ["install", PM_GRAPH_EXTENSION_PATH, "--project"]);
245
+ const install = await runExtensionCommand(dir, ["install", PM_GRAPH_EXTENSION_PATH, "--project"]);
124
246
  if (!install.ok) {
125
247
  return {
126
248
  ok: false,
@@ -130,8 +252,8 @@ export function ensureGraphExtension(userId, slug) {
130
252
  };
131
253
  }
132
254
  }
133
- if (!graphExtensionIsActive(dir)) {
134
- const activate = runExtensionCommand(dir, ["extension", "activate", "pm-graph", "--project"]);
255
+ if (!(await graphExtensionIsActive(dir))) {
256
+ const activate = await runExtensionCommand(dir, ["extension", "activate", "pm-graph", "--project"]);
135
257
  if (!activate.ok) {
136
258
  return {
137
259
  ok: false,
@@ -141,7 +263,7 @@ export function ensureGraphExtension(userId, slug) {
141
263
  };
142
264
  }
143
265
  }
144
- const ping = runExtensionCommand(dir, ["pm-graph", "ping", "--json"]);
266
+ const ping = await runExtensionCommand(dir, ["pm-graph", "ping", "--json"]);
145
267
  if (!ping.ok) {
146
268
  return {
147
269
  ok: false,
@@ -152,24 +274,15 @@ export function ensureGraphExtension(userId, slug) {
152
274
  }
153
275
  return { ok: true, installed: true, active: true };
154
276
  }
155
- export function runPm(opts) {
277
+ export async function runPm(opts) {
156
278
  const dir = getProjectDir(opts.userId, opts.slug);
157
279
  const args = opts.jsonOutput ? ["--json", ...opts.args] : opts.args;
158
- const result = spawnSync("pm", args, {
159
- cwd: dir,
160
- encoding: "utf8",
161
- timeout: 30_000,
280
+ const result = await runSerialized(dir, () => runProcess(dir, args, {
162
281
  input: opts.input,
163
- env: {
164
- ...process.env,
165
- HOME: "/tmp",
166
- NO_COLOR: "1",
167
- PM_GRAPH_PROJECT_KEY: `${opts.userId}:${opts.slug}`,
168
- },
169
- });
170
- const stdout = result.stdout || "";
171
- const stderr = result.stderr || "";
172
- const ok = result.status === 0;
282
+ timeoutMs: opts.timeoutMs,
283
+ env: { PM_GRAPH_PROJECT_KEY: `${opts.userId}:${opts.slug}` },
284
+ }));
285
+ const { stdout, stderr, ok } = result;
173
286
  let parsed;
174
287
  if (opts.jsonOutput && ok && stdout) {
175
288
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"pm-runner.js","sourceRoot":"","sources":["../../src/services/pm-runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pm-runner.js","sourceRoot":"","sources":["../../src/services/pm-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function startRealtimeBus(): Promise<() => Promise<void>>;
@@ -0,0 +1,148 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { pool } from "../db.js";
3
+ import { configureProjectEventPublisher, deliverProjectEvent, } from "./sse.js";
4
+ const CHANNEL = "pm_workspace_events";
5
+ const INSTANCE_ID = randomUUID();
6
+ const PROJECT_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
7
+ const EVENT_TYPE = /^[a-z][a-z0-9-]{0,63}$/;
8
+ function safeSharedData(data) {
9
+ if (!data || typeof data !== "object" || Array.isArray(data))
10
+ return {};
11
+ const source = data;
12
+ const safe = {};
13
+ for (const key of ["itemId", "userId", "change", "target", "rel", "reason", "count", "source", "operation"]) {
14
+ const value = source[key];
15
+ if (typeof value === "string" && value.length <= 256)
16
+ safe[key] = value;
17
+ else if (typeof value === "number" && Number.isFinite(value))
18
+ safe[key] = value;
19
+ }
20
+ return safe;
21
+ }
22
+ function parseEnvelope(raw) {
23
+ if (!raw || Buffer.byteLength(raw, "utf8") > 7_500)
24
+ return null;
25
+ try {
26
+ const value = JSON.parse(raw);
27
+ if (!value.projectId || !PROJECT_ID.test(value.projectId) || !value.type || !EVENT_TYPE.test(value.type))
28
+ return null;
29
+ return { projectId: value.projectId, type: value.type, data: safeSharedData(value.data), ...(value.sourceId ? { sourceId: value.sourceId } : {}) };
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ export async function startRealtimeBus() {
36
+ if (process.env.PM_REALTIME_ENABLED === "false")
37
+ return async () => undefined;
38
+ let listener = null;
39
+ let reconnectTimer = null;
40
+ let reconnectDelayMs = 250;
41
+ let stopped = false;
42
+ let connecting = null;
43
+ const handlers = new Map();
44
+ const safeDiagnostic = (error) => {
45
+ if (!(error instanceof Error))
46
+ return { name: typeof error };
47
+ const code = error.code;
48
+ return {
49
+ name: error.name,
50
+ ...(code && /^[A-Z0-9_]{1,32}$/i.test(String(code)) ? { code: String(code) } : {}),
51
+ };
52
+ };
53
+ const releaseClient = (client, destroy) => {
54
+ const registered = handlers.get(client);
55
+ if (!registered)
56
+ return;
57
+ client.off("error", registered.error);
58
+ client.off("notification", registered.notification);
59
+ handlers.delete(client);
60
+ client.release(destroy);
61
+ };
62
+ const scheduleReconnect = (error) => {
63
+ if (stopped || reconnectTimer)
64
+ return;
65
+ console.error("Realtime PostgreSQL listener disconnected", safeDiagnostic(error));
66
+ const delay = reconnectDelayMs;
67
+ reconnectDelayMs = Math.min(reconnectDelayMs * 2, 30_000);
68
+ reconnectTimer = setTimeout(() => {
69
+ reconnectTimer = null;
70
+ void connect().catch(scheduleReconnect);
71
+ }, delay);
72
+ reconnectTimer.unref();
73
+ };
74
+ const connectOnce = async () => {
75
+ const client = await pool.connect();
76
+ const notification = (message) => {
77
+ const event = parseEnvelope(message.payload);
78
+ if (!event || event.sourceId === INSTANCE_ID)
79
+ return;
80
+ deliverProjectEvent(event.projectId, { type: event.type, data: event.data });
81
+ };
82
+ const error = (cause) => {
83
+ if (listener !== client)
84
+ return;
85
+ listener = null;
86
+ releaseClient(client, true);
87
+ scheduleReconnect(cause);
88
+ };
89
+ handlers.set(client, { error, notification });
90
+ client.on("error", error);
91
+ client.on("notification", notification);
92
+ listener = client;
93
+ try {
94
+ await client.query(`LISTEN ${CHANNEL}`);
95
+ }
96
+ catch (cause) {
97
+ if (listener === client)
98
+ listener = null;
99
+ releaseClient(client, true);
100
+ throw cause;
101
+ }
102
+ if (stopped) {
103
+ if (listener === client)
104
+ listener = null;
105
+ await client.query(`UNLISTEN ${CHANNEL}`).catch(() => undefined);
106
+ releaseClient(client, false);
107
+ return;
108
+ }
109
+ reconnectDelayMs = 250;
110
+ };
111
+ const connect = () => {
112
+ if (connecting)
113
+ return connecting;
114
+ connecting = connectOnce().finally(() => { connecting = null; });
115
+ return connecting;
116
+ };
117
+ await connect();
118
+ configureProjectEventPublisher(async (projectId, event) => {
119
+ if (!PROJECT_ID.test(projectId) || !EVENT_TYPE.test(event.type))
120
+ return;
121
+ const payload = JSON.stringify({
122
+ projectId,
123
+ type: event.type,
124
+ data: safeSharedData(event.data),
125
+ sourceId: INSTANCE_ID,
126
+ });
127
+ if (Buffer.byteLength(payload, "utf8") <= 7_500) {
128
+ await pool.query("SELECT pg_notify($1, $2)", [CHANNEL, payload]);
129
+ }
130
+ else {
131
+ console.warn(`Realtime event payload exceeded size limit: ${projectId}/${event.type}`);
132
+ }
133
+ });
134
+ return async () => {
135
+ stopped = true;
136
+ if (reconnectTimer)
137
+ clearTimeout(reconnectTimer);
138
+ reconnectTimer = null;
139
+ configureProjectEventPublisher(null);
140
+ const client = listener;
141
+ listener = null;
142
+ if (client) {
143
+ await client.query(`UNLISTEN ${CHANNEL}`).catch(() => undefined);
144
+ releaseClient(client, false);
145
+ }
146
+ };
147
+ }
148
+ //# sourceMappingURL=realtime-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-bus.js","sourceRoot":"","sources":["../../src/services/realtime-bus.ts"],"names":[],"mappings":"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"}
@@ -14,10 +14,12 @@ export interface PresenceUser {
14
14
  currentView: string;
15
15
  connectedAt: string;
16
16
  }
17
+ export declare function configureProjectEventPublisher(publisher: ((projectId: string, event: SSEEvent) => Promise<void>) | null): void;
17
18
  export declare function addSSEClient(client: SSEClient): () => void;
18
19
  export declare function broadcastProjectEvent(projectId: string, event: SSEEvent): void;
20
+ export declare function deliverProjectEvent(projectId: string, event: SSEEvent): void;
19
21
  export declare function broadcastPresence(projectId: string): void;
20
- export declare function updateClientView(clientId: string, currentView: string): void;
22
+ export declare function updateClientView(clientId: string, userId: string, projectId: string, currentView: string): boolean;
21
23
  export declare function getProjectPresence(projectId: string): PresenceUser[];
22
24
  export declare function setupSSEHeaders(res: Response): void;
23
25
  export declare function getSSEClientCount(): number;