@lelouchhe/webagent 0.2.1 → 0.2.2

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.
@@ -0,0 +1,74 @@
1
+ const TITLE_MODEL = "claude-haiku-4.5";
2
+ export class TitleService {
3
+ titleSessionId = null;
4
+ activeSourceSessions = new Set();
5
+ cancelledSourceSessions = new Set();
6
+ defaultCwd;
7
+ store;
8
+ sessions;
9
+ constructor(store, sessions, defaultCwd) {
10
+ this.store = store;
11
+ this.sessions = sessions;
12
+ this.defaultCwd = defaultCwd;
13
+ }
14
+ /** Generate a title for the session (non-blocking, fire-and-forget). */
15
+ generate(bridge, userMessage, sessionId, onTitle) {
16
+ if (this.sessions.sessionHasTitle.has(sessionId) || this.activeSourceSessions.has(sessionId))
17
+ return;
18
+ this._generate(bridge, userMessage, sessionId).then((title) => {
19
+ if (title && onTitle)
20
+ onTitle(title);
21
+ }).catch((err) => {
22
+ console.error(`[title] generation failed:`, err);
23
+ });
24
+ }
25
+ async _generate(bridge, userMessage, sessionId) {
26
+ this.activeSourceSessions.add(sessionId);
27
+ const tsId = await this.ensureTitleSession(bridge);
28
+ if (!tsId) {
29
+ this.activeSourceSessions.delete(sessionId);
30
+ this.cancelledSourceSessions.delete(sessionId);
31
+ return;
32
+ }
33
+ try {
34
+ const prompt = `Generate a short title (max 30 chars, no quotes) for a chat that starts with this message. Reply with ONLY the title, nothing else:\n\n${userMessage.slice(0, 500)}`;
35
+ const title = await bridge.promptForText(tsId, prompt);
36
+ if (!title || this.cancelledSourceSessions.has(sessionId))
37
+ return;
38
+ // User may have set a title while generation was in flight
39
+ if (this.sessions.sessionHasTitle.has(sessionId))
40
+ return;
41
+ const cleaned = title.replace(/^["']|["']$/g, "").trim().slice(0, 30);
42
+ if (!cleaned)
43
+ return;
44
+ this.store.updateSessionTitle(sessionId, cleaned);
45
+ this.sessions.sessionHasTitle.add(sessionId);
46
+ return cleaned;
47
+ }
48
+ finally {
49
+ this.activeSourceSessions.delete(sessionId);
50
+ this.cancelledSourceSessions.delete(sessionId);
51
+ }
52
+ }
53
+ async cancel(sessionId, bridge) {
54
+ this.cancelledSourceSessions.add(sessionId);
55
+ if (!this.titleSessionId || !this.activeSourceSessions.has(sessionId))
56
+ return;
57
+ await bridge.cancel(this.titleSessionId);
58
+ }
59
+ /** Ensure the dedicated title session exists. Returns session ID or null. */
60
+ async ensureTitleSession(bridge) {
61
+ if (this.titleSessionId)
62
+ return this.titleSessionId;
63
+ try {
64
+ const id = await bridge.newSession(this.defaultCwd, { silent: true });
65
+ this.sessions.liveSessions.add(id);
66
+ await bridge.setConfigOption(id, "model", TITLE_MODEL).catch(() => []);
67
+ this.titleSessionId = id;
68
+ return id;
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ }
package/lib/types.js ADDED
@@ -0,0 +1,13 @@
1
+ // --- Utility ---
2
+ export function errorMessage(err) {
3
+ if (err instanceof Error)
4
+ return err.message;
5
+ if (typeof err === "string")
6
+ return err;
7
+ try {
8
+ return JSON.stringify(err);
9
+ }
10
+ catch {
11
+ return String(err);
12
+ }
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lelouchhe/webagent",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "A terminal-style web UI for ACP-compatible agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,10 +30,11 @@
30
30
  "config.toml"
31
31
  ],
32
32
  "scripts": {
33
- "prepublishOnly": "npm run build",
33
+ "compile": "tsc -p tsconfig.build.json",
34
+ "prepublishOnly": "npm run compile && npm run build",
34
35
  "build": "node scripts/build.js",
35
36
  "start": "node --experimental-strip-types src/server.ts --config config.toml",
36
- "test": "npx tsc -p tsconfig.build.json && node --experimental-strip-types --test test/*.test.ts",
37
+ "test": "npm run compile && node --experimental-strip-types --test test/*.test.ts",
37
38
  "test:e2e": "playwright test",
38
39
  "dev": "node scripts/build.js --watch & node --experimental-strip-types --watch src/server.ts --config config.dev.toml",
39
40
  "dev:start": "node scripts/build.js --dev && node --experimental-strip-types src/server.ts --config config.dev.toml &",