accrete-kit 0.1.1 → 0.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 (69) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +9 -2
  3. package/dist/scaffold/assets/generated/release.json +1 -1
  4. package/dist/scaffold/manifest.json +2 -2
  5. package/dist/ui/LICENSE +21 -0
  6. package/dist/ui/THIRD-PARTY-NOTICES +212 -0
  7. package/dist/ui/bin/accrete-ui.mjs +46 -0
  8. package/dist/ui/page/app.js +49 -0
  9. package/dist/ui/page/index.html +17 -0
  10. package/dist/ui/page/panels/activity.css +80 -0
  11. package/dist/ui/page/panels/activity.js +85 -0
  12. package/dist/ui/page/panels/agents.css +61 -0
  13. package/dist/ui/page/panels/agents.js +173 -0
  14. package/dist/ui/page/panels/objects.css +155 -0
  15. package/dist/ui/page/panels/objects.js +309 -0
  16. package/dist/ui/page/panels/running.css +35 -0
  17. package/dist/ui/page/panels/running.js +159 -0
  18. package/dist/ui/page/style.css +86 -0
  19. package/dist/ui/page/terminal.js +88 -0
  20. package/dist/ui/server/agent-sessions.mjs +600 -0
  21. package/dist/ui/server/auth.mjs +29 -0
  22. package/dist/ui/server/deps.mjs +12 -0
  23. package/dist/ui/server/documents.mjs +285 -0
  24. package/dist/ui/server/events.mjs +18 -0
  25. package/dist/ui/server/processes.mjs +110 -0
  26. package/dist/ui/server/readers/activity.mjs +134 -0
  27. package/dist/ui/server/readers/agents.mjs +45 -0
  28. package/dist/ui/server/readers/objects.mjs +261 -0
  29. package/dist/ui/server/readers/running.mjs +245 -0
  30. package/dist/ui/server/scope.mjs +36 -0
  31. package/dist/ui/server/server.mjs +156 -0
  32. package/dist/ui/server/terminal.mjs +134 -0
  33. package/dist/ui/server/workspace.mjs +26 -0
  34. package/dist/ui/ui.json +3 -0
  35. package/dist/ui/vendor/@xterm/addon-fit/lib/addon-fit.mjs +18 -0
  36. package/dist/ui/vendor/@xterm/addon-unicode11/lib/addon-unicode11.mjs +44 -0
  37. package/dist/ui/vendor/@xterm/addon-webgl/lib/addon-webgl.mjs +101 -0
  38. package/dist/ui/vendor/@xterm/xterm/css/xterm.css +285 -0
  39. package/dist/ui/vendor/@xterm/xterm/lib/xterm.mjs +53 -0
  40. package/dist/ui/vendor/node-pty/lib/eventEmitter2.js +47 -0
  41. package/dist/ui/vendor/node-pty/lib/index.js +52 -0
  42. package/dist/ui/vendor/node-pty/lib/interfaces.js +7 -0
  43. package/dist/ui/vendor/node-pty/lib/terminal.js +190 -0
  44. package/dist/ui/vendor/node-pty/lib/types.js +7 -0
  45. package/dist/ui/vendor/node-pty/lib/unixTerminal.js +346 -0
  46. package/dist/ui/vendor/node-pty/lib/utils.js +39 -0
  47. package/dist/ui/vendor/node-pty/package.json +64 -0
  48. package/dist/ui/vendor/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
  49. package/dist/ui/vendor/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
  50. package/dist/ui/vendor/node-pty/prebuilds/darwin-x64/pty.node +0 -0
  51. package/dist/ui/vendor/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
  52. package/dist/ui/vendor/ws/index.js +22 -0
  53. package/dist/ui/vendor/ws/lib/buffer-util.js +142 -0
  54. package/dist/ui/vendor/ws/lib/constants.js +19 -0
  55. package/dist/ui/vendor/ws/lib/event-target.js +292 -0
  56. package/dist/ui/vendor/ws/lib/extension.js +203 -0
  57. package/dist/ui/vendor/ws/lib/limiter.js +55 -0
  58. package/dist/ui/vendor/ws/lib/permessage-deflate.js +530 -0
  59. package/dist/ui/vendor/ws/lib/receiver.js +743 -0
  60. package/dist/ui/vendor/ws/lib/sender.js +610 -0
  61. package/dist/ui/vendor/ws/lib/stream.js +161 -0
  62. package/dist/ui/vendor/ws/lib/subprotocol.js +62 -0
  63. package/dist/ui/vendor/ws/lib/validation.js +152 -0
  64. package/dist/ui/vendor/ws/lib/websocket-server.js +562 -0
  65. package/dist/ui/vendor/ws/lib/websocket.js +1426 -0
  66. package/dist/ui/vendor/ws/package.json +74 -0
  67. package/lib/cli.mjs +22 -4
  68. package/lib/ui.mjs +24 -0
  69. package/package.json +5 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 — 2026-11-04
