viberoom 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/NOTICE +12 -0
  2. package/README.md +123 -96
  3. package/dist/fsbrowse.js +65 -0
  4. package/dist/hub.js +18 -0
  5. package/dist/launcher.js +22 -0
  6. package/dist/main.js +4 -3
  7. package/dist/persona.js +1 -1
  8. package/dist/recipes.js +37 -14
  9. package/dist/room.js +3 -2
  10. package/dist/server.js +30 -0
  11. package/package.json +8 -5
  12. package/scripts/vendor-acp.mjs +85 -0
  13. package/ui/app.css +53 -1
  14. package/ui/app.js +360 -8
  15. package/ui/index.html +28 -1
  16. package/vendor/acp/claude-agent-acp/LICENSE +191 -0
  17. package/vendor/acp/claude-agent-acp/dist/acp-agent.js +7694 -0
  18. package/vendor/acp/claude-agent-acp/dist/acp-subagents.js +13 -0
  19. package/vendor/acp/claude-agent-acp/dist/air-extension.js +63 -0
  20. package/vendor/acp/claude-agent-acp/dist/async-tasks.js +613 -0
  21. package/vendor/acp/claude-agent-acp/dist/clear-context-coordinator.js +80 -0
  22. package/vendor/acp/claude-agent-acp/dist/elicitation.js +304 -0
  23. package/vendor/acp/claude-agent-acp/dist/exit-plan.js +154 -0
  24. package/vendor/acp/claude-agent-acp/dist/file-change-audit.js +350 -0
  25. package/vendor/acp/claude-agent-acp/dist/fork-session.js +41 -0
  26. package/vendor/acp/claude-agent-acp/dist/goal-extension.js +50 -0
  27. package/vendor/acp/claude-agent-acp/dist/index.js +98 -0
  28. package/vendor/acp/claude-agent-acp/dist/lib.js +5 -0
  29. package/vendor/acp/claude-agent-acp/dist/native-subagents.js +422 -0
  30. package/vendor/acp/claude-agent-acp/dist/permissions/effects.js +166 -0
  31. package/vendor/acp/claude-agent-acp/dist/permissions/modes.js +41 -0
  32. package/vendor/acp/claude-agent-acp/dist/permissions/normalization.js +100 -0
  33. package/vendor/acp/claude-agent-acp/dist/permissions/options/filesystem.js +124 -0
  34. package/vendor/acp/claude-agent-acp/dist/permissions/options/shared.js +64 -0
  35. package/vendor/acp/claude-agent-acp/dist/permissions/options/shell.js +100 -0
  36. package/vendor/acp/claude-agent-acp/dist/permissions/options/tools.js +135 -0
  37. package/vendor/acp/claude-agent-acp/dist/permissions/options.js +60 -0
  38. package/vendor/acp/claude-agent-acp/dist/permissions/presentation.js +83 -0
  39. package/vendor/acp/claude-agent-acp/dist/permissions/response.js +19 -0
  40. package/vendor/acp/claude-agent-acp/dist/session-config-ids.js +4 -0
  41. package/vendor/acp/claude-agent-acp/dist/session-failure-extension.js +324 -0
  42. package/vendor/acp/claude-agent-acp/dist/session-mode.js +234 -0
  43. package/vendor/acp/claude-agent-acp/dist/session-titles.js +199 -0
  44. package/vendor/acp/claude-agent-acp/dist/settings.js +185 -0
  45. package/vendor/acp/claude-agent-acp/dist/tool-result-meta.js +19 -0
  46. package/vendor/acp/claude-agent-acp/dist/tools.js +1235 -0
  47. package/vendor/acp/claude-agent-acp/dist/utils.js +81 -0
  48. package/vendor/acp/claude-agent-acp/package.json +7 -0
  49. package/vendor/acp/claude-agent-sdk/LICENSE.md +1 -0
  50. package/vendor/acp/claude-agent-sdk/agentSdkTypes.d.ts +1 -0
  51. package/vendor/acp/claude-agent-sdk/bridge.d.ts +378 -0
  52. package/vendor/acp/claude-agent-sdk/bridge.mjs +221 -0
  53. package/vendor/acp/claude-agent-sdk/browser-sdk.d.ts +107 -0
  54. package/vendor/acp/claude-agent-sdk/browser-sdk.js +185 -0
  55. package/vendor/acp/claude-agent-sdk/extractFromBunfs.d.ts +1 -0
  56. package/vendor/acp/claude-agent-sdk/extractFromBunfs.js +156 -0
  57. package/vendor/acp/claude-agent-sdk/manifest.json +65 -0
  58. package/vendor/acp/claude-agent-sdk/manifest.zst.json +73 -0
  59. package/vendor/acp/claude-agent-sdk/package.json +7 -0
  60. package/vendor/acp/claude-agent-sdk/sdk-tools.d.ts +4129 -0
  61. package/vendor/acp/claude-agent-sdk/sdk.d.ts +8687 -0
  62. package/vendor/acp/claude-agent-sdk/sdk.mjs +204 -0
  63. package/vendor/acp/codex-acp/LICENSE +190 -0
  64. package/vendor/acp/codex-acp/dist/index.js +34238 -0
  65. package/vendor/acp/codex-acp/package.json +7 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viberoom",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "viberoom: group chat rooms for a human and several coding agents over the Agent Client Protocol",
