@unbrained/pm-web 2026.7.11 → 2026.7.17-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.
- package/CHANGELOG.md +19 -0
- package/README.md +26 -0
- package/dist/app.d.ts +16 -1
- package/dist/app.js +53 -3
- package/dist/app.js.map +1 -1
- package/dist/auth.d.ts +2 -1
- package/dist/auth.js +10 -0
- package/dist/auth.js.map +1 -1
- package/dist/db.js +17 -1
- package/dist/db.js.map +1 -1
- package/dist/ical.js.map +1 -1
- package/dist/index.d.ts +1 -22
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/oidc.d.ts +89 -0
- package/dist/oidc.js +305 -0
- package/dist/oidc.js.map +1 -0
- package/dist/routes/auth.js +3 -15
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/github.js +3 -3
- package/dist/routes/github.js.map +1 -1
- package/dist/routes/oidc.d.ts +4 -0
- package/dist/routes/oidc.js +147 -0
- package/dist/routes/oidc.js.map +1 -0
- package/dist/routes/pm.js +172 -108
- package/dist/routes/pm.js.map +1 -1
- package/dist/routes/projects.js +9 -2
- package/dist/routes/projects.js.map +1 -1
- package/dist/server.js +7 -2
- package/dist/server.js.map +1 -1
- package/dist/services/pm-runner.d.ts +27 -3
- package/dist/services/pm-runner.js +188 -54
- package/dist/services/pm-runner.js.map +1 -1
- package/dist/services/realtime-bus.d.ts +1 -0
- package/dist/services/realtime-bus.js +148 -0
- package/dist/services/realtime-bus.js.map +1 -0
- package/dist/services/sse.d.ts +3 -1
- package/dist/services/sse.js +83 -48
- package/dist/services/sse.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +11 -11
- package/public/cookie-consent.js +54 -39
- package/public/cookie-settings.html +7 -7
- package/public/index.html +32 -26
- package/public/legal-notice.html +10 -12
- package/public/privacy-policy.html +14 -24
- package/public/src/app.js +18 -4
- package/public/src/app.js.map +1 -1
- package/public/src/app.ts +19 -4
- package/public/src/components/modals.js +5 -3
- package/public/src/components/modals.js.map +1 -1
- package/public/src/components/modals.ts +6 -3
- package/public/src/components/toast.js.map +1 -1
- package/public/src/cookie-consent.ts +68 -0
- package/public/src/i18n/de.json +117 -0
- package/public/src/i18n/en.json +117 -0
- package/public/src/i18n/es.json +117 -0
- package/public/src/i18n/zh.json +117 -0
- package/public/src/i18n.js +287 -0
- package/public/src/i18n.js.map +1 -0
- package/public/src/i18n.ts +306 -0
- package/public/src/sw.ts +446 -0
- package/public/src/views/auth.js +29 -6
- package/public/src/views/auth.js.map +1 -1
- package/public/src/views/auth.ts +27 -6
- package/public/src/views/graph.js.map +1 -1
- package/public/src/views/settings.js +73 -48
- package/public/src/views/settings.js.map +1 -1
- package/public/src/views/settings.ts +77 -48
- package/public/styles.css +2 -0
- package/public/sw.js +323 -256
- package/public/terms.html +7 -9
- package/public/tsconfig.json +1 -1
- package/public/tsconfig.scripts.json +18 -0
- package/public/tsconfig.sw.json +18 -0
- 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
|
|
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
|
package/dist/server.js.map
CHANGED
|
@@ -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;
|
|
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,14 @@
|
|
|
1
|
+
import { PmCliError, EXIT_CODE, type GetItemAtResult } from "@unbrained/pm-cli/sdk";
|
|
2
|
+
export { PmCliError, EXIT_CODE, type GetItemAtResult };
|
|
3
|
+
export declare class Semaphore {
|
|
4
|
+
private readonly limit;
|
|
5
|
+
private active;
|
|
6
|
+
private readonly waiting;
|
|
7
|
+
constructor(limit: number);
|
|
8
|
+
acquire(): Promise<() => void>;
|
|
9
|
+
}
|
|
1
10
|
export declare function getProjectDir(userId: string, slug: string): string;
|
|
2
|
-
export declare function initProject(userId: string, slug: string, prefix: string): void
|
|
11
|
+
export declare function initProject(userId: string, slug: string, prefix: string): Promise<void>;
|
|
3
12
|
export declare function projectExists(userId: string, slug: string): boolean;
|
|
4
13
|
export interface PmRunOptions {
|
|
5
14
|
args: string[];
|
|
@@ -7,6 +16,7 @@ export interface PmRunOptions {
|
|
|
7
16
|
slug: string;
|
|
8
17
|
input?: string;
|
|
9
18
|
jsonOutput?: boolean;
|
|
19
|
+
timeoutMs?: number;
|
|
10
20
|
}
|
|
11
21
|
export interface PmRunResult {
|
|
12
22
|
stdout: string;
|
|
@@ -20,6 +30,20 @@ export interface EnsureGraphExtensionResult {
|
|
|
20
30
|
active: boolean;
|
|
21
31
|
error?: string;
|
|
22
32
|
}
|
|
23
|
-
export declare function ensureGraphExtension(userId: string, slug: string): EnsureGraphExtensionResult
|
|
24
|
-
export declare function runPm(opts: PmRunOptions): PmRunResult
|
|
33
|
+
export declare function ensureGraphExtension(userId: string, slug: string): Promise<EnsureGraphExtensionResult>;
|
|
34
|
+
export declare function runPm(opts: PmRunOptions): Promise<PmRunResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Reconstruct a single item at a one-based version or ISO timestamp using the
|
|
37
|
+
* pm CLI SDK's mutation-free `getItemAt` projection (the same verified replay
|
|
38
|
+
* kernel that powers `pm get --at` and `pm restore`).
|
|
39
|
+
*
|
|
40
|
+
* Unlike {@link runPm}, this calls the SDK in-process — there is no history
|
|
41
|
+
* write, lock acquisition, or derived-index mutation — so it is safe to run
|
|
42
|
+
* concurrently with other readers and writers of the same workspace.
|
|
43
|
+
*
|
|
44
|
+
* @throws {PmCliError} with `exitCode` {@link EXIT_CODE}.NOT_FOUND when the item
|
|
45
|
+
* does not exist (or has no history), and {@link EXIT_CODE}.USAGE for an
|
|
46
|
+
* invalid ref or a version/timestamp outside the available history range.
|
|
47
|
+
*/
|
|
48
|
+
export declare function runGetItemAt(userId: string, slug: string, itemId: string, ref: string): Promise<GetItemAtResult>;
|
|
25
49
|
export declare function deleteProjectDir(userId: string, slug: string): void;
|
|
@@ -1,7 +1,48 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
|
|
4
|
+
import { getItemAt, PmCliError, EXIT_CODE, } from "@unbrained/pm-cli/sdk";
|
|
5
|
+
// Re-exported so route handlers and tests can reference the verified projection
|
|
6
|
+
// shape and the typed error class without reaching into the SDK package map.
|
|
7
|
+
export { PmCliError, EXIT_CODE };
|
|
8
|
+
const DEFAULT_COMMAND_TIMEOUT_MS = 30_000;
|
|
9
|
+
const MAX_OUTPUT_BYTES = 32 * 1024 * 1024;
|
|
10
|
+
function positiveInteger(value, fallback) {
|
|
11
|
+
const parsed = Number.parseInt(value ?? "", 10);
|
|
12
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
13
|
+
}
|
|
14
|
+
export class Semaphore {
|
|
15
|
+
limit;
|
|
16
|
+
active = 0;
|
|
17
|
+
waiting = [];
|
|
18
|
+
constructor(limit) {
|
|
19
|
+
this.limit = limit;
|
|
20
|
+
}
|
|
21
|
+
async acquire() {
|
|
22
|
+
if (this.active >= this.limit) {
|
|
23
|
+
await new Promise((resolve) => this.waiting.push(resolve));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.active += 1;
|
|
27
|
+
}
|
|
28
|
+
let released = false;
|
|
29
|
+
return () => {
|
|
30
|
+
if (released)
|
|
31
|
+
return;
|
|
32
|
+
released = true;
|
|
33
|
+
const next = this.waiting.shift();
|
|
34
|
+
if (next)
|
|
35
|
+
next();
|
|
36
|
+
else
|
|
37
|
+
this.active -= 1;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const commandSlots = new Semaphore(positiveInteger(process.env.PM_WEB_PM_CONCURRENCY, 8));
|
|
42
|
+
const workspaceTails = new Map();
|
|
43
|
+
function projectsRoot() {
|
|
44
|
+
return process.env.PROJECTS_ROOT || "/app/projects";
|
|
45
|
+
}
|
|
5
46
|
const OLLAMA_BASE_URL = process.env.OLLAMA_BASE_URL ||
|
|
6
47
|
process.env.OLLAMA_HOST ||
|
|
7
48
|
"http://localhost:11434";
|
|
@@ -11,23 +52,123 @@ const OLLAMA_API_KEY = process.env.OLLAMA_API_KEY || "";
|
|
|
11
52
|
const PM_GRAPH_EXTENSION_PATH = process.env.PM_GRAPH_EXTENSION_PATH ||
|
|
12
53
|
path.join(process.cwd(), "extensions", "pm-graph");
|
|
13
54
|
export function getProjectDir(userId, slug) {
|
|
14
|
-
return path.join(
|
|
55
|
+
return path.join(projectsRoot(), userId, slug);
|
|
15
56
|
}
|
|
16
|
-
|
|
57
|
+
let cachedPmCommand;
|
|
58
|
+
function pmCliCommand() {
|
|
59
|
+
if (process.env.PM_CLI_BIN)
|
|
60
|
+
return { command: process.env.PM_CLI_BIN, prefixArgs: [] };
|
|
61
|
+
if (cachedPmCommand)
|
|
62
|
+
return cachedPmCommand;
|
|
63
|
+
if (process.platform === "win32") {
|
|
64
|
+
const entry = path.join(process.cwd(), "node_modules", "@unbrained", "pm-cli", "dist", "cli.js");
|
|
65
|
+
cachedPmCommand = fs.existsSync(entry)
|
|
66
|
+
? { command: process.execPath, prefixArgs: [entry] }
|
|
67
|
+
: { command: "pm", prefixArgs: [] };
|
|
68
|
+
return cachedPmCommand;
|
|
69
|
+
}
|
|
70
|
+
const local = path.join(process.cwd(), "node_modules", ".bin", "pm");
|
|
71
|
+
cachedPmCommand = fs.existsSync(local)
|
|
72
|
+
? { command: local, prefixArgs: [] }
|
|
73
|
+
: { command: "pm", prefixArgs: [] };
|
|
74
|
+
return cachedPmCommand;
|
|
75
|
+
}
|
|
76
|
+
async function runProcess(cwd, args, options = {}) {
|
|
77
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS;
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
const pmCommand = pmCliCommand();
|
|
80
|
+
let child;
|
|
81
|
+
try {
|
|
82
|
+
child = spawn(pmCommand.command, [...pmCommand.prefixArgs, ...args], {
|
|
83
|
+
cwd,
|
|
84
|
+
env: { ...process.env, HOME: "/tmp", NO_COLOR: "1", ...options.env },
|
|
85
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
86
|
+
windowsHide: true,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
resolve({
|
|
91
|
+
stdout: "",
|
|
92
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
93
|
+
ok: false,
|
|
94
|
+
});
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const stdout = [];
|
|
98
|
+
const stderr = [];
|
|
99
|
+
let outputBytes = 0;
|
|
100
|
+
let failure = "";
|
|
101
|
+
let settled = false;
|
|
102
|
+
let forceKill;
|
|
103
|
+
const terminate = (reason) => {
|
|
104
|
+
if (failure)
|
|
105
|
+
return;
|
|
106
|
+
failure = reason;
|
|
107
|
+
child.kill("SIGTERM");
|
|
108
|
+
forceKill = setTimeout(() => child.kill("SIGKILL"), 1_000);
|
|
109
|
+
forceKill.unref();
|
|
110
|
+
};
|
|
111
|
+
const collect = (chunks, chunk) => {
|
|
112
|
+
outputBytes += chunk.length;
|
|
113
|
+
if (outputBytes > MAX_OUTPUT_BYTES) {
|
|
114
|
+
terminate(`pm command exceeded the ${MAX_OUTPUT_BYTES}-byte output limit`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
chunks.push(chunk);
|
|
118
|
+
};
|
|
119
|
+
child.stdout.on("data", (chunk) => collect(stdout, chunk));
|
|
120
|
+
child.stderr.on("data", (chunk) => collect(stderr, chunk));
|
|
121
|
+
child.on("error", (error) => {
|
|
122
|
+
failure = error.message;
|
|
123
|
+
});
|
|
124
|
+
const timeout = setTimeout(() => terminate(`pm command timed out after ${timeoutMs}ms`), timeoutMs);
|
|
125
|
+
timeout.unref();
|
|
126
|
+
child.on("close", (code) => {
|
|
127
|
+
if (settled)
|
|
128
|
+
return;
|
|
129
|
+
settled = true;
|
|
130
|
+
clearTimeout(timeout);
|
|
131
|
+
if (forceKill)
|
|
132
|
+
clearTimeout(forceKill);
|
|
133
|
+
const stderrText = Buffer.concat(stderr).toString("utf8");
|
|
134
|
+
resolve({
|
|
135
|
+
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
136
|
+
stderr: failure ? `${stderrText}${stderrText ? "\n" : ""}${failure}` : stderrText,
|
|
137
|
+
ok: code === 0 && !failure,
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
child.stdin.on("error", () => undefined);
|
|
141
|
+
child.stdin.end(options.input);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
async function runSerialized(workspace, work) {
|
|
145
|
+
const previous = workspaceTails.get(workspace) ?? Promise.resolve();
|
|
146
|
+
let releaseWorkspace;
|
|
147
|
+
const gate = new Promise((resolve) => { releaseWorkspace = resolve; });
|
|
148
|
+
const tail = previous.catch(() => undefined).then(() => gate);
|
|
149
|
+
workspaceTails.set(workspace, tail);
|
|
150
|
+
await previous.catch(() => undefined);
|
|
151
|
+
const releaseSlot = await commandSlots.acquire();
|
|
152
|
+
try {
|
|
153
|
+
return await work();
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
releaseSlot();
|
|
157
|
+
releaseWorkspace();
|
|
158
|
+
void tail.finally(() => {
|
|
159
|
+
if (workspaceTails.get(workspace) === tail)
|
|
160
|
+
workspaceTails.delete(workspace);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export async function initProject(userId, slug, prefix) {
|
|
17
165
|
const dir = getProjectDir(userId, slug);
|
|
18
166
|
fs.mkdirSync(dir, { recursive: true });
|
|
19
|
-
const result =
|
|
20
|
-
|
|
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)
|
|
167
|
+
const result = await runSerialized(dir, () => runProcess(dir, ["init", prefix], { timeoutMs: 15_000 }));
|
|
168
|
+
if (!result.ok)
|
|
28
169
|
throw new Error(result.stderr || "pm init failed");
|
|
29
170
|
configureLocalOllamaSearch(dir);
|
|
30
|
-
ensureGraphExtension(userId, slug);
|
|
171
|
+
await ensureGraphExtension(userId, slug);
|
|
31
172
|
}
|
|
32
173
|
function configureLocalOllamaSearch(projectDir) {
|
|
33
174
|
const settingsPath = path.join(projectDir, ".agents", "pm", "settings.json");
|
|
@@ -76,14 +217,9 @@ function bundledGraphExtensionManifest() {
|
|
|
76
217
|
function projectGraphExtensionManifest(projectDir) {
|
|
77
218
|
return readJsonFile(path.join(projectDir, ".agents", "pm", "extensions", "pm-graph", "manifest.json"));
|
|
78
219
|
}
|
|
79
|
-
function graphExtensionIsActive(projectDir) {
|
|
80
|
-
const result =
|
|
81
|
-
|
|
82
|
-
encoding: "utf8",
|
|
83
|
-
timeout: 15_000,
|
|
84
|
-
env: { ...process.env, HOME: "/tmp", NO_COLOR: "1" },
|
|
85
|
-
});
|
|
86
|
-
if (result.status !== 0 || !result.stdout)
|
|
220
|
+
async function graphExtensionIsActive(projectDir) {
|
|
221
|
+
const result = await runSerialized(projectDir, () => runProcess(projectDir, ["extension", "explore", "--project", "--json"], { timeoutMs: 15_000 }));
|
|
222
|
+
if (!result.ok || !result.stdout)
|
|
87
223
|
return false;
|
|
88
224
|
try {
|
|
89
225
|
const parsed = JSON.parse(result.stdout);
|
|
@@ -93,20 +229,10 @@ function graphExtensionIsActive(projectDir) {
|
|
|
93
229
|
return false;
|
|
94
230
|
}
|
|
95
231
|
}
|
|
96
|
-
function runExtensionCommand(projectDir, args) {
|
|
97
|
-
|
|
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
|
-
};
|
|
232
|
+
async function runExtensionCommand(projectDir, args) {
|
|
233
|
+
return runSerialized(projectDir, () => runProcess(projectDir, args));
|
|
108
234
|
}
|
|
109
|
-
export function ensureGraphExtension(userId, slug) {
|
|
235
|
+
export async function ensureGraphExtension(userId, slug) {
|
|
110
236
|
const dir = getProjectDir(userId, slug);
|
|
111
237
|
const bundledManifest = bundledGraphExtensionManifest();
|
|
112
238
|
if (!bundledManifest) {
|
|
@@ -120,7 +246,7 @@ export function ensureGraphExtension(userId, slug) {
|
|
|
120
246
|
const projectManifest = projectGraphExtensionManifest(dir);
|
|
121
247
|
const needsInstall = !projectManifest || projectManifest.version !== bundledManifest.version;
|
|
122
248
|
if (needsInstall) {
|
|
123
|
-
const install = runExtensionCommand(dir, ["install", PM_GRAPH_EXTENSION_PATH, "--project"]);
|
|
249
|
+
const install = await runExtensionCommand(dir, ["install", PM_GRAPH_EXTENSION_PATH, "--project"]);
|
|
124
250
|
if (!install.ok) {
|
|
125
251
|
return {
|
|
126
252
|
ok: false,
|
|
@@ -130,8 +256,8 @@ export function ensureGraphExtension(userId, slug) {
|
|
|
130
256
|
};
|
|
131
257
|
}
|
|
132
258
|
}
|
|
133
|
-
if (!graphExtensionIsActive(dir)) {
|
|
134
|
-
const activate = runExtensionCommand(dir, ["extension", "activate", "pm-graph", "--project"]);
|
|
259
|
+
if (!(await graphExtensionIsActive(dir))) {
|
|
260
|
+
const activate = await runExtensionCommand(dir, ["extension", "activate", "pm-graph", "--project"]);
|
|
135
261
|
if (!activate.ok) {
|
|
136
262
|
return {
|
|
137
263
|
ok: false,
|
|
@@ -141,7 +267,7 @@ export function ensureGraphExtension(userId, slug) {
|
|
|
141
267
|
};
|
|
142
268
|
}
|
|
143
269
|
}
|
|
144
|
-
const ping = runExtensionCommand(dir, ["pm-graph", "ping", "--json"]);
|
|
270
|
+
const ping = await runExtensionCommand(dir, ["pm-graph", "ping", "--json"]);
|
|
145
271
|
if (!ping.ok) {
|
|
146
272
|
return {
|
|
147
273
|
ok: false,
|
|
@@ -152,24 +278,15 @@ export function ensureGraphExtension(userId, slug) {
|
|
|
152
278
|
}
|
|
153
279
|
return { ok: true, installed: true, active: true };
|
|
154
280
|
}
|
|
155
|
-
export function runPm(opts) {
|
|
281
|
+
export async function runPm(opts) {
|
|
156
282
|
const dir = getProjectDir(opts.userId, opts.slug);
|
|
157
283
|
const args = opts.jsonOutput ? ["--json", ...opts.args] : opts.args;
|
|
158
|
-
const result =
|
|
159
|
-
cwd: dir,
|
|
160
|
-
encoding: "utf8",
|
|
161
|
-
timeout: 30_000,
|
|
284
|
+
const result = await runSerialized(dir, () => runProcess(dir, args, {
|
|
162
285
|
input: opts.input,
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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;
|
|
286
|
+
timeoutMs: opts.timeoutMs,
|
|
287
|
+
env: { PM_GRAPH_PROJECT_KEY: `${opts.userId}:${opts.slug}` },
|
|
288
|
+
}));
|
|
289
|
+
const { stdout, stderr, ok } = result;
|
|
173
290
|
let parsed;
|
|
174
291
|
if (opts.jsonOutput && ok && stdout) {
|
|
175
292
|
try {
|
|
@@ -181,6 +298,23 @@ export function runPm(opts) {
|
|
|
181
298
|
}
|
|
182
299
|
return { stdout, stderr, ok, parsed };
|
|
183
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Reconstruct a single item at a one-based version or ISO timestamp using the
|
|
303
|
+
* pm CLI SDK's mutation-free `getItemAt` projection (the same verified replay
|
|
304
|
+
* kernel that powers `pm get --at` and `pm restore`).
|
|
305
|
+
*
|
|
306
|
+
* Unlike {@link runPm}, this calls the SDK in-process — there is no history
|
|
307
|
+
* write, lock acquisition, or derived-index mutation — so it is safe to run
|
|
308
|
+
* concurrently with other readers and writers of the same workspace.
|
|
309
|
+
*
|
|
310
|
+
* @throws {PmCliError} with `exitCode` {@link EXIT_CODE}.NOT_FOUND when the item
|
|
311
|
+
* does not exist (or has no history), and {@link EXIT_CODE}.USAGE for an
|
|
312
|
+
* invalid ref or a version/timestamp outside the available history range.
|
|
313
|
+
*/
|
|
314
|
+
export async function runGetItemAt(userId, slug, itemId, ref) {
|
|
315
|
+
const pmRoot = path.join(getProjectDir(userId, slug), ".agents", "pm");
|
|
316
|
+
return await getItemAt(itemId, ref, { pmRoot });
|
|
317
|
+
}
|
|
184
318
|
export function deleteProjectDir(userId, slug) {
|
|
185
319
|
const dir = getProjectDir(userId, slug);
|
|
186
320
|
if (fs.existsSync(dir)) {
|
|
@@ -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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"}
|
package/dist/services/sse.d.ts
CHANGED
|
@@ -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):
|
|
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;
|