4
+
5
+ - `npx accrete-kit@latest ui` runs the local web page for a Workspace, macOS only for now, with
6
+ `--project`, `--no-open`, `--no-tmux` and `--port`. `accrete-ui` stays its own repository and
7
+ ships inside this package, in `dist/ui/`, placed by `scripts/fetch-ui.mjs` from the GitHub
8
+ Release that `accrete.ui` and `accrete.uiRepo` name. The package still has no npm dependencies,
9
+ and a Workspace gains nothing from this.
10
+ - A release now needs the `accrete-ui` release to exist first, as it does the Kernel's.
11
+
3
12
  ## 0.1.1 — 2026-11-03
4
13
 
5
14
  First release published from GitHub Actions with npm trusted publishing and provenance.
package/README.md CHANGED
@@ -3,7 +3,8 @@
3
3
  Creates and upgrades ACCRETE Workspaces. This repository,
4
4
  `accrete-template`, publishes the npm package `accrete-kit`: the generator, five complete
5
5
  object Skills with their reference manuals, Coordinator and Subagent guidance,
6
- configuration examples, the command catalog, and the Kernel's release binaries.
6
+ configuration examples, the command catalog, the Kernel's release binaries, and a local web
7
+ page for watching a Workspace.
7
8
 
8
9
  A Workspace is an independent Git project owned by the user, not a fork kept in sync with
9
10
  this template. `accrete-kit` creates and maintains it, general-purpose coding agents work in it, and
@@ -18,8 +19,12 @@ npx accrete-kit@latest create .
18
19
  npx accrete-kit@latest upgrade
19
20
  npx accrete-kit@latest upgrade --dry-run
20
21
  npx accrete-kit@<version> install