5
5
  "type": "module",
6
6
  "engines": {
@@ -10,7 +10,7 @@
10
10
  "viberoom": "dist/main.js"
11
11
  },
12
12
  "scripts": {
13
- "build": "tsc -p tsconfig.json",
13
+ "build": "node scripts/vendor-acp.mjs && tsc -p tsconfig.json",
14
14
  "typecheck": "tsc -p tsconfig.json --noEmit",
15
15
  "start": "node dist/main.js",
16
16
  "dev": "npm run build && node dist/main.js --open",
@@ -22,18 +22,21 @@
22
22
  },
23
23
  "files": [
24
24
  "dist",
25
+ "vendor",
25
26
  "ui",
26
27
  "assets",
27
28
  "scripts",
28
29
  "NOTICE"
29
30
  ],
30
31
  "dependencies": {
31
- "@agentclientprotocol/claude-agent-acp": "0.73.0",
32
- "@agentclientprotocol/codex-acp": "^1.8.0",
32
+ "@agentclientprotocol/sdk": "1.4.0",
33
33
  "marked": "^16.4.2",
34
- "mermaid": "^11.17.2"
34
+ "mermaid": "^11.17.2",
35
+ "zod": "^4.0.0"
35
36
  },
36
37
  "devDependencies": {
38
+ "@agentclientprotocol/claude-agent-acp": "0.73.0",
39
+ "@agentclientprotocol/codex-acp": "1.8.0",
37
40
  "@types/node": "^24.0.0",
38
41
  "typescript": "^5.9.0"
39
42
  },
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ // viberoom - Copyright (c) 2026 Todor Rusev - AGPL-3.0-or-later; see LICENSE
3
+
4
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
5
+ import { dirname, join, relative, sep } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const root = join(dirname(fileURLToPath(import.meta.url)), "..");
9
+ const out = join(root, "vendor", "acp");
10
+ function packageDir(name) {
11
+ const dir = join(root, "node_modules", name);
12
+ if (!existsSync(join(dir, "package.json"))) throw new Error(`${name} is not installed; run npm install first`);
13
+ return dir;
14
+ }
15
+ const readJson = (path) => JSON.parse(readFileSync(path, "utf8"));
16
+
17
+ function writeManifest(dir, pkg) {
18
+ const kept = { name: pkg.name, version: pkg.version, type: pkg.type, license: pkg.license, main: pkg.main };
19
+ writeFileSync(join(dir, "package.json"), JSON.stringify(kept, null, 2) + "\n");
20
+ }
21
+
22
+ function copyLicence(from, to) {
23
+ for (const name of ["LICENSE", "LICENSE.md", "LICENSE.txt"]) {
24
+ if (existsSync(join(from, name))) cpSync(join(from, name), join(to, name));
25
+ }
26
+ }
27
+
28
+ function jsFiles(dir) {
29
+ const files = [];
30
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
31
+ const path = join(dir, entry.name);
32
+ if (entry.isDirectory()) files.push(...jsFiles(path));
33
+ else if (entry.name.endsWith(".js") || entry.name.endsWith(".mjs")) files.push(path);
34
+ }
35
+ return files;
36
+ }
37
+
38
+ rmSync(out, { recursive: true, force: true });
39
+
40
+ {
41
+ const from = packageDir("@agentclientprotocol/codex-acp");
42
+ const to = join(out, "codex-acp");
43
+ mkdirSync(join(to, "dist"), { recursive: true });
44
+ cpSync(join(from, "dist", "index.js"), join(to, "dist", "index.js"));
45
+ writeManifest(to, readJson(join(from, "package.json")));
46
+ copyLicence(from, to);
47
+ }
48
+
49
+ {
50
+ const sdkFrom = packageDir("@anthropic-ai/claude-agent-sdk");
51
+ const sdkTo = join(out, "claude-agent-sdk");
52
+ const sdkPkg = readJson(join(sdkFrom, "package.json"));
53
+ mkdirSync(sdkTo, { recursive: true });
54
+ for (const file of sdkPkg.files ?? []) {
55
+ if (existsSync(join(sdkFrom, file))) cpSync(join(sdkFrom, file), join(sdkTo, file), { recursive: true });
56
+ }
57
+ writeManifest(sdkTo, sdkPkg);
58
+ copyLicence(sdkFrom, sdkTo);
59
+
60
+ const from = packageDir("@agentclientprotocol/claude-agent-acp");
61
+ const to = join(out, "claude-agent-acp");
62
+ mkdirSync(to, { recursive: true });
63
+ cpSync(join(from, "dist"), join(to, "dist"), {
64
+ recursive: true,
65
+ filter: (src) => statSync(src).isDirectory() || src.endsWith(".js"),
66
+ });
67
+ writeManifest(to, readJson(join(from, "package.json")));
68
+ copyLicence(from, to);
69
+
70
+ const sdkEntry = join(sdkTo, "sdk.mjs");
71
+ let rewritten = 0;
72
+ for (const file of jsFiles(join(to, "dist"))) {
73
+ let rel = relative(dirname(file), sdkEntry).split(sep).join("/");
74
+ if (!rel.startsWith(".")) rel = "./" + rel;
75
+ const before = readFileSync(file, "utf8");
76
+ const after = before.replace(/(["'])@anthropic-ai\/claude-agent-sdk\1/g, `$1${rel}$1`);
77
+ if (after !== before) {
78
+ writeFileSync(file, after);
79
+ rewritten += 1;
80
+ }
81
+ }
82
+ console.log(`vendored claude-agent-acp ${readJson(join(to, "package.json")).version} (${rewritten} files point at the vendored SDK ${sdkPkg.version})`);
83
+ }
84
+
85
+ console.log(`vendored codex-acp ${readJson(join(out, "codex-acp", "package.json")).version}`);
package/ui/app.css CHANGED
@@ -177,7 +177,7 @@
177
177
  .chat-sub .dir-chip { cursor: help; }
178
178
  .chat-actions { display: flex; align-items: center; gap: 8px; }
179
179
  .chat-actions .search { margin: 0; width: 250px; }
180
- .messages { flex: 1; overflow-y: auto; padding: 12px 22px; display: flex; flex-direction: column; gap: 14px; background: var(--canvas-pattern) content-box, var(--grad-canvas); background-size: var(--canvas-pattern-size), auto; }
180
+ .messages { position: relative; flex: 1; overflow-y: auto; padding: 12px 22px; display: flex; flex-direction: column; gap: 14px; background: var(--canvas-pattern) content-box, var(--grad-canvas); background-size: var(--canvas-pattern-size), auto; }
181
181
  .day { align-self: center; color: var(--faint); font-size: 11px; font-weight: 800; padding: 3px 12px; margin: 2px 0; }
182
182
  .msg { display: flex; gap: 12px; align-items: flex-start; max-width: 100%; animation: bubble-in var(--t-base) var(--ease-out); }
183
183
  .msg.agent { padding-right: 64px; }
@@ -188,6 +188,24 @@
188
188
  .sys.warn { color: var(--warm-ink); background: var(--warm); border-radius: var(--r-pill); padding: 6px 12px; font-weight: 800; }
189
189
  .bubble-col { display: flex; flex-direction: column; gap: 6px; min-width: 0; max-width: min(1040px, 100%); }
190
190
  .msg.mine .bubble-col { align-items: flex-end; }
191
+ .shell.side-collapsed .bubble-col { max-width: min(1480px, 100%); }
192
+ .timeline { position: absolute; right: 6px; top: 78px; bottom: 96px; width: 18px; z-index: 4; }
193
+ .tl-ticks { position: absolute; inset: 0; }
194
+ .tl-view { position: absolute; left: 2px; right: 2px; border-radius: 6px; background: rgba(91, 91, 240, 0.07); pointer-events: none; transition: top 80ms linear, height 80ms linear; }
195
+ .tl-tick { position: absolute; left: 3px; width: 12px; height: 5px; border-radius: 3px; background: #cdcdf9; cursor: pointer; transition: background var(--t-fast), transform var(--t-fast); }
196
+ .tl-tick:hover, .tl-tick.active { background: var(--primary); transform: scaleX(1.25); }
197
+ .tl-tick.in-view { background: #a9a9f5; }
198
+ .tl-pop { position: absolute; right: 26px; width: 340px; background: var(--card); border-radius: 14px; box-shadow: var(--shadow-pop); padding: 6px; z-index: 30; animation: rise var(--t-base) var(--ease-out); }
199
+ .tl-row { padding: 6px 10px; border-radius: 9px; font-size: 12.5px; font-weight: 600; line-height: 1.4; color: var(--ink-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; cursor: pointer; }
200
+ .tl-row.faded { color: var(--muted); opacity: 0.8; }
201
+ .tl-row.far { opacity: 0.5; }
202
+ .tl-row.current { background: var(--lav); color: var(--primary); font-weight: 800; }
203
+ .tl-row:hover { background: var(--lav-2); }
204
+ .msg.flash .bubble { animation: tl-flash 1.4s var(--ease-out); }
205
+ @keyframes tl-flash { 0% { box-shadow: 0 0 0 0 rgba(91, 91, 240, 0.55); } 100% { box-shadow: 0 0 0 14px rgba(91, 91, 240, 0); } }
206
+ .jump-latest { position: absolute; right: 30px; bottom: 96px; z-index: 5; display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px 0 10px; border: 0; border-radius: var(--r-pill); background: var(--card); color: var(--primary); font: inherit; font-size: 12px; font-weight: 800; box-shadow: var(--shadow-pop); cursor: pointer; animation: rise var(--t-base) var(--ease-out); }
207
+ .jump-latest:hover { background: var(--soft); }
208
+ .jump-latest svg { width: 16px; height: 16px; }
191
209
  .bubble { max-width: 100%; background: #fff; border-radius: 6px 18px 18px 18px; padding: 12px 16px; min-width: 0; font-size: 14.5px; font-weight: 600; line-height: 1.55; color: var(--ink-2); box-shadow: 0 2px 0 rgba(28, 27, 51, 0.06), 0 1px 3px rgba(28, 27, 51, 0.04); }
192
210
  .msg.mine .bubble { background: var(--grad-primary); color: #fff; border-radius: 18px 18px 6px 18px; box-shadow: 0 8px 18px -10px rgba(91, 91, 240, 0.7); padding: 11px 16px; }
193
211
  .msg.mine .bubble .text { color: #fff; }
@@ -219,6 +237,37 @@
219
237
  .msg.mine .bubble .text th { background: rgba(255, 255, 255, 0.18); }
220
238
  .msg.mine .bubble .text th, .msg.mine .bubble .text td { border-color: rgba(255, 255, 255, 0.35); }
221
239
  .msg.mine .bubble .text blockquote { border-color: rgba(255, 255, 255, 0.5); color: rgba(255, 255, 255, 0.85); }
240
+ .dir-row { display: flex; gap: 8px; align-items: stretch; }
241
+ .dir-row input { flex: 1; min-width: 0; }
242
+ .dir-row .browse-btn { flex: 0 0 auto; white-space: nowrap; }
243
+ .folder-dialog { width: 760px; height: min(80vh, 720px); flex-direction: column; }
244
+ .folder-dialog[open] { display: flex; }
245
+ .folder-dialog .file-head { flex: 0 0 auto; }
246
+ .fp-bar { display: flex; gap: 8px; align-items: stretch; margin: 6px 0 8px; }
247
+ .fp-bar input { flex: 1; min-width: 0; font-family: var(--mono); font-size: 12.5px; }
248
+ .fp-bar .btn { white-space: nowrap; }
249
+ .fp-recent { display: flex; flex-wrap: wrap; gap: 6px; min-height: 0; margin-bottom: 8px; }
250
+ .fp-recent:empty { display: none; }
251
+ .fp-recent .chip-btn { max-width: 260px; }
252
+ .fp-body { flex: 1; min-height: 0; overflow: auto; border: 2px solid var(--lav); border-radius: var(--r-sm); background: var(--soft); padding: 6px 4px; }
253
+ .tree, .tree ul { list-style: none; margin: 0; padding: 0; }
254
+ .tree ul { padding-left: 18px; }
255
+ .tree li { margin: 0; }
256
+ .tn { display: flex; align-items: center; gap: 4px; height: 30px; padding: 0 8px 0 2px; border-radius: 8px; cursor: pointer; font-size: 13.5px; font-weight: 700; color: var(--ink-2); white-space: nowrap; user-select: none; }
257
+ .tn:hover { background: var(--lav); }
258
+ .tn.selected { background: var(--lav-2); color: var(--primary); }
259
+ .tn.hidden-dir { color: var(--muted); font-weight: 600; }
260
+ .tn-tw { flex: 0 0 18px; width: 18px; height: 18px; border: 0; background: transparent; color: var(--muted); padding: 0; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; border-radius: 5px; transition: transform var(--t-fast); }
261
+ .tn-tw svg { width: 14px; height: 14px; }
262
+ .tn-tw:hover { background: var(--card); color: var(--primary); }
263
+ .tn.open .tn-tw { transform: rotate(90deg); }
264
+ .tn.leaf .tn-tw { visibility: hidden; }
265
+ .tn-ico { flex: 0 0 auto; font-size: 15px; line-height: 1; }
266
+ .tn-name { overflow: hidden; text-overflow: ellipsis; }
267
+ .tn-more { color: var(--faint); font-size: 12px; font-weight: 700; padding: 4px 26px; }
268
+ .tn-new { display: flex; gap: 6px; align-items: center; padding: 2px 0 4px 26px; }
269
+ .tn-new input { height: 28px; font-size: 13px; padding: 0 10px; }
270
+ .fp-selected { flex: 1; min-width: 0; font-family: var(--mono); font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; align-self: center; }
222
271
  .file-dialog { width: 900px; flex-direction: column; }
223
272
  .file-dialog[open] { display: flex; }
224
273
  .file-dialog .file-head { flex: 0 0 auto; }
@@ -326,6 +375,9 @@ table.csv tbody tr:nth-child(even) td { background: rgba(91, 91, 240, 0.03); }
326
375
  .resizer { position: absolute; left: -14px; top: 0; bottom: 0; width: 20px; cursor: col-resize; z-index: 3; }
327
376
  .resizer::after { content: ""; position: absolute; left: 8.5px; top: 44%; height: 12%; width: 3px; border-radius: 3px; background: var(--lav-2); opacity: 0; transition: opacity var(--t-fast); }
328
377
  .resizer:hover::after, .shell.resizing .resizer::after { opacity: 1; }
378
+ .details-handle { position: absolute; left: 0; bottom: 18%; z-index: 4; width: 20px; height: 64px; padding: 0; border: 0; border-radius: 0 12px 12px 0; background: #d6d8fb; color: var(--primary); display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 2px 8px -2px rgba(91, 91, 240, 0.45); transition: background var(--t-fast), color var(--t-fast); }
379
+ .details-handle:hover { background: var(--primary); color: #fff; }
380
+ .details-handle svg { width: 16px; height: 16px; }
329
381
  .panel-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 14px; }
330
382
  .panel-title h3 { font-size: 11px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
331
383
  .panel-title .hint { display: none; }