22
+ npx accrete-kit@latest ui
21
23
  ```
22
24
 
25
+ `ui` serves a page with a real terminal and read-only panels for the Workspace, and stays in
26
+ the foreground until you stop it. It is macOS only for now.
27
+
23
28
  ## What the Agent receives
24
29
 
25
30
  | Skill | Practical scope |
@@ -125,6 +130,7 @@ replacing a Kernel or refreshing guidance does not silently migrate scientific w
125
130
  | `schemas/` | JSON Schemas for the source definition and scaffold manifest |
126
131
  | `scripts/build.mjs` | Assembles `dist/scaffold/` and checks the sources |
127
132
  | `scripts/fetch-kernel.mjs` | Places the declared Kernel release in `dist/kernel/`, verified against `SHA256SUMS` |
133
+ | `scripts/fetch-ui.mjs` | Places the declared `accrete-ui` release in `dist/ui/`, verified against `SHA256SUMS` |
128
134
  | `scripts/check-cli-contract.mjs` | Checks the catalog against a Kernel binary's `--help` |
129
135
  | `.github/workflows/` | CI, and a tag-triggered release with trusted publishing |
130
136
  | `docs/` | The generator, scaffold format, architecture rationale, and maintenance |
@@ -146,4 +152,5 @@ Read [the generator](docs/CLI-INTEGRATION.md) for commands, the Kernel and recei
146
152
  [Build notes](docs/BUILD-REPORT.md) say what the build and tests cover.
147
153
 
148
154
  MIT licensed; see `LICENSE`. Each embedded Kernel keeps its own `LICENSE`,
149
- `THIRD-PARTY-NOTICES` and `licenses/` beside it in `dist/kernel/`.
155
+ `THIRD-PARTY-NOTICES` and `licenses/` beside it in `dist/kernel/`, and the UI keeps its own in
156
+ `dist/ui/`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "template_id": "accrete-foundation",
3
- "template_version": "0.1.1",
3
+ "template_version": "0.2.0",
4
4
  "kernel_version": "0.1.0",
5
5
  "cli_contract": "accrete-template-cli/v1",
6
6
  "project_formats": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "template_id": "accrete-foundation",
4
- "template_version": "0.1.1",
4
+ "template_version": "0.2.0",
5
5
  "kernel_version": "0.1.0",
6
6
  "cli_contract": "accrete-template-cli/v1",
7
7
  "project_formats": {
@@ -243,7 +243,7 @@
243
243
  "destination": ".accrete/release.json",
244
244
  "profile": null,
245
245
  "ownership": "managed-file",
246
- "sha256": "d70f4cb3506ebeb29d47b8886d8e65d497d9aa7ceba029e3bea6af0f5a8def9b",
246
+ "sha256": "28a76d560d9339691f9443070e112ba877a9d7f90a4e832ba1b8e322ca36bbd4",
247
247
  "size": 242
248
248
  },
249
249
  {
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ACCRETE contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,212 @@
1
+ accrete-ui 0.1.0 bundles the following under vendor/.
2
+
3
+ ========================================================================
4
+ @xterm/addon-fit 0.11.0 (MIT)
5
+ ========================================================================
6
+
7
+ Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in
17
+ all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ THE SOFTWARE.
26
+
27
+ ========================================================================
28
+ @xterm/addon-unicode11 0.9.0 (MIT)
29
+ ========================================================================
30
+
31
+ Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
32
+
33
+ Permission is hereby granted, free of charge, to any person obtaining a copy
34
+ of this software and associated documentation files (the "Software"), to deal
35
+ in the Software without restriction, including without limitation the rights
36
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37
+ copies of the Software, and to permit persons to whom the Software is
38
+ furnished to do so, subject to the following conditions:
39
+
40
+ The above copyright notice and this permission notice shall be included in
41
+ all copies or substantial portions of the Software.
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
49
+ THE SOFTWARE.
50
+
51
+ ========================================================================
52
+ @xterm/addon-webgl 0.19.0 (MIT)
53
+ ========================================================================
54
+
55
+ Copyright (c) 2018, The xterm.js authors (https://github.com/xtermjs/xterm.js)
56
+
57
+ Permission is hereby granted, free of charge, to any person obtaining a copy
58
+ of this software and associated documentation files (the "Software"), to deal
59
+ in the Software without restriction, including without limitation the rights
60
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
61
+ copies of the Software, and to permit persons to whom the Software is
62
+ furnished to do so, subject to the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be included in
65
+ all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
73
+ THE SOFTWARE.
74
+
75
+ ========================================================================
76
+ @xterm/xterm 6.0.0 (MIT)
77
+ ========================================================================
78
+
79
+ Copyright (c) 2017-2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
80
+ Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com)
81
+ Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/)
82
+
83
+ Permission is hereby granted, free of charge, to any person obtaining a copy
84
+ of this software and associated documentation files (the "Software"), to deal
85
+ in the Software without restriction, including without limitation the rights
86
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
87
+ copies of the Software, and to permit persons to whom the Software is
88
+ furnished to do so, subject to the following conditions:
89
+
90
+ The above copyright notice and this permission notice shall be included in
91
+ all copies or substantial portions of the Software.
92
+
93
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
94
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
95
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
96
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
97
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
98
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
99
+ THE SOFTWARE.
100
+
101
+ ========================================================================
102
+ node-pty 1.1.0 (MIT)
103
+ ========================================================================
104
+
105
+ Copyright (c) 2012-2015, Christopher Jeffrey (https://github.com/chjj/)
106
+
107
+ Permission is hereby granted, free of charge, to any person obtaining a copy
108
+ of this software and associated documentation files (the "Software"), to deal
109
+ in the Software without restriction, including without limitation the rights
110
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
111
+ copies of the Software, and to permit persons to whom the Software is
112
+ furnished to do so, subject to the following conditions:
113
+
114
+ The above copyright notice and this permission notice shall be included in
115
+ all copies or substantial portions of the Software.
116
+
117
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
118
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
119
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
120
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
121
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
122
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
123
+ THE SOFTWARE.
124
+
125
+
126
+
127
+ The MIT License (MIT)
128
+
129
+ Copyright (c) 2016, Daniel Imms (http://www.growingwiththeweb.com)
130
+
131
+ Permission is hereby granted, free of charge, to any person obtaining a copy
132
+ of this software and associated documentation files (the "Software"), to deal
133
+ in the Software without restriction, including without limitation the rights
134
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
135
+ copies of the Software, and to permit persons to whom the Software is
136
+ furnished to do so, subject to the following conditions:
137
+
138
+ The above copyright notice and this permission notice shall be included in all
139
+ copies or substantial portions of the Software.
140
+
141
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
142
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
143
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
144
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
145
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
146
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
147
+ SOFTWARE.
148
+
149
+
150
+
151
+ MIT License
152
+
153
+ Copyright (c) 2018 - present Microsoft Corporation
154
+
155
+ All rights reserved.
156
+
157
+ Permission is hereby granted, free of charge, to any person obtaining a copy
158
+ of this software and associated documentation files (the "Software"), to deal
159
+ in the Software without restriction, including without limitation the rights
160
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
161
+ copies of the Software, and to permit persons to whom the Software is
162
+ furnished to do so, subject to the following conditions:
163
+
164
+ The above copyright notice and this permission notice shall be included in all
165
+ copies or substantial portions of the Software.
166
+
167
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
169
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
170
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
172
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
173
+ SOFTWARE.
174
+
175
+ ========================================================================
176
+ ws 8.22.1 (MIT)
177
+ ========================================================================
178
+
179
+ Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
180
+ Copyright (c) 2013 Arnout Kazemier and contributors
181
+ Copyright (c) 2016 Luigi Pinca and contributors
182
+
183
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
184
+ this software and associated documentation files (the "Software"), to deal in
185
+ the Software without restriction, including without limitation the rights to
186
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
187
+ the Software, and to permit persons to whom the Software is furnished to do so,
188
+ subject to the following conditions:
189
+
190
+ The above copyright notice and this permission notice shall be included in all
191
+ copies or substantial portions of the Software.
192
+
193
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
194
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
195
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
196
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
197
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
198
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
199
+
200
+ ========================================================================
201
+ node-addon-api 7.1.1 (MIT), compiled into node-pty
202
+ ========================================================================
203
+
204
+ The MIT License (MIT)
205
+
206
+ Copyright (c) 2017 [Node.js API collaborators](https://github.com/nodejs/node-addon-api#collaborators)
207
+
208
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
209
+
210
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
211
+
212
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ import { execFile } from 'node:child_process';
3
+ import { existsSync } from 'node:fs';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { parseArgs } from 'node:util';
6
+ import { startServer } from '../server/server.mjs';
7
+
8
+ function fail(message) {
9
+ console.error(`accrete-ui: ${message}`);
10
+ process.exit(1);
11
+ }
12
+
13
+ let opts;
14
+ try {
15
+ ({ values: opts } = parseArgs({
16
+ options: {
17
+ project: { type: 'string' },
18
+ 'no-open': { type: 'boolean' },
19
+ 'no-tmux': { type: 'boolean' },
20
+ port: { type: 'string' },
21
+ },
22
+ }));
23
+ } catch (err) {
24
+ fail(`${err.message}\nusage: accrete-ui [--project PATH] [--no-open] [--no-tmux] [--port N]`);
25
+ }
26
+
27
+ function findWorkspace(from) {
28
+ for (let dir = resolve(from); ; dir = dirname(dir)) {
29
+ if (existsSync(join(dir, '.accrete/project.toml'))) return dir;
30
+ if (dir === dirname(dir)) return null;
31
+ }
32
+ }
33
+
34
+ const start = opts.project ?? process.cwd();
35
+ const root = findWorkspace(start);
36
+ if (!root) fail(`no ACCRETE Workspace at or above ${resolve(start)} (no .accrete/project.toml found)`);
37
+
38
+ const { url } = await startServer({
39
+ root,
40
+ port: Number(opts.port ?? 0),
41
+ tmux: !opts['no-tmux'],
42
+ tmuxSocket: process.env.ACCRETE_UI_TMUX_SOCKET,
43
+ }).catch((err) => fail(err.message));
44
+
45
+ console.log(url);
46
+ if (!opts['no-open']) execFile('open', [url]);
@@ -0,0 +1,49 @@
1
+ import { startTerminal } from '/terminal.js';
2
+
3
+ const PANELS = ['objects', 'activity', 'agents', 'running'];
4
+
5
+ if (location.hash) history.replaceState(null, '', '/');
6
+
7
+ startTerminal(document.getElementById('terminal'));
8
+
9
+ const tabs = document.getElementById('tabs');
10
+ const panels = document.getElementById('panels');
11
+
12
+ function select(name) {
13
+ for (const button of tabs.children) button.setAttribute('aria-selected', button.dataset.panel === name);
14
+ for (const section of panels.children) section.hidden = section.id !== `panel-${name}`;
15
+ }
16
+
17
+ const sections = PANELS.map((name) => {
18
+ const button = document.createElement('button');
19
+ button.role = 'tab';
20
+ button.dataset.panel = name;
21
+ button.textContent = name[0].toUpperCase() + name.slice(1);
22
+ button.onclick = () => select(name);
23
+ tabs.append(button);
24
+
25
+ const section = document.createElement('section');
26
+ section.id = `panel-${name}`;
27
+ panels.append(section);
28
+
29
+ const style = document.createElement('link');
30
+ style.rel = 'stylesheet';
31
+ style.href = `/panels/${name}.css`;
32
+ document.head.append(style);
33
+ return section;
34
+ });
35
+ select(PANELS[0]);
36
+
37
+ // Imported one by one so a broken panel leaves the others and the terminal running.
38
+ const modules = await Promise.allSettled(PANELS.map((name) => import(`/panels/${name}.js`)));
39
+
40
+ // Open the stream only now and mount in the same tick, so no panel misses the
41
+ // latest values the server replays on connect.
42
+ const events = new EventSource('/events');
43
+ events.addEventListener('workspace', (event) => {
44
+ document.title = `${JSON.parse(event.data).name} - accrete-ui`;
45
+ });
46
+ modules.forEach((result, i) => {
47
+ if (result.status === 'fulfilled') result.value.mount(sections[i], events);
48
+ else console.error(`panel ${PANELS[i]} failed to load`, result.reason);
49
+ });
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>accrete-ui</title>
6
+ <link rel="stylesheet" href="/vendor/xterm.css">
7
+ <link rel="stylesheet" href="/style.css">
8
+ </head>
9
+ <body>
10
+ <main id="terminal"></main>
11
+ <aside>
12
+ <nav id="tabs" role="tablist"></nav>
13
+ <div id="panels"></div>
14
+ </aside>
15
+ <script type="module" src="/app.js"></script>
16
+ </body>
17
+ </html>
@@ -0,0 +1,80 @@
1
+ /* Each panel scrolls itself, so moving between tabs keeps each one's place. */
2
+ #panels > #panel-activity {
3
+ height: 100%;
4
+ overflow: auto;
5
+ padding: 0;
6
+ }
7
+
8
+ #panel-activity .head {
9
+ position: sticky;
10
+ top: 0;
11
+ z-index: 1;
12
+ padding: 6px 12px 5px;
13
+ background: var(--bg);
14
+ border-bottom: 1px solid var(--border);
15
+ font-size: 12px;
16
+ }
17
+ #panel-activity .git { overflow-wrap: anywhere; }
18
+ #panel-activity .receipts {
19
+ margin: 3px 0;
20
+ padding-left: 8px;
21
+ border-left: 2px solid var(--accent);
22
+ overflow-wrap: anywhere;
23
+ }
24
+ #panel-activity .receipts:empty { display: none; }
25
+ #panel-activity .note {
26
+ color: var(--muted);
27
+ font-size: 11px;
28
+ }
29
+
30
+ #panel-activity .feed {
31
+ display: flex;
32
+ flex-direction: column;
33
+ padding: 6px 8px 0;
34
+ }
35
+ #panel-activity .item {
36
+ display: flex;
37
+ gap: 8px;
38
+ width: 100%;
39
+ padding: 2px 4px;
40
+ border: 0;
41
+ border-radius: 3px;
42
+ background: none;
43
+ color: var(--muted);
44
+ font: inherit;
45
+ font-size: 12px;
46
+ text-align: left;
47
+ }
48
+ #panel-activity .item.live { color: var(--fg); }
49
+ #panel-activity button.item { cursor: pointer; }
50
+ #panel-activity button.item:hover {
51
+ background: var(--bg-raised);
52
+ color: var(--fg);
53
+ }
54
+ #panel-activity .when {
55
+ flex: none;
56
+ min-width: 56px;
57
+ color: var(--muted);
58
+ font-variant-numeric: tabular-nums;
59
+ }
60
+ #panel-activity .what {
61
+ min-width: 0;
62
+ overflow-wrap: anywhere;
63
+ }
64
+ #panel-activity .detail { color: var(--muted); }
65
+ #panel-activity .empty {
66
+ padding: 4px;
67
+ color: var(--muted);
68
+ font-size: 12px;
69
+ }
70
+ #panel-activity .more {
71
+ margin: 4px 12px 16px;
72
+ padding: 2px 0;
73
+ border: 0;
74
+ background: none;
75
+ color: var(--accent);
76
+ font: inherit;
77
+ font-size: 12px;
78
+ cursor: pointer;
79
+ }
80
+ #panel-activity .more:hover { text-decoration: underline; }
@@ -0,0 +1,85 @@
1
+ // The activity panel: what was seen in documents, local state and Git, newest first.
2
+ // Workspace text is untrusted, so everything goes in through text nodes.
3
+ const PAGE = 100;
4
+
5
+ function h(tag, props, ...children) {
6
+ const node = Object.assign(document.createElement(tag), props);
7
+ node.append(...children.filter((child) => child !== null && child !== undefined));
8
+ return node;
9
+ }
10
+
11
+ function when(ms) {
12
+ const date = new Date(ms);
13
+ const time = date.toLocaleTimeString([], { hour12: false });
14
+ return date.toDateString() === new Date().toDateString() ? time : `${date.toLocaleDateString('en-CA')} ${time.slice(0, 5)}`;
15
+ }
16
+
17
+ function gitLine(git) {
18
+ if (!git) return 'Reading Git.';
19
+ if (!git.repo) return 'This Workspace is not in a Git repository.';
20
+ const tracking = git.upstream ? `${git.ahead} ahead, ${git.behind} behind ${git.upstream}` : 'no upstream';
21
+ const names = git.worktrees.map((worktree) => worktree.branch ?? 'detached').join(', ');
22
+ const worktrees = `${git.worktrees.length} worktree${git.worktrees.length === 1 ? '' : 's'}: ${names}`;
23
+ return [git.branch, tracking, `${git.dirty} changed or untracked`, worktrees].join(' · ');
24
+ }
25
+
26
+ function itemRow(item) {
27
+ const committed = item.committed_at && item.live && Math.abs(Date.parse(item.committed_at) - item.at) > 60000 ? `committed ${when(Date.parse(item.committed_at))}` : null;
28
+ const detail = [item.detail, committed].filter(Boolean).join(' · ');
29
+ const content = [
30
+ h('span', { className: 'when', textContent: when(item.at) }),
31
+ h('span', { className: 'what' }, item.text, detail ? h('span', { className: 'detail', textContent: ` · ${detail}` }) : null),
32
+ ];
33
+ const className = item.live ? 'item live' : 'item';
34
+ if (!item.open) return h('div', { className }, ...content);
35
+ return h(
36
+ 'button',
37
+ {
38
+ className,
39
+ onclick: () => document.dispatchEvent(new CustomEvent('accrete:open-object', { detail: { id: item.open } })),
40
+ },
41
+ ...content,
42
+ );
43
+ }
44
+
45
+ export function mount(el, events) {
46
+ const git = h('div', { className: 'git' });
47
+ const receipts = h('div', { className: 'receipts' });
48
+ const note = h('div', {
49
+ className: 'note',
50
+ textContent: 'What was seen in documents, local state and Git, not who did it. A refused Kernel call leaves no trace, so it does not appear.',
51
+ });
52
+ const feed = h('div', { className: 'feed' });
53
+ const more = h('button', { className: 'more' });
54
+ el.replaceChildren(h('div', { className: 'head' }, git, receipts, note), feed, more);
55
+
56
+ let state = null;
57
+ let shown = PAGE;
58
+
59
+ function renderFeed() {
60
+ const before = feed.offsetHeight;
61
+ feed.replaceChildren(...state.feed.slice(0, shown).map(itemRow));
62
+ if (!state.feed.length) feed.append(h('div', { className: 'empty', textContent: 'Nothing yet.' }));
63
+ // Someone reading further down keeps their place as new items arrive above.
64
+ if (el.scrollTop > 0) el.scrollTop += feed.offsetHeight - before;
65
+ const left = state.feed.length - shown;
66
+ more.hidden = left <= 0;
67
+ more.textContent = `${left} more`;
68
+ }
69
+
70
+ more.onclick = () => {
71
+ shown += PAGE;
72
+ renderFeed();
73
+ };
74
+
75
+ events.addEventListener('activity', (event) => {
76
+ state = JSON.parse(event.data);
77
+ git.textContent = gitLine(state.git);
78
+ git.title = (state.git?.worktrees ?? []).map((worktree) => worktree.path).join('\n');
79
+ const count = state.receipts.length;
80
+ receipts.textContent = count
81
+ ? `${count} receipt${count === 1 ? '' : 's'} in local state, so an operation is running or was interrupted: ${state.receipts.join(', ')}. .accrete/bin/accrete recover finishes an interrupted one.`
82
+ : '';
83
+ renderFeed();
84
+ });
85
+ }
@@ -0,0 +1,61 @@
1
+ /* Styles for the agents panel. Scope them under #panel-agents. */
2
+ #panel-agents .head { margin-bottom: 8px; }
3
+ #panel-agents .foot { margin-top: 12px; }
4
+ #panel-agents .quiet { color: var(--muted); }
5
+
6
+ #panel-agents .session {
7
+ padding: 8px 0;
8
+ border-top: 1px solid var(--border);
9
+ overflow-wrap: anywhere;
10
+ }
11
+ #panel-agents .row { display: block; }
12
+ #panel-agents .agent,
13
+ #panel-agents .kind {
14
+ color: var(--muted);
15
+ font-size: 12px;
16
+ }
17
+ #panel-agents .title { color: var(--muted); }
18
+ #panel-agents .has-process > .row > .title,
19
+ #panel-agents .subagent .title { color: var(--fg); }
20
+
21
+ #panel-agents .cwd,
22
+ #panel-agents .evidence {
23
+ color: var(--muted);
24
+ font-size: 12px;
25
+ }
26
+ #panel-agents .tool {
27
+ display: flex;
28
+ gap: 6px;
29
+ align-items: baseline;
30
+ min-width: 0;
31
+ font-size: 12px;
32
+ }
33
+ #panel-agents .tool-name { flex: none; color: var(--accent); }
34
+ #panel-agents .tool code {
35
+ flex: 0 1 auto;
36
+ min-width: 0;
37
+ overflow: hidden;
38
+ white-space: nowrap;
39
+ text-overflow: ellipsis;
40
+ font: 12px ui-monospace, Menlo, monospace;
41
+ }
42
+ #panel-agents .tool > .quiet { flex: none; white-space: nowrap; }
43
+
44
+ #panel-agents .subagents { margin-top: 4px; }
45
+ #panel-agents .subagents > summary {
46
+ color: var(--muted);
47
+ font-size: 12px;
48
+ cursor: pointer;
49
+ }
50
+ #panel-agents .subagent {
51
+ margin: 4px 0 0 4px;
52
+ padding-left: 8px;
53
+ border-left: 1px solid var(--border);
54
+ }
55
+ #panel-agents .unattached {
56
+ padding: 8px 0;
57
+ border-top: 1px solid var(--border);
58
+ color: var(--muted);
59
+ font-size: 12px;
60
+ overflow-wrap: anywhere;
61
+ }